diff --git a/.changeset/mean-seals-nail.md b/.changeset/mean-seals-nail.md new file mode 100644 index 0000000000..7ac373d827 --- /dev/null +++ b/.changeset/mean-seals-nail.md @@ -0,0 +1,25 @@ +--- +"@latticexyz/world": patch +"@latticexyz/store": patch +--- + +The `ResourceType` table is removed. +It was previously used to store the resource type for each resource ID in a `World`. This is no longer necessary as the [resource type is now encoded in the resource ID](https://github.com/latticexyz/mud/pull/1544). + +To still be able to determine whether a given resource ID exists, a `ResourceIds` table has been added. +The previous `ResourceType` table was part of `World` and missed tables that were registered directly via `StoreCore.registerTable` instead of via `World.registerTable` (e.g. when a table was registered as part of a root module). +This problem is solved by the new table `ResourceIds` being part of `Store`. + +`StoreCore`'s `hasTable` function was removed in favor of using `ResourceIds.getExists(tableId)` directly. + +```diff +- import { ResourceType } from "@latticexyz/world/src/tables/ResourceType.sol"; +- import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; ++ import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol"; + +- bool tableExists = StoreCore.hasTable(tableId); ++ bool tableExists = ResourceIds.getExists(tableId); + +- bool systemExists = ResourceType.get(systemId) != Resource.NONE; ++ bool systemExists = ResourceIds.getExists(systemId); +``` diff --git a/.changeset/real-students-exercise.md b/.changeset/real-students-exercise.md new file mode 100644 index 0000000000..25ac8a1a75 --- /dev/null +++ b/.changeset/real-students-exercise.md @@ -0,0 +1,25 @@ +--- +"@latticexyz/world": major +--- + +All `World` methods acting on namespaces as resources have been updated to use `ResourceId namespaceId` as parameter instead of `bytes14 namespace`. +The reason for this change is to make it clearer when a namespace is used as resource, as opposed to being part of another resource's ID. + +```diff ++ import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + +IBaseWorld { +- function registerNamespace(bytes14 namespace) external; ++ function registerNamespace(ResourceId namespaceId) external; + +- function transferOwnership(bytes14 namespace, address newOwner) external; ++ function transferOwnership(ResourceId namespaceId, address newOwner) external; + +- function transferBalanceToNamespace(bytes14 fromNamespace, bytes14 toNamespace, uint256 amount) external; ++ function transferBalanceToNamespace(ResourceId fromNamespaceId, ResourceId toNamespaceId, uint256 amount) external; + +- function transferBalanceToAddress(bytes14 fromNamespace, address toAddress, uint256 amount) external; ++ function transferBalanceToAddress(ResourceId fromNamespaceId, address toAddress, uint256 amount) external; +} + +``` diff --git a/.changeset/stale-seahorses-pay.md b/.changeset/stale-seahorses-pay.md new file mode 100644 index 0000000000..8bd942565b --- /dev/null +++ b/.changeset/stale-seahorses-pay.md @@ -0,0 +1,70 @@ +--- +"@latticexyz/cli": major +"@latticexyz/common": major +"@latticexyz/config": major +"@latticexyz/store": major +--- + +- `ResourceSelector` is replaced with `ResourceId`, `ResourceIdLib`, `ResourceIdInstance`, `WorldResourceIdLib` and `WorldResourceIdInstance`. + + Previously a "resource selector" was a `bytes32` value with the first 16 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + Now a "resource ID" is a `bytes32` value with the first 2 bytes reserved for the resource type, the next 14 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + + Previously `ResouceSelector` was a library and the resource selector type was a plain `bytes32`. + Now `ResourceId` is a user type, and the functionality is implemented in the `ResourceIdInstance` (for type) and `WorldResourceIdInstance` (for namespace and name) libraries. + We split the logic into two libraries, because `Store` now also uses `ResourceId` and needs to be aware of resource types, but not of namespaces/names. + + ```diff + - import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol"; + + import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; + + import { WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol"; + + import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol"; + + - bytes32 systemId = ResourceSelector.from("namespace", "name"); + + ResourceId systemId = WorldResourceIdLib.encode(RESOURCE_SYSTEM, "namespace", "name"); + + - using ResourceSelector for bytes32; + + using WorldResourceIdInstance for ResourceId; + + using ResourceIdInstance for ResourceId; + + systemId.getName(); + systemId.getNamespace(); + + systemId.getType(); + + ``` + +- All `Store` and `World` methods now use the `ResourceId` type for `tableId`, `systemId`, `moduleId` and `namespaceId`. + All mentions of `resourceSelector` were renamed to `resourceId` or the more specific type (e.g. `tableId`, `systemId`) + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IStore { + function setRecord( + - bytes32 tableId, + + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + FieldLayout fieldLayout + ) external; + + // Same for all other methods + } + ``` + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IBaseWorld { + function callFrom( + address delegator, + - bytes32 resourceSelector, + + ResourceId systemId, + bytes memory callData + ) external payable returns (bytes memory); + + // Same for all other methods + } + ``` diff --git a/.prettierignore b/.prettierignore index 6ec0121e9d..d36102008d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ dist -**/.next +.next templates/phaser/packages/art CODEOWNERS +out diff --git a/e2e/packages/contracts/src/codegen/tables/Multi.sol b/e2e/packages/contracts/src/codegen/tables/Multi.sol index abab8c9590..b3674887f3 100644 --- a/e2e/packages/contracts/src/codegen/tables/Multi.sol +++ b/e2e/packages/contracts/src/codegen/tables/Multi.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Multi"))); -bytes32 constant MultiTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Multi"))) +); +ResourceId constant MultiTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0021020020010000000000000000000000000000000000000000000000000000 diff --git a/e2e/packages/contracts/src/codegen/tables/Number.sol b/e2e/packages/contracts/src/codegen/tables/Number.sol index 246f60517d..db8e380f8b 100644 --- a/e2e/packages/contracts/src/codegen/tables/Number.sol +++ b/e2e/packages/contracts/src/codegen/tables/Number.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Number"))); -bytes32 constant NumberTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Number"))) +); +ResourceId constant NumberTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0004010004000000000000000000000000000000000000000000000000000000 diff --git a/e2e/packages/contracts/src/codegen/tables/NumberList.sol b/e2e/packages/contracts/src/codegen/tables/NumberList.sol index 4f0a11dccc..17d4e49daa 100644 --- a/e2e/packages/contracts/src/codegen/tables/NumberList.sol +++ b/e2e/packages/contracts/src/codegen/tables/NumberList.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("NumberList"))); -bytes32 constant NumberListTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("NumberList"))) +); +ResourceId constant NumberListTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 diff --git a/e2e/packages/contracts/src/codegen/tables/Vector.sol b/e2e/packages/contracts/src/codegen/tables/Vector.sol index ee5dd92631..8fca7ea7bb 100644 --- a/e2e/packages/contracts/src/codegen/tables/Vector.sol +++ b/e2e/packages/contracts/src/codegen/tables/Vector.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Vector"))); -bytes32 constant VectorTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Vector"))) +); +ResourceId constant VectorTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0008020004040000000000000000000000000000000000000000000000000000 diff --git a/e2e/packages/sync-test/data/setContractData.ts b/e2e/packages/sync-test/data/setContractData.ts index 323189d95c..be886c0d07 100644 --- a/e2e/packages/sync-test/data/setContractData.ts +++ b/e2e/packages/sync-test/data/setContractData.ts @@ -2,7 +2,7 @@ import { Page } from "@playwright/test"; import { Data } from "./types"; import { encodeTestData } from "./encodeTestData"; import { callWorld } from "./callWorld"; -import { tableIdToHex } from "@latticexyz/common"; +import { resourceIdToHex } from "@latticexyz/common"; /** * Writes contract data by calling `world.setRecord` via the client @@ -14,7 +14,7 @@ export async function setContractData(page: Page, data: Data) { for (const record of records) { const promise = await callWorld(page, "setRecord", [ // TODO: add support for multiple namespaces after https://github.com/latticexyz/mud/issues/994 is resolved - tableIdToHex("", table), + resourceIdToHex({ type: "table", namespace: "", name: table }), record.key, record.staticData, record.encodedLengths, diff --git a/examples/minimal/packages/contracts/script/PostDeploy.s.sol b/examples/minimal/packages/contracts/script/PostDeploy.s.sol index 059758821e..06e875346c 100644 --- a/examples/minimal/packages/contracts/script/PostDeploy.s.sol +++ b/examples/minimal/packages/contracts/script/PostDeploy.s.sol @@ -3,7 +3,8 @@ pragma solidity >=0.8.0; import { Script } from "forge-std/Script.sol"; import { console } from "forge-std/console.sol"; -import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol"; +import { ResourceId, WorldResourceIdLib } from "@latticexyz/world/src/WorldResourceId.sol"; +import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol"; import { IWorld } from "../src/codegen/world/IWorld.sol"; import { MessageTable, MessageTableTableId } from "../src/codegen/index.sol"; @@ -19,16 +20,13 @@ contract PostDeploy is Script { // Manually deploy a system with another namespace ChatNamespacedSystem chatNamespacedSystem = new ChatNamespacedSystem(); - IWorld(worldAddress).registerSystem( - ResourceSelector.from("namespace", "ChatNamespaced"), - chatNamespacedSystem, - true - ); - IWorld(worldAddress).registerFunctionSelector( - ResourceSelector.from("namespace", "ChatNamespaced"), - "sendMessage", - "(string)" - ); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "ChatNamespaced" + }); + IWorld(worldAddress).registerSystem(systemId, chatNamespacedSystem, true); + IWorld(worldAddress).registerFunctionSelector(systemId, "sendMessage", "(string)"); // Grant this system access to MessageTable IWorld(worldAddress).grantAccess(MessageTableTableId, address(chatNamespacedSystem)); diff --git a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol index 0eee6c3ff4..fccaf9550e 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("CounterTable"))); -bytes32 constant CounterTableTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("CounterTable"))) +); +ResourceId constant CounterTableTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0004010004000000000000000000000000000000000000000000000000000000 diff --git a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol index 7156ea2c10..046b2889d6 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Inventory"))); -bytes32 constant InventoryTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Inventory"))) +); +ResourceId constant InventoryTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0004010004000000000000000000000000000000000000000000000000000000 diff --git a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol index 48d6426ca7..872bdf5b51 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("MessageTable"))); -bytes32 constant MessageTableTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("MessageTable"))) +); +ResourceId constant MessageTableTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol index e2482100cd..76852f049e 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Dynamics1"))); -bytes32 constant Dynamics1TableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Dynamics1"))) +); +ResourceId constant Dynamics1TableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000500000000000000000000000000000000000000000000000000000000 diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol index c587e088ea..5001ff4efb 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Dynamics2"))); -bytes32 constant Dynamics2TableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Dynamics2"))) +); +ResourceId constant Dynamics2TableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000300000000000000000000000000000000000000000000000000000000 diff --git a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol b/packages/cli/contracts/src/codegen/tables/Ephemeral.sol index dae46bfb71..b2edf7c856 100644 --- a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol +++ b/packages/cli/contracts/src/codegen/tables/Ephemeral.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Ephemeral"))); -bytes32 constant EphemeralTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Ephemeral"))) +); +ResourceId constant EphemeralTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0020010020000000000000000000000000000000000000000000000000000000 diff --git a/packages/cli/contracts/src/codegen/tables/Singleton.sol b/packages/cli/contracts/src/codegen/tables/Singleton.sol index 5d8d466a6c..45d77b5356 100644 --- a/packages/cli/contracts/src/codegen/tables/Singleton.sol +++ b/packages/cli/contracts/src/codegen/tables/Singleton.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Singleton"))); -bytes32 constant SingletonTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Singleton"))) +); +ResourceId constant SingletonTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0020010320000000000000000000000000000000000000000000000000000000 diff --git a/packages/cli/contracts/src/codegen/tables/Statics.sol b/packages/cli/contracts/src/codegen/tables/Statics.sol index 8a911d7d46..961208a783 100644 --- a/packages/cli/contracts/src/codegen/tables/Statics.sol +++ b/packages/cli/contracts/src/codegen/tables/Statics.sol @@ -17,12 +17,16 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; // Import user types import { Enum2, Enum1 } from "./../common.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Statics"))); -bytes32 constant StaticsTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Statics"))) +); +ResourceId constant StaticsTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x004a060020041014010100000000000000000000000000000000000000000000 diff --git a/packages/cli/src/commands/trace.ts b/packages/cli/src/commands/trace.ts index 32ea227735..faca38ed3f 100644 --- a/packages/cli/src/commands/trace.ts +++ b/packages/cli/src/commands/trace.ts @@ -9,12 +9,16 @@ import { StoreConfig } from "@latticexyz/store"; import { resolveWorldConfig, WorldConfig } from "@latticexyz/world"; import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json" assert { type: "json" }; import worldConfig from "@latticexyz/world/mud.config.js"; -import { tableIdToHex } from "@latticexyz/common"; +import { resourceIdToHex } from "@latticexyz/common"; import { getExistingContracts } from "../utils/getExistingContracts"; import { getChainId } from "../utils/utils/getChainId"; // TODO account for multiple namespaces (https://github.com/latticexyz/mud/issues/994) -const systemsTableId = tableIdToHex(worldConfig.namespace, worldConfig.tables.Systems.name); +const systemsTableId = resourceIdToHex({ + type: "system", + namespace: worldConfig.namespace, + name: worldConfig.tables.Systems.name, +}); type Options = { tx: string; @@ -76,7 +80,7 @@ const commandModule: CommandModule = { const systemTableFieldLayout = await WorldContract.getFieldLayout(systemsTableId); const labels: { name: string; address: string }[] = []; for (const name of names) { - const systemSelector = tableIdToHex(namespace, name); + const systemSelector = resourceIdToHex({ type: "system", namespace, name }); // Get the first field of `Systems` table (the table maps system name to its address and other data) const address = await WorldContract.getField(systemsTableId, [systemSelector], 0, systemTableFieldLayout); labels.push({ name, address }); diff --git a/packages/cli/src/utils/systems/getGrantAccessCallData.ts b/packages/cli/src/utils/systems/getGrantAccessCallData.ts index f9cd39a1b5..e5d50b84ad 100644 --- a/packages/cli/src/utils/systems/getGrantAccessCallData.ts +++ b/packages/cli/src/utils/systems/getGrantAccessCallData.ts @@ -1,6 +1,6 @@ import { System } from "./types"; import { CallData } from "../utils/types"; -import { tableIdToHex } from "@latticexyz/common"; +import { resourceIdToHex } from "@latticexyz/common"; export async function getGrantAccessCallData(input: { systems: System[]; @@ -24,6 +24,6 @@ export async function getGrantAccessCallData(input: { function getGrantSystemAccessCallData(name: string, namespace: string, address: string): CallData { return { func: "grantAccess", - args: [tableIdToHex(namespace, name), address], + args: [resourceIdToHex({ type: "system", namespace, name }), address], }; } diff --git a/packages/cli/src/utils/systems/getRegisterFunctionSelectorsCallData.ts b/packages/cli/src/utils/systems/getRegisterFunctionSelectorsCallData.ts index 23545868fd..0af36fec4d 100644 --- a/packages/cli/src/utils/systems/getRegisterFunctionSelectorsCallData.ts +++ b/packages/cli/src/utils/systems/getRegisterFunctionSelectorsCallData.ts @@ -1,4 +1,4 @@ -import { tableIdToHex } from "@latticexyz/common"; +import { resourceIdToHex } from "@latticexyz/common"; import { System } from "./types"; import { loadFunctionSignatures, toFunctionSelector } from "./utils"; import { CallData } from "../utils/types"; @@ -57,12 +57,12 @@ function getRegisterFunctionSelectorCallData(input: { const systemFunctionSelector = toFunctionSelector({ functionName, functionArgs }); return { func: "registerRootFunctionSelector", - args: [tableIdToHex(namespace, name), worldFunctionSelector, systemFunctionSelector], + args: [resourceIdToHex({ type: "system", namespace, name }), worldFunctionSelector, systemFunctionSelector], }; } else { return { func: "registerRootFunctionSelector", - args: [tableIdToHex(namespace, name), functionName, functionArgs], + args: [resourceIdToHex({ type: "system", namespace, name }), functionName, functionArgs], }; } } diff --git a/packages/cli/src/utils/systems/getRegisterSystemCallData.ts b/packages/cli/src/utils/systems/getRegisterSystemCallData.ts index fa2d1c0e20..66243170f3 100644 --- a/packages/cli/src/utils/systems/getRegisterSystemCallData.ts +++ b/packages/cli/src/utils/systems/getRegisterSystemCallData.ts @@ -1,4 +1,4 @@ -import { tableIdToHex } from "@latticexyz/common"; +import { resourceIdToHex } from "@latticexyz/common"; import { System } from "./types"; import { CallData } from "../utils/types"; @@ -12,6 +12,6 @@ export async function getRegisterSystemCallData(input: { const systemAddress = await systemContracts[systemName]; return { func: "registerSystem", - args: [tableIdToHex(namespace, system.name), systemAddress, system.openAccess], + args: [resourceIdToHex({ type: "system", namespace, name: system.name }), systemAddress, system.openAccess], }; } diff --git a/packages/cli/src/utils/tables/getRegisterTableCallData.ts b/packages/cli/src/utils/tables/getRegisterTableCallData.ts index 7b2f80fda6..8db6cc0c43 100644 --- a/packages/cli/src/utils/tables/getRegisterTableCallData.ts +++ b/packages/cli/src/utils/tables/getRegisterTableCallData.ts @@ -1,7 +1,7 @@ import { encodeSchema, getStaticByteLength } from "@latticexyz/schema-type/deprecated"; import { StoreConfig } from "@latticexyz/store"; import { resolveAbiOrUserType } from "@latticexyz/store/codegen"; -import { tableIdToHex } from "@latticexyz/common"; +import { resourceIdToHex } from "@latticexyz/common"; import { Table } from "./types"; import { fieldLayoutToHex } from "@latticexyz/protocol-parser"; import { CallData } from "../utils/types"; @@ -29,7 +29,8 @@ export function getRegisterTableCallData(table: Table, storeConfig: StoreConfig) return { func: "registerTable", args: [ - tableIdToHex(storeConfig.namespace, name), + // TODO: add support for table namespaces (https://github.com/latticexyz/mud/issues/994) + resourceIdToHex({ type: table.ephemeral ? "offchainTable" : "table", namespace: storeConfig.namespace, name }), fieldLayoutToHex(fieldLayout), encodeSchema(keyTypes), encodeSchema(schemaTypes), diff --git a/packages/common/src/codegen/render-solidity/common.ts b/packages/common/src/codegen/render-solidity/common.ts index 1a7a95ebec..c88829706e 100644 --- a/packages/common/src/codegen/render-solidity/common.ts +++ b/packages/common/src/codegen/render-solidity/common.ts @@ -44,7 +44,7 @@ export function renderCommonData({ } { // static resource means static tableId as well, and no tableId arguments const _tableId = staticResourceData ? "" : "_tableId"; - const _typedTableId = staticResourceData ? "" : "bytes32 _tableId"; + const _typedTableId = staticResourceData ? "" : "ResourceId _tableId"; const _keyArgs = renderArguments(keyTuple.map(({ name }) => name)); const _typedKeyArgs = renderArguments(keyTuple.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`)); @@ -166,11 +166,11 @@ export function renderTableId(staticResourceData: StaticResourceData): { hardcodedTableId: string; tableIdDefinition: string; } { - const hardcodedTableId = `bytes32(abi.encodePacked(bytes16("${staticResourceData.namespace}"), bytes16("${staticResourceData.name}")))`; + const hardcodedTableId = `ResourceId.wrap(bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("${staticResourceData.namespace}"), bytes16("${staticResourceData.name}"))))`; const tableIdDefinition = ` - bytes32 constant _tableId = ${hardcodedTableId}; - bytes32 constant ${staticResourceData.tableIdName} = _tableId; + ResourceId constant _tableId = ${hardcodedTableId}; + ResourceId constant ${staticResourceData.tableIdName} = _tableId; `; return { hardcodedTableId, diff --git a/packages/common/src/common.ts b/packages/common/src/common.ts new file mode 100644 index 0000000000..dd2cdf3162 --- /dev/null +++ b/packages/common/src/common.ts @@ -0,0 +1,7 @@ +import { ResourceType } from "./resourceTypes"; + +export type ResourceId = { + namespace: string; + name: string; + type: ResourceType; +}; diff --git a/packages/common/src/hexToResourceId.test.ts b/packages/common/src/hexToResourceId.test.ts new file mode 100644 index 0000000000..56ebfecfdb --- /dev/null +++ b/packages/common/src/hexToResourceId.test.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from "vitest"; +import { hexToResourceId } from "./hexToResourceId"; + +describe("hexToResourceId", () => { + it("can convert from hex string", () => { + const resourceId = hexToResourceId("0x74626e616d65737061636500000000006e616d65000000000000000000000000"); + expect(resourceId.type).toMatchInlineSnapshot('"table"'); + expect(resourceId.namespace).toMatchInlineSnapshot('"namespace"'); + expect(resourceId.name).toMatchInlineSnapshot('"name"'); + }); +}); diff --git a/packages/common/src/hexToResourceId.ts b/packages/common/src/hexToResourceId.ts new file mode 100644 index 0000000000..2f45ac2c17 --- /dev/null +++ b/packages/common/src/hexToResourceId.ts @@ -0,0 +1,30 @@ +import { Hex, hexToString, sliceHex } from "viem"; +import { ResourceId } from "./common"; +import { ResourceType, resourceTypes } from "./resourceTypes"; +import { resourceTypeIds } from "./resourceIdToHex"; +import { ReverseMap } from "./type-utils/common"; + +const resourceTypeIdToType = Object.fromEntries( + Object.entries(resourceTypeIds).map(([key, value]) => [value, key]) +) as ReverseMap; + +function getResourceType(resourceTypeId: string): ResourceType | undefined { + // TODO: replace Partial with `noUncheckedIndexedAccess` + const type = (resourceTypeIdToType as Partial>)[resourceTypeId]; + if (resourceTypes.includes(type as ResourceType)) { + return type; + } +} + +export function hexToResourceId(hex: Hex): ResourceId { + const resourceTypeId = hexToString(sliceHex(hex, 0, 2)).replace(/\0+$/, ""); + const type = getResourceType(resourceTypeId); + const namespace = hexToString(sliceHex(hex, 2, 16)).replace(/\0+$/, ""); + const name = hexToString(sliceHex(hex, 16, 32)).replace(/\0+$/, ""); + + if (!type) { + throw new Error(`Unknown resource type: ${resourceTypeId}`); + } + + return { type, namespace, name }; +} diff --git a/packages/common/src/hexToTableId.test.ts b/packages/common/src/hexToTableId.test.ts deleted file mode 100644 index 20a43c95b0..0000000000 --- a/packages/common/src/hexToTableId.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { describe, it, expect } from "vitest"; -import { hexToTableId } from "./hexToTableId"; - -describe("hexToTableId", () => { - it("can convert from hex string", () => { - const tableId = hexToTableId("0x6e616d657370616365000000000000006e616d65000000000000000000000000"); - expect(tableId.namespace).toMatchInlineSnapshot('"namespace"'); - expect(tableId.name).toMatchInlineSnapshot('"name"'); - }); -}); diff --git a/packages/common/src/hexToTableId.ts b/packages/common/src/hexToTableId.ts deleted file mode 100644 index 8782630888..0000000000 --- a/packages/common/src/hexToTableId.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Hex, hexToString, sliceHex } from "viem"; - -export function hexToTableId(hex: Hex): { namespace: string; name: string } { - const namespace = hexToString(sliceHex(hex, 0, 16)).replace(/\0+$/, ""); - const name = hexToString(sliceHex(hex, 16, 32)).replace(/\0+$/, ""); - return { namespace, name }; -} diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index d6a59390fa..a15afa9877 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1,9 +1,11 @@ +export * from "./common"; export * from "./createBurnerAccount"; export * from "./createContract"; export * from "./createNonceManager"; export * from "./getBurnerPrivateKey"; -export * from "./hexToTableId"; +export * from "./hexToResourceId"; export * from "./readHex"; +export * from "./resourceIdToHex"; +export * from "./resourceTypes"; export * from "./spliceHex"; -export * from "./tableIdToHex"; export * from "./transportObserver"; diff --git a/packages/common/src/resourceIdToHex.test.ts b/packages/common/src/resourceIdToHex.test.ts new file mode 100644 index 0000000000..d8a1ca026d --- /dev/null +++ b/packages/common/src/resourceIdToHex.test.ts @@ -0,0 +1,69 @@ +import { describe, it, expect } from "vitest"; +import { resourceIdToHex } from "./resourceIdToHex"; +import { hexToResourceId } from "./hexToResourceId"; + +describe("resourceIdToHex", () => { + it("can convert table resource to hex string", () => { + const hex = resourceIdToHex({ + type: "table", + namespace: "namespace", + name: "name", + }); + expect(hex).toMatchInlineSnapshot('"0x74626e616d65737061636500000000006e616d65000000000000000000000000"'); + expect(hexToResourceId(hex)).toMatchInlineSnapshot(` + { + "name": "name", + "namespace": "namespace", + "type": "table", + } + `); + }); + + it("can convert offchain table resource to hex string", () => { + const hex = resourceIdToHex({ + type: "offchainTable", + namespace: "namespace", + name: "name", + }); + expect(hex).toMatchInlineSnapshot('"0x6f746e616d65737061636500000000006e616d65000000000000000000000000"'); + expect(hexToResourceId(hex)).toMatchInlineSnapshot(` + { + "name": "name", + "namespace": "namespace", + "type": "offchainTable", + } + `); + }); + + it("truncates namespaces >14 bytes", () => { + const hex = resourceIdToHex({ + type: "table", + namespace: "AVeryLongNamespace", + name: "name", + }); + expect(hex).toMatchInlineSnapshot('"0x746241566572794c6f6e674e616d65736e616d65000000000000000000000000"'); + expect(hexToResourceId(hex)).toMatchInlineSnapshot(` + { + "name": "name", + "namespace": "AVeryLongNames", + "type": "table", + } + `); + }); + + it("truncates names >16 bytes", () => { + const hex = resourceIdToHex({ + type: "table", + namespace: "namespace", + name: "AnUnnecessarilyLongName", + }); + expect(hex).toMatchInlineSnapshot('"0x74626e616d6573706163650000000000416e556e6e65636573736172696c794c"'); + expect(hexToResourceId(hex)).toMatchInlineSnapshot(` + { + "name": "AnUnnecessarilyL", + "namespace": "namespace", + "type": "table", + } + `); + }); +}); diff --git a/packages/common/src/resourceIdToHex.ts b/packages/common/src/resourceIdToHex.ts new file mode 100644 index 0000000000..bebe682aec --- /dev/null +++ b/packages/common/src/resourceIdToHex.ts @@ -0,0 +1,23 @@ +import { Hex, stringToHex, concatHex } from "viem"; +import { ResourceId } from "./common"; +import { ResourceType } from "./resourceTypes"; + +/** @internal */ +export const resourceTypeIds = { + // keep these in sync with storeResourceTypes.sol + table: "tb", + offchainTable: "ot", + // keep these in sync with worldResourceTypes.sol + namespace: "ns", + module: "md", + system: "sy", +} as const satisfies Record; + +export function resourceIdToHex(resourceId: ResourceId): Hex { + const typeId = resourceTypeIds[resourceId.type]; + return concatHex([ + stringToHex(typeId, { size: 2 }), + stringToHex(resourceId.namespace.slice(0, 14), { size: 14 }), + stringToHex(resourceId.name.slice(0, 16), { size: 16 }), + ]); +} diff --git a/packages/common/src/resourceTypes.ts b/packages/common/src/resourceTypes.ts new file mode 100644 index 0000000000..eff7931236 --- /dev/null +++ b/packages/common/src/resourceTypes.ts @@ -0,0 +1,3 @@ +export const resourceTypes = ["table", "offchainTable", "namespace", "module", "system"] as const; + +export type ResourceType = (typeof resourceTypes)[number]; diff --git a/packages/common/src/tableIdToHex.test.ts b/packages/common/src/tableIdToHex.test.ts deleted file mode 100644 index 97fdf9476c..0000000000 --- a/packages/common/src/tableIdToHex.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { describe, it, expect } from "vitest"; -import { tableIdToHex } from "./tableIdToHex"; -import { hexToTableId } from "./hexToTableId"; - -describe("tableIdToHex", () => { - it("can convert to hex string", () => { - const tableIdHex = tableIdToHex("namespace", "name"); - expect(tableIdHex).toMatchInlineSnapshot('"0x6e616d657370616365000000000000006e616d65000000000000000000000000"'); - }); - - it("truncates namespaces >16 bytes", () => { - const hex = "0x41566572794c6f6e674e616d657370616e616d65000000000000000000000000"; - const tableIdHex = tableIdToHex("AVeryLongNamespace", "name"); - expect(tableIdHex).toEqual(hex); - expect(hexToTableId(tableIdHex).namespace).toMatchInlineSnapshot('"AVeryLongNamespa"'); - }); - - it("truncates names >16 bytes", () => { - const hex = "0x6e616d65737061636500000000000000416e556e6e65636573736172696c794c"; - const tableIdHex = tableIdToHex("namespace", "AnUnnecessarilyLongName"); - expect(tableIdHex).toEqual(hex); - expect(hexToTableId(tableIdHex).name).toMatchInlineSnapshot('"AnUnnecessarilyL"'); - }); -}); diff --git a/packages/common/src/tableIdToHex.ts b/packages/common/src/tableIdToHex.ts deleted file mode 100644 index f3cddef064..0000000000 --- a/packages/common/src/tableIdToHex.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Hex, stringToHex, concatHex } from "viem"; - -// TODO: rename to `resourceIdToHex` or `resourceSelectorToHex` since it can be used with other resources than tables -export function tableIdToHex(namespace: string, name: string): Hex { - return concatHex([ - stringToHex(namespace.substring(0, 16), { size: 16 }), - stringToHex(name.substring(0, 16), { size: 16 }), - ]); -} diff --git a/packages/common/src/type-utils/common.ts b/packages/common/src/type-utils/common.ts index e75f5054dc..7694b42c28 100644 --- a/packages/common/src/type-utils/common.ts +++ b/packages/common/src/type-utils/common.ts @@ -21,3 +21,8 @@ export type OrDefaults = { export type UnionOmit = T extends any ? Omit : never; export type UnionKeys = T extends any ? keyof T : never; export type UnionPick> = T extends any ? Pick> : never; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type ReverseMap> = { + [K in keyof T as T[K]]: K; +}; diff --git a/packages/config/src/library/commonSchemas.ts b/packages/config/src/library/commonSchemas.ts index 72ba06da1e..63409583ab 100644 --- a/packages/config/src/library/commonSchemas.ts +++ b/packages/config/src/library/commonSchemas.ts @@ -8,7 +8,7 @@ import { validateRoute, validateSingleLevelRoute, validateUncapitalizedName, - validateSelector, + validateNamespace, } from "./validation"; /** Capitalized names of objects, like tables and systems */ @@ -16,7 +16,10 @@ export const zObjectName = z.string().superRefine(validateCapitalizedName); /** Uncapitalized names of values, like keys and columns */ export const zValueName = z.string().superRefine(validateUncapitalizedName); /** Name that can start with any case */ -export const zAnyCaseName = z.string().superRefine(validateName); +export const zName = z.string().superRefine(validateName); +/** A namespace */ +export const zNamespace = z.string().superRefine(validateNamespace); + /** List of unique enum member names and 0 < length < 256 */ export const zUserEnum = z.array(zObjectName).superRefine(validateEnum); @@ -29,6 +32,3 @@ export const zBaseRoute = z.string().superRefine(validateBaseRoute); /** A valid Ethereum address */ export const zEthereumAddress = z.string().superRefine(validateEthereumAddress); - -/** A selector for namespace/file/resource */ -export const zSelector = z.string().superRefine(validateSelector); diff --git a/packages/config/src/library/validation.ts b/packages/config/src/library/validation.ts index 125187fa85..37609efac1 100644 --- a/packages/config/src/library/validation.ts +++ b/packages/config/src/library/validation.ts @@ -1,7 +1,8 @@ import { utils } from "ethers"; import { ZodIssueCode, RefinementCtx } from "zod"; -export const STORE_SELECTOR_MAX_LENGTH = 16; +export const STORE_NAME_MAX_LENGTH = 16; +export const STORE_NAMESPACE_MAX_LENGTH = 14; export function validateName(name: string, ctx: RefinementCtx) { if (!/^\w+$/.test(name)) { @@ -139,11 +140,11 @@ export function getDuplicates(array: T[]) { return [...duplicates]; } -export function validateSelector(name: string, ctx: RefinementCtx) { - if (name.length > STORE_SELECTOR_MAX_LENGTH) { +export function validateNamespace(name: string, ctx: RefinementCtx) { + if (name.length > STORE_NAMESPACE_MAX_LENGTH) { ctx.addIssue({ code: ZodIssueCode.custom, - message: `Selector must be <= ${STORE_SELECTOR_MAX_LENGTH} characters`, + message: `Namespace must be <= ${STORE_NAMESPACE_MAX_LENGTH} characters`, }); } if (!/^\w*$/.test(name)) { diff --git a/packages/dev-tools/src/actions/WriteSummary.tsx b/packages/dev-tools/src/actions/WriteSummary.tsx index 42aee498ec..6c65b9550f 100644 --- a/packages/dev-tools/src/actions/WriteSummary.tsx +++ b/packages/dev-tools/src/actions/WriteSummary.tsx @@ -9,7 +9,7 @@ import { getTransaction } from "./getTransaction"; import { getTransactionReceipt } from "./getTransactionReceipt"; import { getTransactionResult } from "./getTransactionResult"; import { ErrorTrace } from "../ErrorTrace"; -import { ContractWrite, hexToTableId } from "@latticexyz/common"; +import { ContractWrite, hexToResourceId } from "@latticexyz/common"; import { useDevToolsContext } from "../DevToolsContext"; import { hexKeyTupleToEntity } from "@latticexyz/store-sync/recs"; @@ -145,7 +145,7 @@ export function WriteSummary({ write }: Props) { {events.map(({ eventName, args }, i) => { - const table = hexToTableId((args as any).tableId); + const table = hexToResourceId((args as any).tableId); // TODO: dedupe this with logs table so we can get both rendering the same return ( diff --git a/packages/dev-tools/src/events/LogsTable.tsx b/packages/dev-tools/src/events/LogsTable.tsx index ac4779fb2b..5c720f1a62 100644 --- a/packages/dev-tools/src/events/LogsTable.tsx +++ b/packages/dev-tools/src/events/LogsTable.tsx @@ -1,6 +1,6 @@ import { StorageAdapterLog } from "@latticexyz/store-sync"; import { EventIcon } from "./EventIcon"; -import { hexToTableId } from "@latticexyz/common"; +import { hexToResourceId } from "@latticexyz/common"; // TODO: use react-table or similar for better perf with lots of logs @@ -22,7 +22,7 @@ export function LogsTable({ logs }: Props) { {logs.map((log) => { - const { namespace, name } = hexToTableId(log.args.tableId); + const { namespace, name } = hexToResourceId(log.args.tableId); return ( Promise; // TODO: adjust when we get namespace support (https://github.com/latticexyz/mud/issues/994) and when table has namespace key (https://github.com/latticexyz/mud/issues/1201) export const schemasTable = storeConfig.tables.Tables; -export const schemasTableId = tableIdToHex(storeConfig.namespace, schemasTable.name); +export const schemasTableId = resourceIdToHex({ + type: schemasTable.ephemeral ? "offchainTable" : "table", + namespace: storeConfig.namespace, + name: schemasTable.name, +}); diff --git a/packages/store-sync/src/logToTable.test.ts b/packages/store-sync/src/logToTable.test.ts index 53ec2a6a5e..1812ebb67f 100644 --- a/packages/store-sync/src/logToTable.test.ts +++ b/packages/store-sync/src/logToTable.test.ts @@ -8,8 +8,8 @@ describe("logToTable", () => { address: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", eventName: "StoreSetRecord", args: { - tableId: "0x6d756473746f726500000000000000005461626c657300000000000000000000", - keyTuple: ["0x6d756473746f726500000000000000005461626c657300000000000000000000"], + tableId: "0x74626d756473746f72650000000000005461626c657300000000000000000000", + keyTuple: ["0x74626d756473746f72650000000000005461626c657300000000000000000000"], staticData: "0x0060030220202000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000006003025f5f5fc4c40000000000000000000000000000000000000000000000", encodedLengths: "0x000000000000000000000000000000000000022000000000a0000000000002c0", // "0x00000000000000000000000000000000000000a00000000220000000000002c0", @@ -25,7 +25,7 @@ describe("logToTable", () => { }, "name": "Tables", "namespace": "mudstore", - "tableId": "0x6d756473746f726500000000000000005461626c657300000000000000000000", + "tableId": "0x74626d756473746f72650000000000005461626c657300000000000000000000", "valueSchema": { "abiEncodedFieldNames": "bytes", "abiEncodedKeyNames": "bytes", diff --git a/packages/store-sync/src/logToTable.ts b/packages/store-sync/src/logToTable.ts index 72f7f01d47..14d5b3ff75 100644 --- a/packages/store-sync/src/logToTable.ts +++ b/packages/store-sync/src/logToTable.ts @@ -1,7 +1,7 @@ import { hexToSchema, decodeValue } from "@latticexyz/protocol-parser"; import { concatHex, decodeAbiParameters, parseAbiParameters } from "viem"; import { StorageAdapterLog, Table, schemasTable } from "./common"; -import { hexToTableId } from "@latticexyz/common"; +import { hexToResourceId } from "@latticexyz/common"; // TODO: add tableToLog @@ -11,7 +11,7 @@ export function logToTable(log: StorageAdapterLog & { eventName: "StoreSetRecord console.warn("registerSchema event is expected to have only one key in key tuple, but got multiple", log); } - const table = hexToTableId(tableId); + const table = hexToResourceId(tableId); const value = decodeValue( schemasTable.valueSchema, diff --git a/packages/store-sync/src/postgres/buildInternalTables.ts b/packages/store-sync/src/postgres/buildInternalTables.ts index 08a4fd8b80..bd0b7372e0 100644 --- a/packages/store-sync/src/postgres/buildInternalTables.ts +++ b/packages/store-sync/src/postgres/buildInternalTables.ts @@ -1,6 +1,6 @@ import { integer, pgSchema, text } from "drizzle-orm/pg-core"; import { transformSchemaName } from "./transformSchemaName"; -import { asAddress, asBigInt, asJson, asNumber } from "./columnTypes"; +import { asAddress, asBigInt, asHex, asJson, asNumber } from "./columnTypes"; import { KeySchema, ValueSchema } from "@latticexyz/protocol-parser"; // eslint-disable-next-line @typescript-eslint/explicit-function-return-type @@ -19,7 +19,7 @@ export function buildInternalTables() { schemaVersion: integer("schema_version").primaryKey(), key: text("key").notNull().primaryKey(), address: asAddress("address").notNull(), - tableId: text("table_id").notNull(), + tableId: asHex("table_id").notNull(), namespace: text("namespace").notNull(), name: text("name").notNull(), keySchema: asJson("key_schema").notNull(), diff --git a/packages/store-sync/src/postgres/getTableKey.ts b/packages/store-sync/src/postgres/getTableKey.ts index 3c58cae80e..e27ce16b58 100644 --- a/packages/store-sync/src/postgres/getTableKey.ts +++ b/packages/store-sync/src/postgres/getTableKey.ts @@ -1,8 +1,8 @@ import { getAddress } from "viem"; import { Table } from "../common"; -import { hexToTableId } from "@latticexyz/common"; +import { hexToResourceId } from "@latticexyz/common"; export function getTableKey({ address, tableId }: Pick): string { - const { namespace, name } = hexToTableId(tableId); + const { namespace, name } = hexToResourceId(tableId); return `${getAddress(address)}:${namespace}:${name}`; } diff --git a/packages/store-sync/src/postgres/getTables.ts b/packages/store-sync/src/postgres/getTables.ts index c88919c54d..b3ea2ce5e4 100644 --- a/packages/store-sync/src/postgres/getTables.ts +++ b/packages/store-sync/src/postgres/getTables.ts @@ -2,7 +2,6 @@ import { PgDatabase } from "drizzle-orm/pg-core"; import { inArray } from "drizzle-orm"; import { Table } from "../common"; import { buildInternalTables } from "./buildInternalTables"; -import { tableIdToHex } from "@latticexyz/common"; export async function getTables(db: PgDatabase, keys: string[] = []): Promise { const internalTables = buildInternalTables(); @@ -12,13 +11,5 @@ export async function getTables(db: PgDatabase, keys: string[] = []): Promi .from(internalTables.tables) .where(keys.length ? inArray(internalTables.tables.key, [...new Set(keys)]) : undefined); - return tables.map((table) => ({ - address: table.address, - tableId: tableIdToHex(table.namespace, table.name), - namespace: table.namespace, - name: table.name, - keySchema: table.keySchema, - valueSchema: table.valueSchema, - lastUpdatedBlockNumber: table.lastUpdatedBlockNumber, - })); + return tables; } diff --git a/packages/store-sync/src/postgres/postgresStorage.test.ts b/packages/store-sync/src/postgres/postgresStorage.test.ts index 8aa0548082..f717c07ea8 100644 --- a/packages/store-sync/src/postgres/postgresStorage.test.ts +++ b/packages/store-sync/src/postgres/postgresStorage.test.ts @@ -78,7 +78,7 @@ describe("postgresStorage", async () => { "name": "NumberList", "namespace": "", "schemaVersion": 1, - "tableId": "0x000000000000000000000000000000004e756d6265724c697374000000000000", + "tableId": "0x746200000000000000000000000000004e756d6265724c697374000000000000", "valueSchema": { "value": "uint32[]", }, @@ -91,11 +91,14 @@ describe("postgresStorage", async () => { [ { "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", + "key": "0x5FbDB2315678afecb367f032d93F642f64180aa3::NumberList", "keySchema": {}, + "lastError": null, "lastUpdatedBlockNumber": 5n, "name": "NumberList", "namespace": "", - "tableId": "0x000000000000000000000000000000004e756d6265724c697374000000000000", + "schemaVersion": 1, + "tableId": "0x746200000000000000000000000000004e756d6265724c697374000000000000", "valueSchema": { "value": "uint32[]", }, diff --git a/packages/store-sync/src/postgres/postgresStorage.ts b/packages/store-sync/src/postgres/postgresStorage.ts index 7e61e5f5d7..4246c037cc 100644 --- a/packages/store-sync/src/postgres/postgresStorage.ts +++ b/packages/store-sync/src/postgres/postgresStorage.ts @@ -7,7 +7,7 @@ import { debug } from "./debug"; import { buildInternalTables } from "./buildInternalTables"; import { getTables } from "./getTables"; import { schemaVersion } from "./schemaVersion"; -import { hexToTableId, spliceHex, tableIdToHex } from "@latticexyz/common"; +import { hexToResourceId, spliceHex } from "@latticexyz/common"; import { setupTables } from "./setupTables"; import { getTableKey } from "./getTableKey"; import { StorageAdapter, StorageAdapterBlock } from "../common"; @@ -40,15 +40,7 @@ export async function postgresStorage async function postgresStorageAdapter({ blockNumber, logs }: StorageAdapterBlock): Promise { const newTables = logs.filter(isTableRegistrationLog).map(logToTable); - const newSqlTables = newTables.map((table) => - buildTable({ - address: table.address, - namespace: table.namespace, - name: table.name, - keySchema: table.keySchema, - valueSchema: table.valueSchema, - }) - ); + const newSqlTables = newTables.map(buildTable); cleanUp.push(await setupTables(database, newSqlTables)); @@ -59,12 +51,7 @@ export async function postgresStorage .values({ schemaVersion, key: getTableKey(table), - address: table.address, - tableId: tableIdToHex(table.namespace, table.name), - namespace: table.namespace, - name: table.name, - keySchema: table.keySchema, - valueSchema: table.valueSchema, + ...table, lastUpdatedBlockNumber: blockNumber, }) .onConflictDoNothing() @@ -98,7 +85,7 @@ export async function postgresStorage (table) => getTableKey(table) === getTableKey({ address: log.address, tableId: log.args.tableId }) ); if (!table) { - const { namespace, name } = hexToTableId(log.args.tableId); + const { namespace, name } = hexToResourceId(log.args.tableId); debug(`table ${namespace}:${name} not found, skipping log`, log); continue; } diff --git a/packages/store-sync/src/recs/configToRecsComponents.ts b/packages/store-sync/src/recs/configToRecsComponents.ts index 9243f846c9..de52d113b8 100644 --- a/packages/store-sync/src/recs/configToRecsComponents.ts +++ b/packages/store-sync/src/recs/configToRecsComponents.ts @@ -1,6 +1,6 @@ import { StoreConfig } from "@latticexyz/store"; import { SchemaAbiType } from "@latticexyz/schema-type"; -import { tableIdToHex } from "@latticexyz/common"; +import { resourceIdToHex } from "@latticexyz/common"; import { World, defineComponent, Type } from "@latticexyz/recs"; import { ConfigToRecsComponents } from "./common"; import { schemaAbiTypeToRecsType } from "./schemaAbiTypeToRecsType"; @@ -26,7 +26,12 @@ export function configToRecsComponents( __dynamicData: Type.OptionalString, }, { - id: tableIdToHex(config.namespace, tableName), + // TODO: support table namespaces https://github.com/latticexyz/mud/issues/994 + id: resourceIdToHex({ + type: table.ephemeral ? "offchainTable" : "table", + namespace: config.namespace, + name: tableName, + }), metadata: { componentName: tableName, tableName: `${config.namespace}:${tableName}`, diff --git a/packages/store-sync/src/recs/recsStorage.test.ts b/packages/store-sync/src/recs/recsStorage.test.ts index 4bb747b0dc..28879f788b 100644 --- a/packages/store-sync/src/recs/recsStorage.test.ts +++ b/packages/store-sync/src/recs/recsStorage.test.ts @@ -27,7 +27,7 @@ describe("recsStorage", () => { const world = createWorld(); const { components } = recsStorage({ world, config: mudConfig }); expect(components.NumberList.id).toMatchInlineSnapshot( - '"0x000000000000000000000000000000004e756d6265724c697374000000000000"' + '"0x746200000000000000000000000000004e756d6265724c697374000000000000"' ); }); diff --git a/packages/store-sync/src/recs/recsStorage.ts b/packages/store-sync/src/recs/recsStorage.ts index 457eb88793..ce351803f7 100644 --- a/packages/store-sync/src/recs/recsStorage.ts +++ b/packages/store-sync/src/recs/recsStorage.ts @@ -3,7 +3,7 @@ import { debug } from "./debug"; import { World as RecsWorld, getComponentValue, hasComponent, removeComponent, setComponent } from "@latticexyz/recs"; import { defineInternalComponents } from "./defineInternalComponents"; import { getTableEntity } from "./getTableEntity"; -import { hexToTableId, spliceHex } from "@latticexyz/common"; +import { hexToResourceId, spliceHex } from "@latticexyz/common"; import { decodeValueArgs } from "@latticexyz/protocol-parser"; import { Hex } from "viem"; import { isTableRegistrationLog } from "../isTableRegistrationLog"; @@ -58,7 +58,7 @@ export function recsStorage({ } for (const log of logs) { - const { namespace, name } = hexToTableId(log.args.tableId); + const { namespace, name } = hexToResourceId(log.args.tableId); const table = getComponentValue( components.RegisteredTables, getTableEntity({ address: log.address, namespace, name }) diff --git a/packages/store-sync/src/sqlite/columnTypes.ts b/packages/store-sync/src/sqlite/columnTypes.ts index 3dd4c07e9f..d94f10faee 100644 --- a/packages/store-sync/src/sqlite/columnTypes.ts +++ b/packages/store-sync/src/sqlite/columnTypes.ts @@ -1,6 +1,8 @@ import { customType } from "drizzle-orm/sqlite-core"; import superjson from "superjson"; -import { Address, getAddress } from "viem"; +import { Address, Hex, getAddress } from "viem"; + +// TODO: migrate these to same patterns in postgres/columnTypes // eslint-disable-next-line @typescript-eslint/explicit-function-return-type export const json = (name: string) => @@ -29,3 +31,11 @@ export const address = (name: string) => return getAddress(driverData); }, })(name); + +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export const asHex = (name: string) => + customType<{ data: Hex; driverData: Hex }>({ + dataType() { + return "string"; + }, + })(name); diff --git a/packages/store-sync/src/sqlite/getTables.ts b/packages/store-sync/src/sqlite/getTables.ts index 9a99afacbf..f0db291ddb 100644 --- a/packages/store-sync/src/sqlite/getTables.ts +++ b/packages/store-sync/src/sqlite/getTables.ts @@ -3,7 +3,6 @@ import { inArray } from "drizzle-orm"; import { Table } from "../common"; import { getTableName } from "./getTableName"; import { mudStoreTables } from "./internalTables"; -import { tableIdToHex } from "@latticexyz/common"; export function getTables( db: BaseSQLiteDatabase<"sync", void>, @@ -18,17 +17,5 @@ export function getTables( .where(ids.length ? inArray(mudStoreTables.id, ids) : undefined) .all(); - return tables.map((table) => { - const tableId = tableIdToHex(table.namespace, table.name); - return { - id: getTableName(table.address, table.namespace, table.name), - address: table.address, - tableId, - namespace: table.namespace, - name: table.name, - keySchema: table.keySchema, - valueSchema: table.valueSchema, - lastUpdatedBlockNumber: table.lastUpdatedBlockNumber, - }; - }); + return tables; } diff --git a/packages/store-sync/src/sqlite/internalTables.ts b/packages/store-sync/src/sqlite/internalTables.ts index d2774a48e0..fe11932238 100644 --- a/packages/store-sync/src/sqlite/internalTables.ts +++ b/packages/store-sync/src/sqlite/internalTables.ts @@ -1,5 +1,5 @@ import { blob, integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; -import { address, json } from "./columnTypes"; +import { address, asHex, json } from "./columnTypes"; import { KeySchema, ValueSchema } from "@latticexyz/protocol-parser"; export const chainState = sqliteTable("__chainState", { @@ -14,7 +14,7 @@ export const mudStoreTables = sqliteTable("__mudStoreTables", { schemaVersion: integer("schema_version").primaryKey(), id: text("id").notNull().primaryKey(), address: address("address").notNull(), - tableId: text("table_id").notNull(), + tableId: asHex("table_id").notNull(), namespace: text("namespace").notNull(), name: text("name").notNull(), keySchema: json("key_schema").notNull(), diff --git a/packages/store-sync/src/sqlite/sqliteStorage.test.ts b/packages/store-sync/src/sqlite/sqliteStorage.test.ts index 1c8845f37c..06b01ce31e 100644 --- a/packages/store-sync/src/sqlite/sqliteStorage.test.ts +++ b/packages/store-sync/src/sqlite/sqliteStorage.test.ts @@ -81,7 +81,7 @@ describe("sqliteStorage", async () => { "name": "NumberList", "namespace": "", "schemaVersion": 1, - "tableId": "0x000000000000000000000000000000004e756d6265724c697374000000000000", + "tableId": "0x746200000000000000000000000000004e756d6265724c697374000000000000", "valueSchema": { "value": "uint32[]", }, @@ -96,10 +96,12 @@ describe("sqliteStorage", async () => { "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", "id": "0x5FbDB2315678afecb367f032d93F642f64180aa3____NumberList", "keySchema": {}, + "lastError": null, "lastUpdatedBlockNumber": 5n, "name": "NumberList", "namespace": "", - "tableId": "0x000000000000000000000000000000004e756d6265724c697374000000000000", + "schemaVersion": 1, + "tableId": "0x746200000000000000000000000000004e756d6265724c697374000000000000", "valueSchema": { "value": "uint32[]", }, diff --git a/packages/store-sync/src/sqlite/sqliteStorage.ts b/packages/store-sync/src/sqlite/sqliteStorage.ts index 08ca78f547..180048279e 100644 --- a/packages/store-sync/src/sqlite/sqliteStorage.ts +++ b/packages/store-sync/src/sqlite/sqliteStorage.ts @@ -12,7 +12,7 @@ import { schemaVersion } from "./schemaVersion"; import { StorageAdapter } from "../common"; import { isTableRegistrationLog } from "../isTableRegistrationLog"; import { logToTable } from "../logToTable"; -import { hexToTableId, spliceHex, tableIdToHex } from "@latticexyz/common"; +import { hexToResourceId, spliceHex } from "@latticexyz/common"; import { decodeKey, decodeValueArgs } from "@latticexyz/protocol-parser"; // TODO: upgrade drizzle and use async sqlite interface for consistency @@ -38,13 +38,7 @@ export async function sqliteStorage({ for (const table of newTables) { debug(`creating table ${table.namespace}:${table.name} for world ${chainId}:${table.address}`); - const sqliteTable = buildTable({ - address: table.address, - namespace: table.namespace, - name: table.name, - keySchema: table.keySchema, - valueSchema: table.valueSchema, - }); + const sqliteTable = buildTable(table); tx.run(sql.raw(sqliteTableToSql(sqliteTable))); @@ -52,12 +46,7 @@ export async function sqliteStorage({ .values({ schemaVersion, id: getTableName(table.address, table.namespace, table.name), - address: table.address, - tableId: tableIdToHex(table.namespace, table.name), - namespace: table.namespace, - name: table.name, - keySchema: table.keySchema, - valueSchema: table.valueSchema, + ...table, lastUpdatedBlockNumber: blockNumber, }) .onConflictDoNothing() @@ -72,7 +61,7 @@ export async function sqliteStorage({ logs.map((log) => JSON.stringify({ address: getAddress(log.address), - ...hexToTableId(log.args.tableId), + ...hexToResourceId(log.args.tableId), }) ) ) @@ -98,7 +87,7 @@ export async function sqliteStorage({ (table) => table.address === getAddress(log.address) && table.tableId === log.args.tableId ); if (!table) { - const tableId = hexToTableId(log.args.tableId); + const tableId = hexToResourceId(log.args.tableId); debug(`table ${tableId.namespace}:${tableId.name} not found, skipping log`, log); continue; } diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 765b65cbf3..6f8ba5f968 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -351,7 +351,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register KeyEncoding table", - "gasUsed": 687778 + "gasUsed": 720082 }, { "file": "test/Mixed.t.sol", @@ -363,19 +363,19 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Mixed table", - "gasUsed": 549596 + "gasUsed": 581907 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 103898 + "gasUsed": 103942 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "get record from Mixed", - "gasUsed": 7015 + "gasUsed": 7025 }, { "file": "test/PackedCounter.t.sol", @@ -407,6 +407,18 @@ "name": "set value at index of PackedCounter", "gasUsed": 286 }, + { + "file": "test/ResourceId.t.sol", + "test": "testEncode", + "name": "encode table ID with name and type", + "gasUsed": 188 + }, + { + "file": "test/ResourceId.t.sol", + "test": "testGetType", + "name": "get type from a table ID", + "gasUsed": 4 + }, { "file": "test/Schema.t.sol", "test": "testEncodeDecodeSchema", @@ -609,31 +621,31 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 19408 + "gasUsed": 19440 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 13418 + "gasUsed": 13450 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 17176 + "gasUsed": 17208 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 13187 + "gasUsed": 13219 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access non-existing record", - "gasUsed": 7041 + "gasUsed": 7042 }, { "file": "test/StoreCoreGas.t.sol", @@ -645,7 +657,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access dynamic field of non-existing record", - "gasUsed": 2033 + "gasUsed": 2034 }, { "file": "test/StoreCoreGas.t.sol", @@ -657,115 +669,115 @@ "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access slice of dynamic field of non-existing record", - "gasUsed": 1483 + "gasUsed": 1484 }, { "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 6678 + "gasUsed": 6700 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "Check for existence of table (existent)", - "gasUsed": 1260 + "gasUsed": 1249 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "check for existence of table (non-existent)", - "gasUsed": 3261 + "gasUsed": 3249 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 58654 + "gasUsed": 58696 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 71024 + "gasUsed": 71265 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 20506 + "gasUsed": 20746 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 16373 + "gasUsed": 16736 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 58654 + "gasUsed": 58696 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 164146 + "gasUsed": 164386 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 24273 + "gasUsed": 24513 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 17358 + "gasUsed": 17721 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 10241 + "gasUsed": 10264 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 32918 + "gasUsed": 32940 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 609747 + "gasUsed": 642028 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get field layout (warm)", - "gasUsed": 1272 + "gasUsed": 1293 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get value schema (warm)", - "gasUsed": 1782 + "gasUsed": 1804 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get key schema (warm)", - "gasUsed": 2816 + "gasUsed": 2827 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 101818 + "gasUsed": 101840 }, { "file": "test/StoreCoreGas.t.sol", @@ -783,7 +795,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "compare: Set complex record with dynamic data using abi.encode", - "gasUsed": 267368 + "gasUsed": 267369 }, { "file": "test/StoreCoreGas.t.sol", @@ -795,19 +807,19 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 1", - "gasUsed": 970 + "gasUsed": 971 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "reduce dynamic length of dynamic index 0", - "gasUsed": 960 + "gasUsed": 961 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 31579 + "gasUsed": 31601 }, { "file": "test/StoreCoreGas.t.sol", @@ -819,19 +831,19 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 30219 + "gasUsed": 30241 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (overlap 2 slot)", - "gasUsed": 1844 + "gasUsed": 1845 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 53942 + "gasUsed": 53966 }, { "file": "test/StoreCoreGas.t.sol", @@ -843,19 +855,19 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 32169 + "gasUsed": 32192 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, second dynamic field)", - "gasUsed": 2203 + "gasUsed": 2204 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 32124 + "gasUsed": 32145 }, { "file": "test/StoreCoreGas.t.sol", @@ -867,25 +879,25 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 54628 + "gasUsed": 54650 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "get static record (2 slots)", - "gasUsed": 1709 + "gasUsed": 1711 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 9585 + "gasUsed": 9608 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 10022 + "gasUsed": 10045 }, { "file": "test/StoreHook.t.sol", @@ -927,121 +939,121 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 57008 + "gasUsed": 57052 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: get field (warm)", - "gasUsed": 2881 + "gasUsed": 2902 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 33292 + "gasUsed": 33337 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 59012 + "gasUsed": 59054 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 59012 + "gasUsed": 59054 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: get field (warm)", - "gasUsed": 2883 + "gasUsed": 2904 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 13389 + "gasUsed": 13431 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 10686 + "gasUsed": 10739 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 11411 + "gasUsed": 11453 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 30626 + "gasUsed": 30668 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 7086 + "gasUsed": 7128 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 31173 + "gasUsed": 31215 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 81703 + "gasUsed": 81745 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 81615 + "gasUsed": 81657 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 15954 + "gasUsed": 15996 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGet", "name": "StoreHooks: get field (cold)", - "gasUsed": 8880 + "gasUsed": 8901 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGetItem", "name": "StoreHooks: get 1 element (cold)", - "gasUsed": 6521 + "gasUsed": 6542 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testLength", "name": "StoreHooks: get length (cold)", - "gasUsed": 5840 + "gasUsed": 5861 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 19126 + "gasUsed": 19168 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 21069 + "gasUsed": 21111 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -1095,18 +1107,18 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 411019 + "gasUsed": 443350 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 33027 + "gasUsed": 33069 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "get Vector2 record", - "gasUsed": 2505 + "gasUsed": 2514 } ] diff --git a/packages/store/mud.config.ts b/packages/store/mud.config.ts index 814ab527b9..e871948207 100644 --- a/packages/store/mud.config.ts +++ b/packages/store/mud.config.ts @@ -21,6 +21,14 @@ export default mudConfig({ abiEncodedFieldNames: "bytes", }, }, + ResourceIds: { + keySchema: { + resourceId: "bytes32", + }, + valueSchema: { + exists: "bool", + }, + }, // The Hooks table is a generic table used by the `filterFromList` util in `Hook.sol` Hooks: { valueSchema: "bytes21[]", diff --git a/packages/store/src/Hook.sol b/packages/store/src/Hook.sol index d7511d4dc2..bba92c89aa 100644 --- a/packages/store/src/Hook.sol +++ b/packages/store/src/Hook.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0; import { Hooks } from "./codegen/tables/Hooks.sol"; +import { ResourceId } from "./ResourceId.sol"; // 20 bytes address, 1 byte bitmap of enabled hooks type Hook is bytes21; @@ -20,8 +21,12 @@ library HookLib { /** * Filter the given hook from the hook list at the given key in the given hook table */ - function filterListByAddress(bytes32 hookTableId, bytes32 key, address hookAddressToRemove) internal { - bytes21[] memory currentHooks = Hooks._get(hookTableId, key); + function filterListByAddress( + ResourceId hookTableId, + ResourceId tableWithHooks, + address hookAddressToRemove + ) internal { + bytes21[] memory currentHooks = Hooks._get(hookTableId, ResourceId.unwrap(tableWithHooks)); // Initialize the new hooks array with the same length because we don't know if the hook is registered yet bytes21[] memory newHooks = new bytes21[](currentHooks.length); @@ -44,7 +49,7 @@ library HookLib { } // Set the new hooks table - Hooks._set(hookTableId, key, newHooks); + Hooks._set(hookTableId, ResourceId.unwrap(tableWithHooks), newHooks); } } diff --git a/packages/store/src/IStore.sol b/packages/store/src/IStore.sol index 0e8546acaf..f73f4f4c46 100644 --- a/packages/store/src/IStore.sol +++ b/packages/store/src/IStore.sol @@ -6,23 +6,24 @@ import { PackedCounter } from "./PackedCounter.sol"; import { FieldLayout } from "./FieldLayout.sol"; import { Schema } from "./Schema.sol"; import { IStoreHook } from "./IStoreHook.sol"; +import { ResourceId } from "./ResourceId.sol"; interface IStoreRead { event HelloStore(bytes32 indexed storeVersion); function storeVersion() external view returns (bytes32); - function getFieldLayout(bytes32 tableId) external view returns (FieldLayout fieldLayout); + function getFieldLayout(ResourceId tableId) external view returns (FieldLayout fieldLayout); - function getValueSchema(bytes32 tableId) external view returns (Schema valueSchema); + function getValueSchema(ResourceId tableId) external view returns (Schema valueSchema); - function getKeySchema(bytes32 tableId) external view returns (Schema keySchema); + function getKeySchema(ResourceId tableId) external view returns (Schema keySchema); /** * Get full record (all fields, static and dynamic data) for the given tableId and key tuple, with the given value field layout */ function getRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, FieldLayout fieldLayout ) external view returns (bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData); @@ -31,7 +32,7 @@ interface IStoreRead { * Get a single field from the given tableId and key tuple, with the given value field layout */ function getField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -43,7 +44,7 @@ interface IStoreRead { * Consumers are expected to truncate the returned value as needed. */ function getStaticField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -54,7 +55,7 @@ interface IStoreRead { * (Dynamic field index = field index - number of static fields) */ function getDynamicField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex ) external view returns (bytes memory); @@ -63,7 +64,7 @@ interface IStoreRead { * Get the byte length of a single field from the given tableId and key tuple, with the given value field layout */ function getFieldLength( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -74,7 +75,7 @@ interface IStoreRead { * The slice is unchecked and will return invalid data if `start`:`end` overflow. */ function getFieldSlice( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout, @@ -85,32 +86,32 @@ interface IStoreRead { interface IStoreWrite { event StoreSetRecord( - bytes32 indexed tableId, + ResourceId indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData ); event StoreSpliceStaticData( - bytes32 indexed tableId, + ResourceId indexed tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data ); event StoreSpliceDynamicData( - bytes32 indexed tableId, + ResourceId indexed tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data, bytes32 encodedLengths ); - event StoreDeleteRecord(bytes32 indexed tableId, bytes32[] keyTuple); + event StoreDeleteRecord(ResourceId indexed tableId, bytes32[] keyTuple); // Set full record (including full dynamic data) function setRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, bytes calldata staticData, PackedCounter encodedLengths, @@ -120,7 +121,7 @@ interface IStoreWrite { // Splice data in the static part of the record function spliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint48 start, uint40 deleteCount, @@ -129,7 +130,7 @@ interface IStoreWrite { // Splice data in the dynamic part of the record function spliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -139,7 +140,7 @@ interface IStoreWrite { // Set partial data at field index function setField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, bytes calldata data, @@ -148,7 +149,7 @@ interface IStoreWrite { // Push encoded items to the dynamic field at field index function pushToField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, bytes calldata dataToPush, @@ -157,7 +158,7 @@ interface IStoreWrite { // Pop byte length from the dynamic field at field index function popFromField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, uint256 byteLengthToPop, @@ -166,7 +167,7 @@ interface IStoreWrite { // Change encoded items within the dynamic field at field index function updateInField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, uint256 startByteIndex, @@ -175,12 +176,12 @@ interface IStoreWrite { ) external; // Set full record (including full dynamic data) - function deleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) external; + function deleteRecord(ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) external; } interface IStoreEphemeral { event StoreEphemeralRecord( - bytes32 indexed tableId, + ResourceId indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, @@ -189,7 +190,7 @@ interface IStoreEphemeral { // Emit the ephemeral event without modifying storage function emitEphemeralRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, bytes calldata staticData, PackedCounter encodedLengths, @@ -214,7 +215,7 @@ interface IStoreData is IStoreRead, IStoreWrite { */ interface IStoreRegistration { function registerTable( - bytes32 tableId, + ResourceId tableId, FieldLayout fieldLayout, Schema keySchema, Schema valueSchema, @@ -223,10 +224,10 @@ interface IStoreRegistration { ) external; // Register hook to be called when a record or field is set or deleted - function registerStoreHook(bytes32 tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) external; + function registerStoreHook(ResourceId tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) external; // Unregister a hook for the given tableId - function unregisterStoreHook(bytes32 tableId, IStoreHook hookAddress) external; + function unregisterStoreHook(ResourceId tableId, IStoreHook hookAddress) external; } interface IStore is IStoreData, IStoreRegistration, IStoreEphemeral, IStoreErrors {} diff --git a/packages/store/src/IStoreErrors.sol b/packages/store/src/IStoreErrors.sol index 5987a1d408..1b42a84107 100644 --- a/packages/store/src/IStoreErrors.sol +++ b/packages/store/src/IStoreErrors.sol @@ -1,10 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; +import { ResourceId } from "./ResourceId.sol"; + interface IStoreErrors { // Errors include a stringified version of the tableId for easier debugging if cleartext tableIds are used - error StoreCore_TableAlreadyExists(bytes32 tableId, string tableIdString); - error StoreCore_TableNotFound(bytes32 tableId, string tableIdString); + error StoreCore_TableAlreadyExists(ResourceId tableId, string tableIdString); + error StoreCore_TableNotFound(ResourceId tableId, string tableIdString); + error StoreCore_InvalidResourceType(bytes2 expected, ResourceId resourceId, string resourceIdString); error StoreCore_NotImplemented(); error StoreCore_NotDynamicField(); diff --git a/packages/store/src/IStoreHook.sol b/packages/store/src/IStoreHook.sol index a2be6d40f0..271e07ac97 100644 --- a/packages/store/src/IStoreHook.sol +++ b/packages/store/src/IStoreHook.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.0; import { FieldLayout } from "./FieldLayout.sol"; import { IERC165, ERC165_INTERFACE_ID } from "./IERC165.sol"; import { PackedCounter } from "./PackedCounter.sol"; +import { ResourceId } from "./ResourceId.sol"; // ERC-165 Interface ID (see https://eips.ethereum.org/EIPS/eip-165) bytes4 constant STORE_HOOK_INTERFACE_ID = IStoreHook.onBeforeSetRecord.selector ^ @@ -20,7 +21,7 @@ interface IStoreHook is IERC165 { error StoreHook_NotImplemented(); function onBeforeSetRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, bytes memory staticData, PackedCounter encodedLengths, @@ -29,7 +30,7 @@ interface IStoreHook is IERC165 { ) external; function onAfterSetRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, bytes memory staticData, PackedCounter encodedLengths, @@ -38,7 +39,7 @@ interface IStoreHook is IERC165 { ) external; function onBeforeSpliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint48 start, uint40 deleteCount, @@ -46,7 +47,7 @@ interface IStoreHook is IERC165 { ) external; function onAfterSpliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint48 start, uint40 deleteCount, @@ -54,7 +55,7 @@ interface IStoreHook is IERC165 { ) external; function onBeforeSpliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -64,7 +65,7 @@ interface IStoreHook is IERC165 { ) external; function onAfterSpliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -73,7 +74,7 @@ interface IStoreHook is IERC165 { PackedCounter encodedLengths ) external; - function onBeforeDeleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) external; + function onBeforeDeleteRecord(ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) external; - function onAfterDeleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) external; + function onAfterDeleteRecord(ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) external; } diff --git a/packages/store/src/ResourceId.sol b/packages/store/src/ResourceId.sol new file mode 100644 index 0000000000..20dec4c6b8 --- /dev/null +++ b/packages/store/src/ResourceId.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +type ResourceId is bytes32; + +uint256 constant TYPE_BYTES = 2; +uint256 constant NAME_BYTES = 32 - TYPE_BYTES; +uint256 constant BYTES_TO_BITS = 8; + +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))); + } +} + +library ResourceIdInstance { + function getType(ResourceId resourceId) internal pure returns (bytes2) { + return bytes2(ResourceId.unwrap(resourceId)); + } +} diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 7fae2a9f36..d4683aaa10 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -9,12 +9,14 @@ import { FieldLayout, FieldLayoutLib } from "./FieldLayout.sol"; import { Schema, SchemaLib } from "./Schema.sol"; import { PackedCounter } from "./PackedCounter.sol"; import { Slice, SliceLib } from "./Slice.sol"; -import { StoreHooks, Tables, StoreHooksTableId } from "./codegen/index.sol"; +import { StoreHooks, Tables, ResourceIds, StoreHooksTableId } from "./codegen/index.sol"; import { IStoreErrors } from "./IStoreErrors.sol"; import { IStoreHook } from "./IStoreHook.sol"; import { StoreSwitch } from "./StoreSwitch.sol"; import { Hook, HookLib } from "./Hook.sol"; import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SPLICE_STATIC_DATA, AFTER_SPLICE_STATIC_DATA, BEFORE_SPLICE_DYNAMIC_DATA, AFTER_SPLICE_DYNAMIC_DATA, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "./storeHookTypes.sol"; +import { ResourceId, ResourceIdInstance } from "./ResourceId.sol"; +import { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "./storeResourceTypes.sol"; /** * StoreCore includes implementations for all IStore methods. @@ -22,32 +24,34 @@ import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SPLICE_STATIC_DATA, AFTER_S * It's split into a separate library to make it clear that it's not intended to be outside StoreCore. */ library StoreCore { + using ResourceIdInstance for ResourceId; + event HelloStore(bytes32 indexed version); event StoreSetRecord( - bytes32 indexed tableId, + ResourceId indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData ); event StoreSpliceStaticData( - bytes32 indexed tableId, + ResourceId indexed tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data ); event StoreSpliceDynamicData( - bytes32 indexed tableId, + ResourceId indexed tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data, bytes32 encodedLengths ); - event StoreDeleteRecord(bytes32 indexed tableId, bytes32[] keyTuple); + event StoreDeleteRecord(ResourceId indexed tableId, bytes32[] keyTuple); event StoreEphemeralRecord( - bytes32 indexed tableId, + ResourceId indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, @@ -76,6 +80,7 @@ library StoreCore { // Register core tables Tables.register(); StoreHooks.register(); + ResourceIds.register(); } /************************************************************************ @@ -87,8 +92,8 @@ library StoreCore { /** * Get the field layout for the given tableId */ - function getFieldLayout(bytes32 tableId) internal view returns (FieldLayout fieldLayout) { - fieldLayout = FieldLayout.wrap(Tables._getFieldLayout(tableId)); + function getFieldLayout(ResourceId tableId) internal view returns (FieldLayout fieldLayout) { + fieldLayout = FieldLayout.wrap(Tables._getFieldLayout(ResourceId.unwrap(tableId))); if (fieldLayout.isEmpty()) { revert IStoreErrors.StoreCore_TableNotFound(tableId, string(abi.encodePacked(tableId))); } @@ -97,10 +102,10 @@ library StoreCore { /** * Get the key schema for the given tableId */ - function getKeySchema(bytes32 tableId) internal view returns (Schema keySchema) { - keySchema = Schema.wrap(Tables._getKeySchema(tableId)); + function getKeySchema(ResourceId tableId) internal view returns (Schema keySchema) { + keySchema = Schema.wrap(Tables._getKeySchema(ResourceId.unwrap(tableId))); // key schemas can be empty for singleton tables, so we can't depend on key schema for table check - if (!hasTable(tableId)) { + if (!ResourceIds._getExists(ResourceId.unwrap(tableId))) { revert IStoreErrors.StoreCore_TableNotFound(tableId, string(abi.encodePacked(tableId))); } } @@ -108,31 +113,29 @@ library StoreCore { /** * Get the schema for the given tableId */ - function getValueSchema(bytes32 tableId) internal view returns (Schema valueSchema) { - valueSchema = Schema.wrap(Tables._getValueSchema(tableId)); + function getValueSchema(ResourceId tableId) internal view returns (Schema valueSchema) { + valueSchema = Schema.wrap(Tables._getValueSchema(ResourceId.unwrap(tableId))); if (valueSchema.isEmpty()) { revert IStoreErrors.StoreCore_TableNotFound(tableId, string(abi.encodePacked(tableId))); } } - /** - * Check if a table with the given tableId exists - */ - function hasTable(bytes32 tableId) internal view returns (bool) { - return Tables._getFieldLayout(tableId) != bytes32(0); - } - /** * Register a new table the given config */ function registerTable( - bytes32 tableId, + ResourceId tableId, FieldLayout fieldLayout, Schema keySchema, Schema valueSchema, string[] memory keyNames, string[] memory fieldNames ) internal { + // Verify the table ID is of type RESOURCE_TABLE + if (tableId.getType() != RESOURCE_TABLE && tableId.getType() != RESOURCE_OFFCHAIN_TABLE) { + revert IStoreErrors.StoreCore_InvalidResourceType(RESOURCE_TABLE, tableId, string(abi.encodePacked(tableId))); + } + // Verify the field layout is valid fieldLayout.validate({ allowEmpty: false }); @@ -155,20 +158,23 @@ library StoreCore { revert IStoreErrors.StoreCore_InvalidValueSchemaLength(fieldLayout.numFields(), valueSchema.numFields()); } - // Verify the field layout doesn't exist yet - if (hasTable(tableId)) { + // Verify there is no resource with this ID yet + if (ResourceIds._getExists(ResourceId.unwrap(tableId))) { revert IStoreErrors.StoreCore_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); } // Register the table metadata Tables._set( - tableId, + ResourceId.unwrap(tableId), FieldLayout.unwrap(fieldLayout), Schema.unwrap(keySchema), Schema.unwrap(valueSchema), abi.encode(keyNames), abi.encode(fieldNames) ); + + // Register the table ID + ResourceIds._setExists(ResourceId.unwrap(tableId), true); } /************************************************************************ @@ -180,14 +186,14 @@ library StoreCore { /* * Register hooks to be called when a record or field is set or deleted */ - function registerStoreHook(bytes32 tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) internal { - StoreHooks.push(tableId, Hook.unwrap(HookLib.encode(address(hookAddress), enabledHooksBitmap))); + function registerStoreHook(ResourceId tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) internal { + StoreHooks.push(ResourceId.unwrap(tableId), Hook.unwrap(HookLib.encode(address(hookAddress), enabledHooksBitmap))); } /** * Unregister a hook from the given tableId */ - function unregisterStoreHook(bytes32 tableId, IStoreHook hookAddress) internal { + function unregisterStoreHook(ResourceId tableId, IStoreHook hookAddress) internal { HookLib.filterListByAddress(StoreHooksTableId, tableId, address(hookAddress)); } @@ -201,7 +207,7 @@ library StoreCore { * Set full data record for the given table ID and key tuple and field layout */ function setRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, bytes memory staticData, PackedCounter encodedLengths, @@ -218,7 +224,7 @@ library StoreCore { emit StoreSetRecord(tableId, keyTuple, staticData, encodedLengths.unwrap(), dynamicData); // Call onBeforeSetRecord hooks (before actually modifying the state, so observers have access to the previous state if needed) - bytes21[] memory hooks = StoreHooks._get(tableId); + bytes21[] memory hooks = StoreHooks._get(ResourceId.unwrap(tableId)); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(BEFORE_SET_RECORD)) { @@ -288,7 +294,7 @@ library StoreCore { } function spliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint48 start, uint40 deleteCount, @@ -297,7 +303,7 @@ library StoreCore { 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); + bytes21[] memory hooks = StoreHooks._get(ResourceId.unwrap(tableId)); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(BEFORE_SPLICE_STATIC_DATA)) { @@ -339,7 +345,7 @@ library StoreCore { } function spliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, // need this to compute the dynamic data location uint40 startWithinField, @@ -361,7 +367,7 @@ library StoreCore { * Set data for a field in a table with the given tableId, key tuple and value field layout */ function setField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, bytes memory data, @@ -375,7 +381,7 @@ library StoreCore { } function setStaticField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout, uint8 fieldIndex, @@ -391,7 +397,7 @@ library StoreCore { } function setDynamicField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, bytes memory data @@ -414,12 +420,12 @@ library StoreCore { /** * Delete a record for the given tableId, key tuple and value field layout */ - function deleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) internal { + function deleteRecord(ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) internal { // Emit event to notify indexers emit StoreDeleteRecord(tableId, keyTuple); // Call onBeforeDeleteRecord hooks (before actually modifying the state, so observers have access to the previous state if needed) - bytes21[] memory hooks = StoreHooks._get(tableId); + bytes21[] memory hooks = StoreHooks._get(ResourceId.unwrap(tableId)); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(BEFORE_DELETE_RECORD)) { @@ -450,7 +456,7 @@ library StoreCore { * Push data to a field in a table with the given tableId, keyTuple tuple and value field layout */ function pushToField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, bytes memory dataToPush, @@ -467,7 +473,7 @@ library StoreCore { * Pop data from a field in a table with the given tableId, key tuple and value field layout */ function popFromField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, uint256 byteLengthToPop, @@ -484,7 +490,7 @@ library StoreCore { * Update data in a field in a table with the given tableId, key tuple and value field layout */ function updateInField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, uint256 startByteIndex, @@ -514,7 +520,7 @@ library StoreCore { * Emit the ephemeral event without modifying storage for the full data of the given table ID and key tuple */ function emitEphemeralRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, bytes memory staticData, PackedCounter encodedLengths, @@ -538,7 +544,7 @@ library StoreCore { * Get full record (all fields, static and dynamic data) for the given table ID and key tuple, with the given value field layout */ function getRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout ) internal view returns (bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData) { @@ -572,7 +578,7 @@ library StoreCore { * Get a single field from the given table ID and key tuple, with the given value field layout */ function getField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -590,7 +596,7 @@ library StoreCore { * Consumers are expected to truncate the returned value as needed. */ function getStaticField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -609,7 +615,7 @@ library StoreCore { * Get a single dynamic field from the given table ID and key tuple, with the given value field layout */ function getDynamicField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex ) internal view returns (bytes memory) { @@ -627,7 +633,7 @@ library StoreCore { * Get the byte length of a single field from the given table ID and key tuple, with the given value field layout */ function getFieldLength( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -647,7 +653,7 @@ library StoreCore { * The slice is unchecked and will return invalid data if `start`:`end` overflow. */ function getFieldSlice( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout, @@ -679,7 +685,7 @@ library StoreCoreInternal { ************************************************************************/ function _spliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -709,7 +715,7 @@ library StoreCoreInternal { 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); + bytes21[] memory hooks = StoreHooks._get(ResourceId.unwrap(tableId)); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(BEFORE_SPLICE_DYNAMIC_DATA)) { @@ -765,7 +771,7 @@ library StoreCoreInternal { } function _pushToDynamicField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout, uint8 fieldIndex, @@ -790,7 +796,7 @@ library StoreCoreInternal { } function _popFromDynamicField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout, uint8 fieldIndex, @@ -815,7 +821,7 @@ library StoreCoreInternal { } function _setDynamicFieldItem( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout, uint8 fieldIndex, @@ -843,7 +849,7 @@ library StoreCoreInternal { * Get full static data for the given table ID and key tuple, with the given static length */ function _getStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint256 length ) internal view returns (bytes memory) { @@ -859,7 +865,7 @@ library StoreCoreInternal { * Returns dynamic bytes memory in the size of the field. */ function _getStaticFieldBytes( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -905,7 +911,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) { + function _getStaticDataLocation(ResourceId tableId, bytes32[] memory keyTuple) internal pure returns (uint256) { return uint256(SLOT ^ keccak256(abi.encodePacked(tableId, keyTuple))); } @@ -928,7 +934,7 @@ library StoreCoreInternal { * Compute the storage location based on tableId id and index tuple */ function _getDynamicDataLocation( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex ) internal pure returns (uint256) { @@ -938,7 +944,10 @@ library StoreCoreInternal { /** * Compute the storage location for the length of the dynamic data */ - function _getDynamicDataLengthLocation(bytes32 tableId, bytes32[] memory keyTuple) internal pure returns (uint256) { + function _getDynamicDataLengthLocation( + ResourceId tableId, + bytes32[] memory keyTuple + ) internal pure returns (uint256) { return uint256(DYNAMIC_DATA_LENGTH_SLOT ^ keccak256(abi.encodePacked(tableId, keyTuple))); } @@ -946,7 +955,7 @@ library StoreCoreInternal { * Load the encoded dynamic data length from storage for the given table ID and key tuple */ function _loadEncodedDynamicDataLength( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple ) internal view returns (PackedCounter) { // Load dynamic data length from storage diff --git a/packages/store/src/StoreHook.sol b/packages/store/src/StoreHook.sol index ca854c06fa..19db392bb7 100644 --- a/packages/store/src/StoreHook.sol +++ b/packages/store/src/StoreHook.sol @@ -5,6 +5,7 @@ import { IStoreHook, STORE_HOOK_INTERFACE_ID } from "./IStoreHook.sol"; import { ERC165_INTERFACE_ID } from "./IERC165.sol"; import { PackedCounter } from "./PackedCounter.sol"; import { FieldLayout } from "./FieldLayout.sol"; +import { ResourceId } from "./ResourceId.sol"; abstract contract StoreHook is IStoreHook { // ERC-165 supportsInterface (see https://eips.ethereum.org/EIPS/eip-165) @@ -13,7 +14,7 @@ abstract contract StoreHook is IStoreHook { } function onBeforeSetRecord( - bytes32, + ResourceId, bytes32[] memory, bytes memory, PackedCounter, @@ -24,7 +25,7 @@ abstract contract StoreHook is IStoreHook { } function onAfterSetRecord( - bytes32, + ResourceId, bytes32[] memory, bytes memory, PackedCounter, @@ -34,16 +35,16 @@ abstract contract StoreHook is IStoreHook { revert StoreHook_NotImplemented(); } - function onBeforeSpliceStaticData(bytes32, bytes32[] memory, uint48, uint40, bytes memory) public virtual { + function onBeforeSpliceStaticData(ResourceId, bytes32[] memory, uint48, uint40, bytes memory) public virtual { revert StoreHook_NotImplemented(); } - function onAfterSpliceStaticData(bytes32, bytes32[] memory, uint48, uint40, bytes memory) public virtual { + function onAfterSpliceStaticData(ResourceId, bytes32[] memory, uint48, uint40, bytes memory) public virtual { revert StoreHook_NotImplemented(); } function onBeforeSpliceDynamicData( - bytes32, + ResourceId, bytes32[] memory, uint8, uint40, @@ -55,7 +56,7 @@ abstract contract StoreHook is IStoreHook { } function onAfterSpliceDynamicData( - bytes32, + ResourceId, bytes32[] memory, uint8, uint40, @@ -66,11 +67,11 @@ abstract contract StoreHook is IStoreHook { revert StoreHook_NotImplemented(); } - function onBeforeDeleteRecord(bytes32, bytes32[] memory, FieldLayout) public virtual { + function onBeforeDeleteRecord(ResourceId, bytes32[] memory, FieldLayout) public virtual { revert StoreHook_NotImplemented(); } - function onAfterDeleteRecord(bytes32, bytes32[] memory, FieldLayout) public virtual { + function onAfterDeleteRecord(ResourceId, bytes32[] memory, FieldLayout) public virtual { revert StoreHook_NotImplemented(); } } diff --git a/packages/store/src/StoreRead.sol b/packages/store/src/StoreRead.sol index 5d85bef3e6..f4925e77eb 100644 --- a/packages/store/src/StoreRead.sol +++ b/packages/store/src/StoreRead.sol @@ -7,26 +7,27 @@ import { StoreCore } from "./StoreCore.sol"; import { FieldLayout } from "./FieldLayout.sol"; import { Schema } from "./Schema.sol"; import { PackedCounter } from "./PackedCounter.sol"; +import { ResourceId } from "./ResourceId.sol"; contract StoreRead is IStoreRead { function storeVersion() public pure returns (bytes32) { return STORE_VERSION; } - function getFieldLayout(bytes32 tableId) public view virtual returns (FieldLayout fieldLayout) { + function getFieldLayout(ResourceId tableId) public view virtual returns (FieldLayout fieldLayout) { fieldLayout = StoreCore.getFieldLayout(tableId); } - function getValueSchema(bytes32 tableId) public view virtual returns (Schema valueSchema) { + function getValueSchema(ResourceId tableId) public view virtual returns (Schema valueSchema) { valueSchema = StoreCore.getValueSchema(tableId); } - function getKeySchema(bytes32 tableId) public view virtual returns (Schema keySchema) { + function getKeySchema(ResourceId tableId) public view virtual returns (Schema keySchema) { keySchema = StoreCore.getKeySchema(tableId); } function getRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, FieldLayout fieldLayout ) public view virtual returns (bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData) { @@ -34,7 +35,7 @@ contract StoreRead is IStoreRead { } function getField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -43,7 +44,7 @@ contract StoreRead is IStoreRead { } function getStaticField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -52,7 +53,7 @@ contract StoreRead is IStoreRead { } function getDynamicField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 dynamicFieldIndex ) public view virtual returns (bytes memory data) { @@ -60,7 +61,7 @@ contract StoreRead is IStoreRead { } function getFieldLength( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -69,7 +70,7 @@ contract StoreRead is IStoreRead { } function getFieldSlice( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout, diff --git a/packages/store/src/StoreSwitch.sol b/packages/store/src/StoreSwitch.sol index 396b246010..caa043ebfe 100644 --- a/packages/store/src/StoreSwitch.sol +++ b/packages/store/src/StoreSwitch.sol @@ -8,6 +8,7 @@ import { StoreCore } from "./StoreCore.sol"; import { Schema } from "./Schema.sol"; import { FieldLayout } from "./FieldLayout.sol"; import { PackedCounter } from "./PackedCounter.sol"; +import { ResourceId } from "./ResourceId.sol"; /** * Call IStore functions on self or msg.sender, depending on whether the call is a delegatecall or regular call. @@ -48,7 +49,7 @@ library StoreSwitch { _layout().storeAddress = _storeAddress; } - function registerStoreHook(bytes32 tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) internal { + function registerStoreHook(ResourceId tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) internal { address _storeAddress = getStoreAddress(); if (_storeAddress == address(this)) { StoreCore.registerStoreHook(tableId, hookAddress, enabledHooksBitmap); @@ -57,7 +58,7 @@ library StoreSwitch { } } - function unregisterStoreHook(bytes32 tableId, IStoreHook hookAddress) internal { + function unregisterStoreHook(ResourceId tableId, IStoreHook hookAddress) internal { address _storeAddress = getStoreAddress(); if (_storeAddress == address(this)) { StoreCore.unregisterStoreHook(tableId, hookAddress); @@ -66,7 +67,7 @@ library StoreSwitch { } } - function getFieldLayout(bytes32 tableId) internal view returns (FieldLayout fieldLayout) { + function getFieldLayout(ResourceId tableId) internal view returns (FieldLayout fieldLayout) { address _storeAddress = getStoreAddress(); if (_storeAddress == address(this)) { fieldLayout = StoreCore.getFieldLayout(tableId); @@ -75,7 +76,7 @@ library StoreSwitch { } } - function getValueSchema(bytes32 tableId) internal view returns (Schema valueSchema) { + function getValueSchema(ResourceId tableId) internal view returns (Schema valueSchema) { address _storeAddress = getStoreAddress(); if (_storeAddress == address(this)) { valueSchema = StoreCore.getValueSchema(tableId); @@ -84,7 +85,7 @@ library StoreSwitch { } } - function getKeySchema(bytes32 tableId) internal view returns (Schema keySchema) { + function getKeySchema(ResourceId tableId) internal view returns (Schema keySchema) { address _storeAddress = getStoreAddress(); if (_storeAddress == address(this)) { keySchema = StoreCore.getKeySchema(tableId); @@ -94,7 +95,7 @@ library StoreSwitch { } function registerTable( - bytes32 tableId, + ResourceId tableId, FieldLayout fieldLayout, Schema keySchema, Schema valueSchema, @@ -110,7 +111,7 @@ library StoreSwitch { } function setRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, bytes memory staticData, PackedCounter encodedLengths, @@ -126,7 +127,7 @@ library StoreSwitch { } function spliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint48 start, uint40 deleteCount, @@ -141,7 +142,7 @@ library StoreSwitch { } function spliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -164,7 +165,7 @@ library StoreSwitch { } function setField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, bytes memory data, @@ -179,7 +180,7 @@ library StoreSwitch { } function pushToField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, bytes memory dataToPush, @@ -194,7 +195,7 @@ library StoreSwitch { } function popFromField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, uint256 byteLengthToPop, @@ -209,7 +210,7 @@ library StoreSwitch { } function updateInField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, uint256 startByteIndex, @@ -224,7 +225,7 @@ library StoreSwitch { } } - function deleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) internal { + function deleteRecord(ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) internal { address _storeAddress = getStoreAddress(); if (_storeAddress == address(this)) { StoreCore.deleteRecord(tableId, keyTuple, fieldLayout); @@ -234,7 +235,7 @@ library StoreSwitch { } function emitEphemeralRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, bytes memory staticData, PackedCounter encodedLengths, @@ -257,7 +258,7 @@ library StoreSwitch { } function getRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout ) internal view returns (bytes memory, PackedCounter, bytes memory) { @@ -270,7 +271,7 @@ library StoreSwitch { } function getField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -284,7 +285,7 @@ library StoreSwitch { } function getStaticField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -298,7 +299,7 @@ library StoreSwitch { } function getDynamicField( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex ) internal view returns (bytes memory) { @@ -311,7 +312,7 @@ library StoreSwitch { } function getFieldLength( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout @@ -325,7 +326,7 @@ library StoreSwitch { } function getFieldSlice( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout, diff --git a/packages/store/src/codegen/index.sol b/packages/store/src/codegen/index.sol index 64381605a6..7e033ae735 100644 --- a/packages/store/src/codegen/index.sol +++ b/packages/store/src/codegen/index.sol @@ -6,6 +6,7 @@ pragma solidity >=0.8.0; import { StoreHooks, StoreHooksTableId } from "./tables/StoreHooks.sol"; import { Callbacks, CallbacksTableId } from "./tables/Callbacks.sol"; import { Tables, TablesData, TablesTableId } from "./tables/Tables.sol"; +import { ResourceIds, ResourceIdsTableId } from "./tables/ResourceIds.sol"; import { Hooks } from "./tables/Hooks.sol"; import { Mixed, MixedData, MixedTableId } from "./tables/Mixed.sol"; import { Vector2, Vector2Data, Vector2TableId } from "./tables/Vector2.sol"; diff --git a/packages/store/src/codegen/tables/Callbacks.sol b/packages/store/src/codegen/tables/Callbacks.sol index f13f8f9f9e..e7c1e00837 100644 --- a/packages/store/src/codegen/tables/Callbacks.sol +++ b/packages/store/src/codegen/tables/Callbacks.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "../../tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "../../FieldLayout.sol"; import { Schema, SchemaLib } from "../../Schema.sol"; import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; +import { ResourceId } from "../../ResourceId.sol"; +import { RESOURCE_TABLE } from "../../storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("Callbacks"))); -bytes32 constant CallbacksTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("Callbacks"))) +); +ResourceId constant CallbacksTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 diff --git a/packages/store/src/codegen/tables/Hooks.sol b/packages/store/src/codegen/tables/Hooks.sol index 28c6a546bc..ed26828797 100644 --- a/packages/store/src/codegen/tables/Hooks.sol +++ b/packages/store/src/codegen/tables/Hooks.sol @@ -17,6 +17,8 @@ import { EncodeArray } from "../../tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "../../FieldLayout.sol"; import { Schema, SchemaLib } from "../../Schema.sol"; import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; +import { ResourceId } from "../../ResourceId.sol"; +import { RESOURCE_TABLE } from "../../storeResourceTypes.sol"; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 @@ -57,22 +59,22 @@ library Hooks { } /** Register the table with its config */ - function register(bytes32 _tableId) internal { + function register(ResourceId _tableId) internal { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config */ - function _register(bytes32 _tableId) internal { + function _register(ResourceId _tableId) internal { StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ - function register(IStore _store, bytes32 _tableId) internal { + function register(IStore _store, ResourceId _tableId) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ - function getValue(bytes32 _tableId, bytes32 key) internal view returns (bytes21[] memory value) { + function getValue(ResourceId _tableId, bytes32 key) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -81,7 +83,7 @@ library Hooks { } /** Get value */ - function _getValue(bytes32 _tableId, bytes32 key) internal view returns (bytes21[] memory value) { + function _getValue(ResourceId _tableId, bytes32 key) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -90,7 +92,7 @@ library Hooks { } /** Get value (using the specified store) */ - function getValue(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (bytes21[] memory value) { + function getValue(IStore _store, ResourceId _tableId, bytes32 key) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -99,7 +101,7 @@ library Hooks { } /** Get value */ - function get(bytes32 _tableId, bytes32 key) internal view returns (bytes21[] memory value) { + function get(ResourceId _tableId, bytes32 key) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -108,7 +110,7 @@ library Hooks { } /** Get value */ - function _get(bytes32 _tableId, bytes32 key) internal view returns (bytes21[] memory value) { + function _get(ResourceId _tableId, bytes32 key) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -117,7 +119,7 @@ library Hooks { } /** Get value (using the specified store) */ - function get(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (bytes21[] memory value) { + function get(IStore _store, ResourceId _tableId, bytes32 key) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -126,7 +128,7 @@ library Hooks { } /** Set value */ - function setValue(bytes32 _tableId, bytes32 key, bytes21[] memory value) internal { + function setValue(ResourceId _tableId, bytes32 key, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -134,7 +136,7 @@ library Hooks { } /** Set value */ - function _setValue(bytes32 _tableId, bytes32 key, bytes21[] memory value) internal { + function _setValue(ResourceId _tableId, bytes32 key, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -142,7 +144,7 @@ library Hooks { } /** Set value (using the specified store) */ - function setValue(IStore _store, bytes32 _tableId, bytes32 key, bytes21[] memory value) internal { + function setValue(IStore _store, ResourceId _tableId, bytes32 key, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -150,7 +152,7 @@ library Hooks { } /** Set value */ - function set(bytes32 _tableId, bytes32 key, bytes21[] memory value) internal { + function set(ResourceId _tableId, bytes32 key, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -158,7 +160,7 @@ library Hooks { } /** Set value */ - function _set(bytes32 _tableId, bytes32 key, bytes21[] memory value) internal { + function _set(ResourceId _tableId, bytes32 key, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -166,7 +168,7 @@ library Hooks { } /** Set value (using the specified store) */ - function set(IStore _store, bytes32 _tableId, bytes32 key, bytes21[] memory value) internal { + function set(IStore _store, ResourceId _tableId, bytes32 key, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -174,7 +176,7 @@ library Hooks { } /** Get the length of value */ - function lengthValue(bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function lengthValue(ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -185,7 +187,7 @@ library Hooks { } /** Get the length of value */ - function _lengthValue(bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function _lengthValue(ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -196,7 +198,7 @@ library Hooks { } /** Get the length of value (using the specified store) */ - function lengthValue(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function lengthValue(IStore _store, ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -207,7 +209,7 @@ library Hooks { } /** Get the length of value */ - function length(bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function length(ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -218,7 +220,7 @@ library Hooks { } /** Get the length of value */ - function _length(bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function _length(ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -229,7 +231,7 @@ library Hooks { } /** Get the length of value (using the specified store) */ - function length(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function length(IStore _store, ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -243,7 +245,7 @@ library Hooks { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function getItemValue(bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { + function getItemValue(ResourceId _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -264,7 +266,7 @@ library Hooks { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function _getItemValue(bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { + function _getItemValue(ResourceId _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -285,7 +287,12 @@ library Hooks { * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) */ - function getItemValue(IStore _store, bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { + function getItemValue( + IStore _store, + ResourceId _tableId, + bytes32 key, + uint256 _index + ) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -299,7 +306,7 @@ library Hooks { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function getItem(bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { + function getItem(ResourceId _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -320,7 +327,7 @@ library Hooks { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function _getItem(bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { + function _getItem(ResourceId _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -341,7 +348,7 @@ library Hooks { * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) */ - function getItem(IStore _store, bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { + function getItem(IStore _store, ResourceId _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -352,7 +359,7 @@ library Hooks { } /** Push an element to value */ - function pushValue(bytes32 _tableId, bytes32 key, bytes21 _element) internal { + function pushValue(ResourceId _tableId, bytes32 key, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -360,7 +367,7 @@ library Hooks { } /** Push an element to value */ - function _pushValue(bytes32 _tableId, bytes32 key, bytes21 _element) internal { + function _pushValue(ResourceId _tableId, bytes32 key, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -368,7 +375,7 @@ library Hooks { } /** Push an element to value (using the specified store) */ - function pushValue(IStore _store, bytes32 _tableId, bytes32 key, bytes21 _element) internal { + function pushValue(IStore _store, ResourceId _tableId, bytes32 key, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -376,7 +383,7 @@ library Hooks { } /** Push an element to value */ - function push(bytes32 _tableId, bytes32 key, bytes21 _element) internal { + function push(ResourceId _tableId, bytes32 key, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -384,7 +391,7 @@ library Hooks { } /** Push an element to value */ - function _push(bytes32 _tableId, bytes32 key, bytes21 _element) internal { + function _push(ResourceId _tableId, bytes32 key, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -392,7 +399,7 @@ library Hooks { } /** Push an element to value (using the specified store) */ - function push(IStore _store, bytes32 _tableId, bytes32 key, bytes21 _element) internal { + function push(IStore _store, ResourceId _tableId, bytes32 key, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -400,7 +407,7 @@ library Hooks { } /** Pop an element from value */ - function popValue(bytes32 _tableId, bytes32 key) internal { + function popValue(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -408,7 +415,7 @@ library Hooks { } /** Pop an element from value */ - function _popValue(bytes32 _tableId, bytes32 key) internal { + function _popValue(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -416,7 +423,7 @@ library Hooks { } /** Pop an element from value (using the specified store) */ - function popValue(IStore _store, bytes32 _tableId, bytes32 key) internal { + function popValue(IStore _store, ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -424,7 +431,7 @@ library Hooks { } /** Pop an element from value */ - function pop(bytes32 _tableId, bytes32 key) internal { + function pop(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -432,7 +439,7 @@ library Hooks { } /** Pop an element from value */ - function _pop(bytes32 _tableId, bytes32 key) internal { + function _pop(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -440,7 +447,7 @@ library Hooks { } /** Pop an element from value (using the specified store) */ - function pop(IStore _store, bytes32 _tableId, bytes32 key) internal { + function pop(IStore _store, ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -451,7 +458,7 @@ library Hooks { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function updateValue(bytes32 _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { + function updateValue(ResourceId _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -464,7 +471,7 @@ library Hooks { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function _updateValue(bytes32 _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { + function _updateValue(ResourceId _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -477,7 +484,7 @@ library Hooks { * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function updateValue(IStore _store, bytes32 _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { + function updateValue(IStore _store, ResourceId _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -490,7 +497,7 @@ library Hooks { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function update(bytes32 _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { + function update(ResourceId _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -503,7 +510,7 @@ library Hooks { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function _update(bytes32 _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { + function _update(ResourceId _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -516,7 +523,7 @@ library Hooks { * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function update(IStore _store, bytes32 _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { + function update(IStore _store, ResourceId _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -556,7 +563,7 @@ library Hooks { } /* Delete all data for given keys */ - function deleteRecord(bytes32 _tableId, bytes32 key) internal { + function deleteRecord(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -564,7 +571,7 @@ library Hooks { } /* Delete all data for given keys */ - function _deleteRecord(bytes32 _tableId, bytes32 key) internal { + function _deleteRecord(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -572,7 +579,7 @@ library Hooks { } /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 _tableId, bytes32 key) internal { + function deleteRecord(IStore _store, ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; diff --git a/packages/store/src/codegen/tables/KeyEncoding.sol b/packages/store/src/codegen/tables/KeyEncoding.sol index 132acd4eb1..4f5afd260d 100644 --- a/packages/store/src/codegen/tables/KeyEncoding.sol +++ b/packages/store/src/codegen/tables/KeyEncoding.sol @@ -17,12 +17,16 @@ import { EncodeArray } from "../../tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "../../FieldLayout.sol"; import { Schema, SchemaLib } from "../../Schema.sol"; import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; +import { ResourceId } from "../../ResourceId.sol"; +import { RESOURCE_TABLE } from "../../storeResourceTypes.sol"; // Import user types import { ExampleEnum } from "./../common.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("KeyEncoding"))); -bytes32 constant KeyEncodingTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("KeyEncoding"))) +); +ResourceId constant KeyEncodingTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0001010001000000000000000000000000000000000000000000000000000000 diff --git a/packages/store/src/codegen/tables/Mixed.sol b/packages/store/src/codegen/tables/Mixed.sol index f4b9e76651..995a84f49c 100644 --- a/packages/store/src/codegen/tables/Mixed.sol +++ b/packages/store/src/codegen/tables/Mixed.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "../../tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "../../FieldLayout.sol"; import { Schema, SchemaLib } from "../../Schema.sol"; import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; +import { ResourceId } from "../../ResourceId.sol"; +import { RESOURCE_TABLE } from "../../storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("Mixed"))); -bytes32 constant MixedTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("Mixed"))) +); +ResourceId constant MixedTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0014020204100000000000000000000000000000000000000000000000000000 diff --git a/packages/store/src/codegen/tables/ResourceIds.sol b/packages/store/src/codegen/tables/ResourceIds.sol new file mode 100644 index 0000000000..229d236416 --- /dev/null +++ b/packages/store/src/codegen/tables/ResourceIds.sol @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +/* Autogenerated file. Do not edit manually. */ + +// Import schema type +import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; + +// Import store internals +import { IStore } from "../../IStore.sol"; +import { StoreSwitch } from "../../StoreSwitch.sol"; +import { StoreCore } from "../../StoreCore.sol"; +import { Bytes } from "../../Bytes.sol"; +import { Memory } from "../../Memory.sol"; +import { SliceLib } from "../../Slice.sol"; +import { EncodeArray } from "../../tightcoder/EncodeArray.sol"; +import { FieldLayout, FieldLayoutLib } from "../../FieldLayout.sol"; +import { Schema, SchemaLib } from "../../Schema.sol"; +import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; +import { ResourceId } from "../../ResourceId.sol"; +import { RESOURCE_TABLE } from "../../storeResourceTypes.sol"; + +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("ResourceIds"))) +); +ResourceId constant ResourceIdsTableId = _tableId; + +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0001010001000000000000000000000000000000000000000000000000000000 +); + +library ResourceIds { + /** Get the table values' field layout */ + function getFieldLayout() internal pure returns (FieldLayout) { + return _fieldLayout; + } + + /** Get the table's key schema */ + function getKeySchema() internal pure returns (Schema) { + SchemaType[] memory _keySchema = new SchemaType[](1); + _keySchema[0] = SchemaType.BYTES32; + + return SchemaLib.encode(_keySchema); + } + + /** Get the table's value schema */ + function getValueSchema() internal pure returns (Schema) { + SchemaType[] memory _valueSchema = new SchemaType[](1); + _valueSchema[0] = SchemaType.BOOL; + + return SchemaLib.encode(_valueSchema); + } + + /** Get the table's key names */ + function getKeyNames() internal pure returns (string[] memory keyNames) { + keyNames = new string[](1); + keyNames[0] = "resourceId"; + } + + /** Get the table's field names */ + function getFieldNames() internal pure returns (string[] memory fieldNames) { + fieldNames = new string[](1); + fieldNames[0] = "exists"; + } + + /** Register the table with its config */ + function register() internal { + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + + /** Register the table with its config (using the specified store) */ + function register(IStore _store) internal { + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + + /** Get exists */ + function getExists(bytes32 resourceId) internal view returns (bool exists) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + + /** Get exists */ + function _getExists(bytes32 resourceId) internal view returns (bool exists) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + + /** Get exists (using the specified store) */ + function getExists(IStore _store, bytes32 resourceId) internal view returns (bool exists) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + + /** Get exists */ + function get(bytes32 resourceId) internal view returns (bool exists) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + + /** Get exists */ + function _get(bytes32 resourceId) internal view returns (bool exists) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + + /** Get exists (using the specified store) */ + function get(IStore _store, bytes32 resourceId) internal view returns (bool exists) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + + /** Set exists */ + function setExists(bytes32 resourceId, bool exists) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); + } + + /** Set exists */ + function _setExists(bytes32 resourceId, bool exists) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); + } + + /** Set exists (using the specified store) */ + function setExists(IStore _store, bytes32 resourceId, bool exists) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); + } + + /** Set exists */ + function set(bytes32 resourceId, bool exists) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); + } + + /** Set exists */ + function _set(bytes32 resourceId, bool exists) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); + } + + /** Set exists (using the specified store) */ + function set(IStore _store, bytes32 resourceId, bool exists) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); + } + + /** Tightly pack static data using this table's schema */ + function encodeStatic(bool exists) internal pure returns (bytes memory) { + return abi.encodePacked(exists); + } + + /** Tightly pack full data using this table's field layout */ + function encode(bool exists) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(exists); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** Encode keys as a bytes32 array using this table's field layout */ + function encodeKeyTuple(bytes32 resourceId) internal pure returns (bytes32[] memory) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + return _keyTuple; + } + + /* Delete all data for given keys */ + function deleteRecord(bytes32 resourceId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /* Delete all data for given keys */ + function _deleteRecord(bytes32 resourceId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /* Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 resourceId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceId; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } +} + +function _toBool(uint8 value) pure returns (bool result) { + assembly { + result := value + } +} diff --git a/packages/store/src/codegen/tables/StoreHooks.sol b/packages/store/src/codegen/tables/StoreHooks.sol index 11c11e6c84..bba07c02cd 100644 --- a/packages/store/src/codegen/tables/StoreHooks.sol +++ b/packages/store/src/codegen/tables/StoreHooks.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "../../tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "../../FieldLayout.sol"; import { Schema, SchemaLib } from "../../Schema.sol"; import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; +import { ResourceId } from "../../ResourceId.sol"; +import { RESOURCE_TABLE } from "../../storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("StoreHooks"))); -bytes32 constant StoreHooksTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("StoreHooks"))) +); +ResourceId constant StoreHooksTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 diff --git a/packages/store/src/codegen/tables/Tables.sol b/packages/store/src/codegen/tables/Tables.sol index dbf0de5289..3e4c7b0724 100644 --- a/packages/store/src/codegen/tables/Tables.sol +++ b/packages/store/src/codegen/tables/Tables.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "../../tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "../../FieldLayout.sol"; import { Schema, SchemaLib } from "../../Schema.sol"; import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; +import { ResourceId } from "../../ResourceId.sol"; +import { RESOURCE_TABLE } from "../../storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("Tables"))); -bytes32 constant TablesTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("Tables"))) +); +ResourceId constant TablesTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0060030220202000000000000000000000000000000000000000000000000000 diff --git a/packages/store/src/codegen/tables/Vector2.sol b/packages/store/src/codegen/tables/Vector2.sol index 58402ad8b5..cb95a745ea 100644 --- a/packages/store/src/codegen/tables/Vector2.sol +++ b/packages/store/src/codegen/tables/Vector2.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "../../tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "../../FieldLayout.sol"; import { Schema, SchemaLib } from "../../Schema.sol"; import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; +import { ResourceId } from "../../ResourceId.sol"; +import { RESOURCE_TABLE } from "../../storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("Vector2"))); -bytes32 constant Vector2TableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("Vector2"))) +); +ResourceId constant Vector2TableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0008020004040000000000000000000000000000000000000000000000000000 diff --git a/packages/store/src/storeResourceTypes.sol b/packages/store/src/storeResourceTypes.sol new file mode 100644 index 0000000000..5854db2429 --- /dev/null +++ b/packages/store/src/storeResourceTypes.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +bytes2 constant RESOURCE_TABLE = "tb"; +bytes2 constant RESOURCE_OFFCHAIN_TABLE = "ot"; diff --git a/packages/store/test/EchoSubscriber.sol b/packages/store/test/EchoSubscriber.sol index acaf3b50ab..90e9ca592f 100644 --- a/packages/store/test/EchoSubscriber.sol +++ b/packages/store/test/EchoSubscriber.sol @@ -4,12 +4,13 @@ pragma solidity >=0.8.0; import { PackedCounter } from "../src/PackedCounter.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; import { StoreHook } from "../src/StoreHook.sol"; +import { ResourceId } from "../src/ResourceId.sol"; contract EchoSubscriber is StoreHook { event HookCalled(bytes); function onBeforeSetRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, bytes memory staticData, PackedCounter encodedLengths, @@ -22,7 +23,7 @@ contract EchoSubscriber is StoreHook { } function onAfterSetRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, bytes memory staticData, PackedCounter encodedLengths, @@ -35,7 +36,7 @@ contract EchoSubscriber is StoreHook { } function onBeforeSpliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint48 start, uint40 deleteCount, @@ -45,7 +46,7 @@ contract EchoSubscriber is StoreHook { } function onAfterSpliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint48 start, uint40 deleteCount, @@ -55,7 +56,7 @@ contract EchoSubscriber is StoreHook { } function onBeforeSpliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -72,7 +73,7 @@ contract EchoSubscriber is StoreHook { } function onAfterSpliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -88,11 +89,15 @@ contract EchoSubscriber is StoreHook { ); } - function onBeforeDeleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) public override { + function onBeforeDeleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + FieldLayout fieldLayout + ) public override { emit HookCalled(abi.encodeCall(this.onBeforeDeleteRecord, (tableId, keyTuple, fieldLayout))); } - function onAfterDeleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) public override { + function onAfterDeleteRecord(ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) public override { emit HookCalled(abi.encodeCall(this.onAfterDeleteRecord, (tableId, keyTuple, fieldLayout))); } } diff --git a/packages/store/test/MirrorSubscriber.sol b/packages/store/test/MirrorSubscriber.sol index 3c86958cd6..e646d3634d 100644 --- a/packages/store/test/MirrorSubscriber.sol +++ b/packages/store/test/MirrorSubscriber.sol @@ -7,14 +7,18 @@ import { PackedCounter } from "../src/PackedCounter.sol"; import { StoreSwitch } from "../src/StoreSwitch.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; import { Schema } from "../src/Schema.sol"; +import { ResourceId } from "../src/ResourceId.sol"; +import { RESOURCE_TABLE } from "../src/storeResourceTypes.sol"; -bytes32 constant indexerTableId = keccak256("indexer.tableId"); +ResourceId constant indexerTableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mirror"), bytes16("indexer"))) +); contract MirrorSubscriber is StoreHook { bytes32 public _tableId; constructor( - bytes32 tableId, + ResourceId tableId, FieldLayout fieldLayout, Schema keySchema, Schema valueSchema, @@ -22,34 +26,34 @@ contract MirrorSubscriber is StoreHook { string[] memory fieldNames ) { IStore(msg.sender).registerTable(indexerTableId, fieldLayout, keySchema, valueSchema, keyNames, fieldNames); - _tableId = tableId; + _tableId = ResourceId.unwrap(tableId); } function onBeforeSetRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData, FieldLayout fieldLayout ) public override { - if (tableId != _tableId) revert("invalid table"); + if (ResourceId.unwrap(tableId) != _tableId) revert("invalid table"); StoreSwitch.setRecord(indexerTableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); } function onBeforeSpliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint48 start, uint40 deleteCount, bytes memory data ) public override { - if (tableId != _tableId) revert("invalid tableId"); + if (ResourceId.unwrap(tableId) != _tableId) revert("invalid tableId"); StoreSwitch.spliceStaticData(indexerTableId, keyTuple, start, deleteCount, data); } function onBeforeSpliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -57,12 +61,12 @@ contract MirrorSubscriber is StoreHook { bytes memory data, PackedCounter ) public override { - if (tableId != _tableId) revert("invalid tableId"); + if (ResourceId.unwrap(tableId) != _tableId) revert("invalid tableId"); StoreSwitch.spliceDynamicData(indexerTableId, keyTuple, dynamicFieldIndex, startWithinField, deleteCount, data); } function onAfterSpliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -70,12 +74,16 @@ contract MirrorSubscriber is StoreHook { bytes memory data, PackedCounter ) public override { - if (tableId != _tableId) revert("invalid tableId"); + if (ResourceId.unwrap(tableId) != _tableId) revert("invalid tableId"); StoreSwitch.spliceDynamicData(indexerTableId, keyTuple, dynamicFieldIndex, startWithinField, deleteCount, data); } - function onBeforeDeleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) public override { - if (tableId != tableId) revert("invalid tableId"); + function onBeforeDeleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + FieldLayout fieldLayout + ) public override { + if (ResourceId.unwrap(tableId) != _tableId) revert("invalid tableId"); StoreSwitch.deleteRecord(indexerTableId, keyTuple, fieldLayout); } } diff --git a/packages/store/test/ResourceId.t.sol b/packages/store/test/ResourceId.t.sol new file mode 100644 index 0000000000..d64afe4f53 --- /dev/null +++ b/packages/store/test/ResourceId.t.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import { Test, console } from "forge-std/Test.sol"; +import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; +import { ResourceId } from "../src/ResourceId.sol"; +import { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "../src/storeResourceTypes.sol"; +import { ResourceId, ResourceIdInstance, ResourceIdLib } from "../src/ResourceId.sol"; + +contract ResourceIdTest is Test, GasReporter { + using ResourceIdInstance for ResourceId; + + function testEncode() public { + startGasReport("encode table ID with name and type"); + ResourceId tableId = ResourceIdLib.encode({ typeId: RESOURCE_TABLE, name: "name" }); + endGasReport(); + + assertEq(ResourceId.unwrap(tableId), bytes32(abi.encodePacked(RESOURCE_TABLE, bytes30("name")))); + } + + function testGetType() public { + ResourceId tableId = ResourceIdLib.encode({ typeId: RESOURCE_TABLE, name: "name" }); + + startGasReport("get type from a table ID"); + bytes2 resourceType = tableId.getType(); + endGasReport(); + + assertEq(resourceType, RESOURCE_TABLE); + } + + function testFuzz(bytes30 name, bytes2 resourceType) public { + ResourceId tableId = ResourceIdLib.encode({ typeId: resourceType, name: name }); + assertEq(tableId.getType(), resourceType); + } +} diff --git a/packages/store/test/RevertSubscriber.sol b/packages/store/test/RevertSubscriber.sol index 7d706405d4..38e6810603 100644 --- a/packages/store/test/RevertSubscriber.sol +++ b/packages/store/test/RevertSubscriber.sol @@ -4,10 +4,11 @@ pragma solidity >=0.8.0; import { StoreHook } from "../src/StoreHook.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; import { PackedCounter } from "../src/PackedCounter.sol"; +import { ResourceId } from "../src/ResourceId.sol"; contract RevertSubscriber is StoreHook { function onBeforeSetRecord( - bytes32, + ResourceId, bytes32[] memory, bytes memory, PackedCounter, @@ -18,7 +19,7 @@ contract RevertSubscriber is StoreHook { } function onAfterSetRecord( - bytes32, + ResourceId, bytes32[] memory, bytes memory, PackedCounter, @@ -28,16 +29,16 @@ contract RevertSubscriber is StoreHook { revert("onAfterSetRecord"); } - function onBeforeSpliceStaticData(bytes32, bytes32[] memory, uint48, uint40, bytes memory) public pure override { + function onBeforeSpliceStaticData(ResourceId, bytes32[] memory, uint48, uint40, bytes memory) public pure override { revert("onBeforeSpliceStaticData"); } - function onAfterSpliceStaticData(bytes32, bytes32[] memory, uint48, uint40, bytes memory) public pure override { + function onAfterSpliceStaticData(ResourceId, bytes32[] memory, uint48, uint40, bytes memory) public pure override { revert("onAfterSpliceStaticData"); } function onBeforeSpliceDynamicData( - bytes32, + ResourceId, bytes32[] memory, uint8, uint40, @@ -49,7 +50,7 @@ contract RevertSubscriber is StoreHook { } function onAfterSpliceDynamicData( - bytes32, + ResourceId, bytes32[] memory, uint8, uint40, @@ -60,11 +61,11 @@ contract RevertSubscriber is StoreHook { revert("onAfterSpliceDynamicData"); } - function onBeforeDeleteRecord(bytes32, bytes32[] memory, FieldLayout) public pure override { + function onBeforeDeleteRecord(ResourceId, bytes32[] memory, FieldLayout) public pure override { revert("onBeforeDeleteRecord"); } - function onAfterDeleteRecord(bytes32, bytes32[] memory, FieldLayout) public pure override { + function onAfterDeleteRecord(ResourceId, bytes32[] memory, FieldLayout) public pure override { revert("onAfterDeleteRecord"); } } diff --git a/packages/store/test/StoreCore.t.sol b/packages/store/test/StoreCore.t.sol index 132b198940..9c96aecb80 100644 --- a/packages/store/test/StoreCore.t.sol +++ b/packages/store/test/StoreCore.t.sol @@ -7,7 +7,7 @@ import { StoreCore, StoreCoreInternal } from "../src/StoreCore.sol"; import { Bytes } from "../src/Bytes.sol"; import { SliceLib } from "../src/Slice.sol"; import { EncodeArray } from "../src/tightcoder/EncodeArray.sol"; -import { FieldLayout } from "../src/FieldLayout.sol"; +import { FieldLayout, FieldLayoutLib } from "../src/FieldLayout.sol"; import { Schema } from "../src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "../src/PackedCounter.sol"; import { StoreMock } from "../test/StoreMock.sol"; @@ -15,7 +15,9 @@ import { IStoreErrors } from "../src/IStoreErrors.sol"; import { IStore } from "../src/IStore.sol"; import { StoreSwitch } from "../src/StoreSwitch.sol"; import { IStoreHook } from "../src/IStoreHook.sol"; -import { Tables, TablesTableId } from "../src/codegen/index.sol"; +import { Tables, ResourceIds, TablesTableId } from "../src/codegen/index.sol"; +import { ResourceId, ResourceIdLib, ResourceIdInstance } from "../src/ResourceId.sol"; +import { RESOURCE_TABLE } from "../src/storeResourceTypes.sol"; import { FieldLayoutEncodeHelper } from "./FieldLayoutEncodeHelper.sol"; import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SPLICE_STATIC_DATA, AFTER_SPLICE_STATIC_DATA, BEFORE_SPLICE_DYNAMIC_DATA, AFTER_SPLICE_DYNAMIC_DATA, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD, ALL, BEFORE_ALL, AFTER_ALL } from "../src/storeHookTypes.sol"; import { SchemaEncodeHelper } from "./SchemaEncodeHelper.sol"; @@ -32,14 +34,20 @@ struct TestStruct { } contract StoreCoreTest is Test, StoreMock { + using ResourceIdInstance for ResourceId; + TestStruct private testStruct; event HookCalled(bytes); mapping(uint256 => bytes) private testMapping; Schema defaultKeySchema = SchemaEncodeHelper.encode(SchemaType.BYTES32); string[] defaultKeyNames = new string[](1); + ResourceId _tableId = ResourceIdLib.encode({ typeId: RESOURCE_TABLE, name: "some table" }); + ResourceId _tableId2 = ResourceIdLib.encode({ typeId: RESOURCE_TABLE, name: "some other table" }); + + function testRegisterTable() public { + ResourceId tableId = _tableId; - function testRegisterAndGetFieldLayout() public { FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 2, 1, 2, 0); Schema keySchema = SchemaEncodeHelper.encode(SchemaType.UINT8, SchemaType.UINT16); Schema valueSchema = SchemaEncodeHelper.encode( @@ -57,11 +65,9 @@ contract StoreCoreTest is Test, StoreMock { fieldNames[2] = "value3"; fieldNames[3] = "value4"; - bytes32 tableId = keccak256("some.tableId"); - // Expect a StoreSetRecord event to be emitted bytes32[] memory keyTuple = new bytes32[](1); - keyTuple[0] = bytes32(tableId); + keyTuple[0] = ResourceId.unwrap(tableId); vm.expectEmit(true, true, true, true); emit StoreSetRecord( TablesTableId, @@ -76,18 +82,52 @@ contract StoreCoreTest is Test, StoreMock { assertEq(IStore(this).getValueSchema(tableId).unwrap(), valueSchema.unwrap()); assertEq(IStore(this).getKeySchema(tableId).unwrap(), keySchema.unwrap()); - bytes memory loadedKeyNames = Tables.getAbiEncodedKeyNames(IStore(this), tableId); + bytes memory loadedKeyNames = Tables.getAbiEncodedKeyNames(IStore(this), ResourceId.unwrap(tableId)); assertEq(loadedKeyNames, abi.encode(keyNames)); - bytes memory loadedFieldNames = Tables.getAbiEncodedFieldNames(IStore(this), tableId); + bytes memory loadedFieldNames = Tables.getAbiEncodedFieldNames(IStore(this), ResourceId.unwrap(tableId)); assertEq(loadedFieldNames, abi.encode(fieldNames)); + + // Expect the table ID to be registered + assertTrue(ResourceIds._getExists(ResourceId.unwrap(tableId))); } - function testFailRegisterInvalidFieldLayout() public { + function testRevertTableExists() public { + ResourceId tableId = _tableId; + FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 0); + Schema keySchema = SchemaEncodeHelper.encode(SchemaType.UINT8); + Schema valueSchema = SchemaEncodeHelper.encode(SchemaType.UINT8); + string[] memory keyNames = new string[](1); + string[] memory fieldNames = new string[](1); + + IStore(this).registerTable(tableId, fieldLayout, keySchema, valueSchema, keyNames, fieldNames); + + // Expect a revert when registering a table that already exists + vm.expectRevert( + abi.encodeWithSelector( + IStoreErrors.StoreCore_TableAlreadyExists.selector, + ResourceId.unwrap(tableId), + string(bytes.concat(ResourceId.unwrap(tableId))) + ) + ); + IStore(this).registerTable(tableId, fieldLayout, keySchema, valueSchema, keyNames, fieldNames); + } + + function testRevertRegisterInvalidFieldLayout() public { + ResourceId tableId = _tableId; + string[] memory keyNames = new string[](2); string[] memory fieldNames = new string[](4); + FieldLayout invalidFieldLayout = FieldLayout.wrap(keccak256("random bytes as value field layout")); + + vm.expectRevert( + abi.encodeWithSelector( + FieldLayoutLib.FieldLayoutLib_InvalidLength.selector, + invalidFieldLayout.numDynamicFields() + ) + ); IStore(this).registerTable( - keccak256("tableId"), + tableId, FieldLayout.wrap(keccak256("random bytes as value field layout")), Schema.wrap(keccak256("random bytes as key schema")), Schema.wrap(keccak256("random bytes as value schema")), @@ -96,7 +136,32 @@ contract StoreCoreTest is Test, StoreMock { ); } + function testRevertRegisterInvalidTableId() public { + bytes2 invalidType = "xx"; + ResourceId invalidTableId = ResourceIdLib.encode({ typeId: invalidType, name: "somename" }); + + vm.expectRevert( + abi.encodeWithSelector( + IStoreErrors.StoreCore_InvalidResourceType.selector, + RESOURCE_TABLE, + invalidTableId, + string(abi.encodePacked(invalidTableId)) + ) + ); + IStore(this).registerTable( + invalidTableId, + FieldLayoutEncodeHelper.encode(1, 0), + SchemaEncodeHelper.encode(SchemaType.UINT8), + SchemaEncodeHelper.encode(SchemaType.UINT8), + new string[](1), + new string[](1) + ); + } + function testHasFieldLayoutAndSchema() public { + ResourceId tableId = _tableId; + ResourceId tableId2 = _tableId2; + string[] memory keyNames = new string[](1); string[] memory fieldNames = new string[](4); FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 2, 1, 2, 0); @@ -106,12 +171,10 @@ contract StoreCoreTest is Test, StoreMock { SchemaType.UINT8, SchemaType.UINT16 ); - bytes32 tableId = keccak256("some.tableId"); - bytes32 tableId2 = keccak256("other.tableId"); IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, keyNames, fieldNames); - assertTrue(StoreCore.hasTable(tableId)); - assertFalse(StoreCore.hasTable(tableId2)); + assertTrue(ResourceIds._getExists(ResourceId.unwrap(tableId))); + assertFalse(ResourceIds._getExists(ResourceId.unwrap(tableId2))); IStore(this).getFieldLayout(tableId); IStore(this).getValueSchema(tableId); @@ -121,7 +184,7 @@ contract StoreCoreTest is Test, StoreMock { abi.encodeWithSelector( IStoreErrors.StoreCore_TableNotFound.selector, tableId2, - string(abi.encodePacked(tableId2)) + string(abi.encodePacked(ResourceId.unwrap(tableId2))) ) ); IStore(this).getFieldLayout(tableId2); @@ -146,7 +209,8 @@ contract StoreCoreTest is Test, StoreMock { } function testRegisterTableRevertNames() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; + FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 0); Schema keySchema = SchemaEncodeHelper.encode( SchemaType.UINT8, @@ -168,7 +232,7 @@ contract StoreCoreTest is Test, StoreMock { } function testSetAndGetDynamicDataLength() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 2, 4, 2); Schema valueSchema = SchemaEncodeHelper.encode( @@ -212,6 +276,8 @@ contract StoreCoreTest is Test, StoreMock { } function testSetAndGetStaticData() public { + ResourceId tableId = _tableId; + // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 2, 1, 2, 0); Schema valueSchema = SchemaEncodeHelper.encode( @@ -221,7 +287,6 @@ contract StoreCoreTest is Test, StoreMock { SchemaType.UINT16 ); - bytes32 tableId = keccak256("some.tableId"); IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](4)); // Set data @@ -248,7 +313,9 @@ contract StoreCoreTest is Test, StoreMock { assertEq(_dynamicData, ""); } - function testFailSetAndGetStaticData() public { + function testRevertSetAndGetStaticData() public { + ResourceId tableId = _tableId; + // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 2, 1, 2, 0); Schema valueSchema = SchemaEncodeHelper.encode( @@ -257,7 +324,6 @@ contract StoreCoreTest is Test, StoreMock { SchemaType.UINT8, SchemaType.UINT16 ); - bytes32 tableId = keccak256("some.tableId"); IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](4)); // Set data @@ -267,13 +333,15 @@ contract StoreCoreTest is Test, StoreMock { keyTuple[0] = "some key"; // This should fail because the data is not 6 bytes long + vm.expectRevert(abi.encodeWithSelector(IStoreErrors.StoreCore_InvalidStaticDataLength.selector, 6, 4)); IStore(this).setRecord(tableId, keyTuple, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout); } function testSetAndGetStaticDataSpanningWords() public { + ResourceId tableId = _tableId; + // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 32, 0); - bytes32 tableId = keccak256("some.table"); { Schema valueSchema = SchemaEncodeHelper.encode(SchemaType.UINT128, SchemaType.UINT256); IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](2)); @@ -307,7 +375,7 @@ contract StoreCoreTest is Test, StoreMock { } function testSetAndGetDynamicData() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 2); @@ -382,7 +450,7 @@ contract StoreCoreTest is Test, StoreMock { } struct SetAndGetData { - bytes32 tableId; + ResourceId tableId; FieldLayout fieldLayout; bytes16 firstDataBytes; bytes firstDataPacked; @@ -393,8 +461,10 @@ contract StoreCoreTest is Test, StoreMock { } function testSetAndGetField() public { + ResourceId tableId = _tableId; + SetAndGetData memory _data; - _data.tableId = keccak256("some.tableId"); + _data.tableId = tableId; // Register table _data.fieldLayout = FieldLayoutEncodeHelper.encode(16, 32, 2); @@ -608,7 +678,7 @@ contract StoreCoreTest is Test, StoreMock { } function testDeleteData() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 2); @@ -687,7 +757,7 @@ contract StoreCoreTest is Test, StoreMock { } struct TestPushToFieldData { - bytes32 tableId; + ResourceId tableId; bytes32[] keyTuple; bytes32 firstDataBytes; bytes secondDataBytes; @@ -700,9 +770,9 @@ contract StoreCoreTest is Test, StoreMock { } function testPushToField() public { - TestPushToFieldData memory data = TestPushToFieldData(0, new bytes32[](0), 0, "", "", "", "", "", "", ""); + ResourceId tableId = _tableId; - data.tableId = keccak256("some.tableId"); + TestPushToFieldData memory data = TestPushToFieldData(tableId, new bytes32[](0), 0, "", "", "", "", "", "", ""); // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(32, 2); @@ -826,7 +896,7 @@ contract StoreCoreTest is Test, StoreMock { } struct TestUpdateInFieldData { - bytes32 tableId; + ResourceId tableId; bytes32[] keyTuple; bytes32 firstDataBytes; uint32[] secondData; @@ -841,8 +911,10 @@ contract StoreCoreTest is Test, StoreMock { } function testUpdateInField() public { + ResourceId tableId = _tableId; + TestUpdateInFieldData memory data = TestUpdateInFieldData( - 0, + tableId, new bytes32[](0), 0, new uint32[](0), @@ -856,8 +928,6 @@ contract StoreCoreTest is Test, StoreMock { "" ); - data.tableId = keccak256("some.tableId"); - // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(32, 2); Schema valueSchema = SchemaEncodeHelper.encode( @@ -987,7 +1057,8 @@ contract StoreCoreTest is Test, StoreMock { } function testAccessEmptyData() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; + FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(4, 1); Schema valueSchema = SchemaEncodeHelper.encode(SchemaType.UINT32, SchemaType.UINT32_ARRAY); @@ -1014,7 +1085,8 @@ contract StoreCoreTest is Test, StoreMock { } function testRegisterHook() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; + bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = "some key"; @@ -1059,7 +1131,8 @@ contract StoreCoreTest is Test, StoreMock { } function testUnregisterHook() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; + bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = "some key"; @@ -1174,7 +1247,8 @@ contract StoreCoreTest is Test, StoreMock { } function testHooksDynamicData() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; + bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = "some key"; diff --git a/packages/store/test/StoreCoreDynamic.t.sol b/packages/store/test/StoreCoreDynamic.t.sol index d5979239c3..33e1434d0d 100644 --- a/packages/store/test/StoreCoreDynamic.t.sol +++ b/packages/store/test/StoreCoreDynamic.t.sol @@ -10,6 +10,8 @@ import { EncodeArray } from "../src/tightcoder/EncodeArray.sol"; import { PackedCounterLib } from "../src/PackedCounter.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; import { Schema } from "../src/Schema.sol"; +import { ResourceId, ResourceIdLib } from "../src/ResourceId.sol"; +import { RESOURCE_TABLE } from "../src/storeResourceTypes.sol"; import { StoreMock } from "../test/StoreMock.sol"; import { FieldLayoutEncodeHelper } from "./FieldLayoutEncodeHelper.sol"; import { SchemaEncodeHelper } from "./SchemaEncodeHelper.sol"; @@ -18,7 +20,7 @@ contract StoreCoreDynamicTest is Test, GasReporter, StoreMock { Schema internal defaultKeySchema = SchemaEncodeHelper.encode(SchemaType.BYTES32); bytes32[] internal _keyTuple; - bytes32 internal _tableId = keccak256("some.tableId"); + ResourceId internal _tableId = ResourceIdLib.encode({ typeId: RESOURCE_TABLE, name: "some table" }); bytes32 internal firstDataBytes; uint32[] internal secondData; @@ -28,7 +30,7 @@ contract StoreCoreDynamicTest is Test, GasReporter, StoreMock { // Expose an external popFromField function for testing purposes of indexers (see testHooks) function popFromField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, uint256 byteLengthToPop, diff --git a/packages/store/test/StoreCoreGas.t.sol b/packages/store/test/StoreCoreGas.t.sol index 219b3b8c64..31419806e6 100644 --- a/packages/store/test/StoreCoreGas.t.sol +++ b/packages/store/test/StoreCoreGas.t.sol @@ -14,6 +14,9 @@ import { PackedCounter, PackedCounterLib } from "../src/PackedCounter.sol"; import { StoreMock } from "../test/StoreMock.sol"; import { IStoreErrors } from "../src/IStoreErrors.sol"; import { IStore } from "../src/IStore.sol"; +import { ResourceId, ResourceIdLib } from "../src/ResourceId.sol"; +import { ResourceIds } from "../src/codegen/tables/ResourceIds.sol"; +import { RESOURCE_TABLE } from "../src/storeResourceTypes.sol"; import { FieldLayoutEncodeHelper } from "./FieldLayoutEncodeHelper.sol"; import { SchemaEncodeHelper } from "./SchemaEncodeHelper.sol"; import { StoreMock } from "./StoreMock.sol"; @@ -32,8 +35,12 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { mapping(uint256 => bytes) private testMapping; Schema defaultKeySchema = SchemaEncodeHelper.encode(SchemaType.BYTES32); + ResourceId _tableId = ResourceIdLib.encode({ typeId: RESOURCE_TABLE, name: "some table" }); + ResourceId _tableId2 = ResourceIdLib.encode({ typeId: RESOURCE_TABLE, name: "some other table" }); function testRegisterAndGetFieldLayout() public { + ResourceId tableId = _tableId; + FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 2, 1, 2, 0); Schema valueSchema = SchemaEncodeHelper.encode( SchemaType.UINT8, @@ -42,7 +49,6 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { SchemaType.UINT16 ); Schema keySchema = SchemaEncodeHelper.encode(SchemaType.UINT8, SchemaType.UINT16); - bytes32 tableId = keccak256("some.tableId"); string[] memory keyNames = new string[](2); keyNames[0] = "key1"; @@ -71,6 +77,9 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testHasFieldLayout() public { + ResourceId tableId = _tableId; + ResourceId tableId2 = _tableId2; + Schema valueSchema = SchemaEncodeHelper.encode( SchemaType.UINT8, SchemaType.UINT16, @@ -78,21 +87,19 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { SchemaType.UINT16 ); FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 2, 1, 2, 0); - bytes32 tableId = keccak256("some.tableId"); - bytes32 tableId2 = keccak256("other.tableId"); StoreCore.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](4)); startGasReport("Check for existence of table (existent)"); - StoreCore.hasTable(tableId); + ResourceIds._getExists(ResourceId.unwrap(tableId)); endGasReport(); startGasReport("check for existence of table (non-existent)"); - StoreCore.hasTable(tableId2); + ResourceIds._getExists(ResourceId.unwrap(tableId2)); endGasReport(); } function testSetAndGetDynamicDataLength() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; Schema valueSchema = SchemaEncodeHelper.encode( SchemaType.UINT8, @@ -128,6 +135,8 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testSetAndGetStaticData() public { + ResourceId tableId = _tableId; + // Register table Schema valueSchema = SchemaEncodeHelper.encode( SchemaType.UINT8, @@ -136,7 +145,6 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { SchemaType.UINT16 ); FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 2, 1, 2, 0); - bytes32 tableId = keccak256("some.tableId"); StoreCore.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](4)); // Set data @@ -156,10 +164,11 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testSetAndGetStaticDataSpanningWords() public { + ResourceId tableId = _tableId; + // Register table Schema valueSchema = SchemaEncodeHelper.encode(SchemaType.UINT128, SchemaType.UINT256); FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 32, 0); - bytes32 tableId = keccak256("some.tableId"); StoreCore.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](2)); // Set data @@ -183,7 +192,7 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testSetAndGetDynamicData() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 2); @@ -255,7 +264,7 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testSetAndGetField() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 32, 2); @@ -345,7 +354,7 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testDeleteData() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 2); @@ -398,7 +407,7 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testPushToField() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(32, 2); @@ -484,9 +493,9 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testUpdateInField() public { - TestUpdateInFieldData memory data = TestUpdateInFieldData("", "", "", "", "", "", ""); - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; + TestUpdateInFieldData memory data = TestUpdateInFieldData("", "", "", "", "", "", ""); // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(32, 2); Schema valueSchema = SchemaEncodeHelper.encode( @@ -561,7 +570,8 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testAccessEmptyData() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; + FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(4, 1); Schema valueSchema = SchemaEncodeHelper.encode(SchemaType.UINT32, SchemaType.UINT32_ARRAY); @@ -593,7 +603,8 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testHooks() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; + bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = keccak256("some key"); @@ -635,7 +646,8 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { } function testHooksDynamicData() public { - bytes32 tableId = keccak256("some.tableId"); + ResourceId tableId = _tableId; + bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = keccak256("some key"); diff --git a/packages/store/test/StoreHook.t.sol b/packages/store/test/StoreHook.t.sol index 3060df585d..d9ef3615a3 100644 --- a/packages/store/test/StoreHook.t.sol +++ b/packages/store/test/StoreHook.t.sol @@ -11,6 +11,8 @@ import { Hook, HookLib } from "../src/Hook.sol"; import { IStoreHook } from "../src/IStore.sol"; import { PackedCounter } from "../src/PackedCounter.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; +import { ResourceId, ResourceIdLib } from "../src/ResourceId.sol"; +import { RESOURCE_TABLE } from "../src/storeResourceTypes.sol"; import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SPLICE_STATIC_DATA, AFTER_SPLICE_STATIC_DATA, BEFORE_SPLICE_DYNAMIC_DATA, AFTER_SPLICE_DYNAMIC_DATA, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD, ALL, BEFORE_ALL, AFTER_ALL } from "../src/storeHookTypes.sol"; contract StoreHookTest is Test, GasReporter { @@ -19,7 +21,7 @@ contract StoreHookTest is Test, GasReporter { // Testdata EchoSubscriber private echoSubscriber = new EchoSubscriber(); RevertSubscriber private revertSubscriber = new RevertSubscriber(); - bytes32 private tableId = "table"; + ResourceId private tableId; bytes32[] private key = new bytes32[](1); bytes private staticData = abi.encodePacked(bytes32(0)); PackedCounter private encodedLengths = PackedCounter.wrap(bytes32(0)); @@ -27,6 +29,10 @@ contract StoreHookTest is Test, GasReporter { uint8 private fieldIndex = 1; FieldLayout private fieldLayout = FieldLayout.wrap(0); + constructor() { + tableId = ResourceIdLib.encode({ typeId: RESOURCE_TABLE, name: "table" }); + } + function testEncodeBitmap() public { assertEq(BEFORE_SET_RECORD, uint8(0x01), "0b00000001"); assertEq(AFTER_SET_RECORD, uint8(0x02), "0b00000010"); @@ -193,7 +199,7 @@ contract StoreHookTest is Test, GasReporter { vm.expectEmit(true, true, true, true); emit HookCalled( abi.encodeCall( - echoSubscriber.onBeforeSetRecord, + IStoreHook.onBeforeSetRecord, (tableId, key, staticData, encodedLengths, emptyDynamicData, fieldLayout) ) ); diff --git a/packages/store/test/StoreMock.sol b/packages/store/test/StoreMock.sol index 761fbf282a..14eb95c89b 100644 --- a/packages/store/test/StoreMock.sol +++ b/packages/store/test/StoreMock.sol @@ -7,6 +7,7 @@ import { StoreCore } from "../src/StoreCore.sol"; import { Schema } from "../src/Schema.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; import { StoreRead } from "../src/StoreRead.sol"; +import { ResourceId } from "../src/ResourceId.sol"; /** * StoreMock is a contract wrapper around the StoreCore library for testing purposes. @@ -19,7 +20,7 @@ contract StoreMock is IStore, StoreRead { // Set full record (including full dynamic data) function setRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, bytes calldata staticData, PackedCounter encodedLengths, @@ -31,7 +32,7 @@ contract StoreMock is IStore, StoreRead { // Splice data in the static part of the record function spliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint48 start, uint40 deleteCount, @@ -42,7 +43,7 @@ contract StoreMock is IStore, StoreRead { // Splice data in the dynamic part of the record function spliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -54,7 +55,7 @@ contract StoreMock is IStore, StoreRead { // Set partial data at field index function setField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, bytes calldata data, @@ -65,7 +66,7 @@ contract StoreMock is IStore, StoreRead { // Push encoded items to the dynamic field at field index function pushToField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, bytes calldata dataToPush, @@ -76,7 +77,7 @@ contract StoreMock is IStore, StoreRead { // Pop byte length from the dynamic field at field index function popFromField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, uint256 byteLengthToPop, @@ -87,7 +88,7 @@ contract StoreMock is IStore, StoreRead { // Change encoded items within the dynamic field at field index function updateInField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, uint256 startByteIndex, @@ -98,13 +99,13 @@ contract StoreMock is IStore, StoreRead { } // Set full record (including full dynamic data) - function deleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) public virtual { + function deleteRecord(ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) public virtual { StoreCore.deleteRecord(tableId, keyTuple, fieldLayout); } // Emit the ephemeral event without modifying storage function emitEphemeralRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, bytes calldata staticData, PackedCounter encodedLengths, @@ -115,7 +116,7 @@ contract StoreMock is IStore, StoreRead { } function registerTable( - bytes32 tableId, + ResourceId tableId, FieldLayout fieldLayout, Schema keySchema, Schema valueSchema, @@ -126,12 +127,12 @@ contract StoreMock is IStore, StoreRead { } // Register hook to be called when a record or field is set or deleted - function registerStoreHook(bytes32 tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) public virtual { + function registerStoreHook(ResourceId tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) public virtual { StoreCore.registerStoreHook(tableId, hookAddress, enabledHooksBitmap); } // Unregister hook to be called when a record or field is set or deleted - function unregisterStoreHook(bytes32 tableId, IStoreHook hookAddress) public virtual { + function unregisterStoreHook(ResourceId tableId, IStoreHook hookAddress) public virtual { StoreCore.unregisterStoreHook(tableId, hookAddress); } } diff --git a/packages/store/test/setDynamicDataLengthAtIndex.sol b/packages/store/test/setDynamicDataLengthAtIndex.sol index 10bb2c9872..146ffddfee 100644 --- a/packages/store/test/setDynamicDataLengthAtIndex.sol +++ b/packages/store/test/setDynamicDataLengthAtIndex.sol @@ -4,12 +4,13 @@ pragma solidity >=0.8.0; import { PackedCounter } from "../src/PackedCounter.sol"; import { StoreCoreInternal } from "../src/StoreCore.sol"; import { Storage } from "../src/Storage.sol"; +import { ResourceId } from "../src/ResourceId.sol"; /** * Test helper function to set the length of the dynamic data (in bytes) for the given value field layout and index */ function setDynamicDataLengthAtIndex( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8 dynamicFieldIndex, // fieldIndex - numStaticFields uint256 newLengthAtIndex diff --git a/packages/store/ts/codegen/renderTable.ts b/packages/store/ts/codegen/renderTable.ts index ad0b6d9cab..0e97775183 100644 --- a/packages/store/ts/codegen/renderTable.ts +++ b/packages/store/ts/codegen/renderTable.ts @@ -53,6 +53,8 @@ export function renderTable(options: RenderTableOptions) { import { FieldLayout, FieldLayoutLib } from "${storeImportPath}FieldLayout.sol"; import { Schema, SchemaLib } from "${storeImportPath}Schema.sol"; import { PackedCounter, PackedCounterLib } from "${storeImportPath}PackedCounter.sol"; + import { ResourceId } from "${storeImportPath}ResourceId.sol"; + import { RESOURCE_TABLE } from "${storeImportPath}storeResourceTypes.sol"; ${ imports.length > 0 diff --git a/packages/store/ts/config/storeConfig.ts b/packages/store/ts/config/storeConfig.ts index 2795a266ff..36a951b862 100644 --- a/packages/store/ts/config/storeConfig.ts +++ b/packages/store/ts/config/storeConfig.ts @@ -11,14 +11,15 @@ import { // validation utils getDuplicates, parseStaticArray, - STORE_SELECTOR_MAX_LENGTH, + STORE_NAME_MAX_LENGTH, // config MUDCoreUserConfig, // schemas zObjectName, - zSelector, zUserEnum, zValueName, + zNamespace, + zName, } from "@latticexyz/config"; import { DEFAULTS, PATH_DEFAULTS, TABLE_DEFAULTS } from "./defaults"; @@ -127,7 +128,7 @@ export interface ExpandTableConfig, TableN const zFullTableConfig = z .object({ directory: z.string().default(TABLE_DEFAULTS.directory), - name: zSelector.optional(), + name: zName.optional(), tableIdArgument: z.boolean().default(TABLE_DEFAULTS.tableIdArgument), storeArgument: z.boolean().default(TABLE_DEFAULTS.storeArgument), dataStruct: z.boolean().optional(), @@ -170,7 +171,7 @@ export const zTablesConfig = z.record(zTableName, zTableConfig).transform((table // default name depends on tableName for (const tableName of Object.keys(tables)) { const table = tables[tableName]; - table.name = tableName.slice(0, STORE_SELECTOR_MAX_LENGTH); + table.name = tableName.slice(0, STORE_NAME_MAX_LENGTH); tables[tableName] = table; } @@ -271,7 +272,7 @@ export type MUDUserConfig< const StoreConfigUnrefined = z .object({ - namespace: zSelector.default(DEFAULTS.namespace), + namespace: zNamespace.default(DEFAULTS.namespace), storeImportPath: z.string().default(PATH_DEFAULTS.storeImportPath), tables: zTablesConfig, userTypesFilename: z.string().default(PATH_DEFAULTS.userTypesFilename), diff --git a/packages/store/ts/storeEventsAbi.test.ts b/packages/store/ts/storeEventsAbi.test.ts index 17b704d341..55d23793c4 100644 --- a/packages/store/ts/storeEventsAbi.test.ts +++ b/packages/store/ts/storeEventsAbi.test.ts @@ -5,26 +5,29 @@ import { AbiEvent } from "abitype"; // Make sure `storeEvents` stays in sync with Solidity definition/events +function normalizeAbiEvents(abiEvents: readonly AbiEvent[]) { + return abiEvents + .map((item) => ({ + type: item.type, + name: item.name, + inputs: item.inputs.map((input) => ({ + type: input.type, + name: input.name, + ...(input.indexed ? { indexed: true } : null), + })), + })) + .sort((a, b) => a.name.localeCompare(b.name)); +} + describe("storeEventsAbi", () => { it("should match the store ABI", () => { - const expectedEvents = IStoreAbi.filter((item) => item.type === "event").filter( - (item) => item.name !== "HelloStore" - ) as readonly AbiEvent[]; - - const expectedAbi = expectedEvents - .map((item) => ({ - // return data in a shape that matches abitype's parseAbi - type: item.type, - name: item.name, - inputs: item.inputs.map((input) => ({ - name: input.name, - type: input.type, - ...(input.indexed ? { indexed: true } : null), - })), - })) - .sort((a, b) => a.name.localeCompare(b.name)); + const eventsDefined = normalizeAbiEvents(storeEventsAbi); + const eventsFromAbi = normalizeAbiEvents( + IStoreAbi.filter((item) => item.type === "event").filter( + (item) => item.name !== "HelloStore" + ) as readonly AbiEvent[] + ); - const sortedStoreEventsAbi = [...storeEventsAbi].sort((a, b) => a.name.localeCompare(b.name)); - expect(sortedStoreEventsAbi).toStrictEqual(expectedAbi); + expect(JSON.stringify(eventsDefined)).toEqual(JSON.stringify(eventsFromAbi)); }); }); diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index c021f1084d..1a53c2c895 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": 6924 + "gasUsed": 7179 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm, namespace only)", - "gasUsed": 1534 + "gasUsed": 1727 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm)", - "gasUsed": 2944 + "gasUsed": 3187 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (cold)", - "gasUsed": 6966 + "gasUsed": 7222 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (warm)", - "gasUsed": 2969 + "gasUsed": 3225 }, { "file": "test/AccessControl.t.sol", @@ -39,342 +39,366 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1413512 + "gasUsed": 1414600 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1413512 + "gasUsed": 1414600 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 157414 + "gasUsed": 158308 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1413512 + "gasUsed": 1414600 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1413512 + "gasUsed": 1414600 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 22025 + "gasUsed": 22290 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 157762 + "gasUsed": 160543 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1413512 + "gasUsed": 1414600 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 20747 + "gasUsed": 21012 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 84152 + "gasUsed": 85675 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 652783 + "gasUsed": 664896 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "Get list of keys with a given value", - "gasUsed": 5338 + "gasUsed": 6175 }, { "file": "test/KeysWithValueModule.t.sol", - "test": "testGetTargetTableSelector", + "test": "testGetTargetTableId", "name": "compute the target table selector", - "gasUsed": 2234 + "gasUsed": 3071 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 652783 + "gasUsed": 664896 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 134041 + "gasUsed": 135679 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 652783 + "gasUsed": 664896 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 104450 + "gasUsed": 106088 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 33978 + "gasUsed": 35339 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 652783 + "gasUsed": 664896 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 145891 + "gasUsed": 148411 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 110650 + "gasUsed": 113170 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 101456 + "gasUsed": 104597 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 51595 + "gasUsed": 54366 }, { "file": "test/query.t.sol", "test": "testCombinedHasNotQuery", "name": "CombinedHasNotQuery", - "gasUsed": 127301 + "gasUsed": 128263 }, { "file": "test/query.t.sol", "test": "testCombinedHasQuery", "name": "CombinedHasQuery", - "gasUsed": 80857 + "gasUsed": 81486 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 82233 + "gasUsed": 83650 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueQuery", "name": "CombinedHasValueQuery", - "gasUsed": 14940 + "gasUsed": 16664 }, { "file": "test/query.t.sol", "test": "testHasQuery", "name": "HasQuery", - "gasUsed": 17953 + "gasUsed": 18101 }, { "file": "test/query.t.sol", "test": "testHasQuery1000Keys", "name": "HasQuery with 1000 keys", - "gasUsed": 5901526 + "gasUsed": 5938600 }, { "file": "test/query.t.sol", "test": "testHasQuery100Keys", "name": "HasQuery with 100 keys", - "gasUsed": 550220 + "gasUsed": 553994 }, { "file": "test/query.t.sol", "test": "testHasValueQuery", "name": "HasValueQuery", - "gasUsed": 7141 + "gasUsed": 8003 }, { "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 45191 + "gasUsed": 47962 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 113954 + "gasUsed": 114520 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 33517 + "gasUsed": 34023 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 108418 + "gasUsed": 108972 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 26642 + "gasUsed": 27100 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 678987 + "gasUsed": 689839 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 51263 + "gasUsed": 52112 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 669072 + "gasUsed": 680105 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 51263 + "gasUsed": 52112 }, { "file": "test/World.t.sol", "test": "testCall", "name": "call a system via the World", - "gasUsed": 12356 + "gasUsed": 12769 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 50265 + "gasUsed": 50584 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "call a system via an unlimited delegation", - "gasUsed": 12705 + "gasUsed": 12961 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 8888 + "gasUsed": 9120 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 86650 + "gasUsed": 86882 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 58852 + "gasUsed": 59355 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 52169 + "gasUsed": 52902 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 79446 + "gasUsed": 79949 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 122816 + "gasUsed": 123062 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 74087 + "gasUsed": 74815 + }, + { + "file": "test/World.t.sol", + "test": "testRegisterSystem", + "name": "register a system", + "gasUsed": 165531 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 641696 + "gasUsed": 651531 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 37171 + "gasUsed": 37403 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 35165 + "gasUsed": 35397 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 24401 + "gasUsed": 24633 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 13547 + "gasUsed": 13779 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 25012 + "gasUsed": 25244 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 14217 + "gasUsed": 14449 + }, + { + "file": "test/WorldResourceId.t.sol", + "test": "testGetNamespace", + "name": "encode namespace, name and type", + "gasUsed": 151 + }, + { + "file": "test/WorldResourceId.t.sol", + "test": "testGetNamespaceId", + "name": "get namespace ID from a resource ID", + "gasUsed": 175 + }, + { + "file": "test/WorldResourceId.t.sol", + "test": "testGetType", + "name": "get type from a resource ID", + "gasUsed": 4 } ] diff --git a/packages/world/mud.config.ts b/packages/world/mud.config.ts index 1ad535703d..1a77d8309b 100644 --- a/packages/world/mud.config.ts +++ b/packages/world/mud.config.ts @@ -13,7 +13,7 @@ export default mudConfig({ ************************************************************************/ NamespaceOwner: { keySchema: { - namespace: "bytes16", + namespaceId: "bytes32", }, valueSchema: { owner: "address", @@ -21,7 +21,7 @@ export default mudConfig({ }, ResourceAccess: { keySchema: { - resourceSelector: "bytes32", + resourceId: "bytes32", caller: "address", }, valueSchema: { @@ -54,7 +54,7 @@ export default mudConfig({ Balances: { directory: "modules/core/tables", keySchema: { - namespace: "bytes16", + namespaceId: "bytes32", }, valueSchema: { balance: "uint256", @@ -63,7 +63,7 @@ export default mudConfig({ Systems: { directory: "modules/core/tables", keySchema: { - resourceSelector: "bytes32", + systemId: "bytes32", }, valueSchema: { system: "address", @@ -77,32 +77,23 @@ export default mudConfig({ system: "address", }, valueSchema: { - resourceSelector: "bytes32", + systemId: "bytes32", }, }, SystemHooks: { directory: "modules/core/tables", keySchema: { - resourceSelector: "bytes32", + systemId: "bytes32", }, valueSchema: "bytes21[]", }, - ResourceType: { - directory: "modules/core/tables", - keySchema: { - resourceSelector: "bytes32", - }, - valueSchema: { - resourceType: "Resource", - }, - }, FunctionSelectors: { directory: "modules/core/tables", keySchema: { functionSelector: "bytes4", }, valueSchema: { - resourceSelector: "bytes32", + systemId: "bytes32", systemFunctionSelector: "bytes4", }, dataStruct: false, @@ -149,7 +140,7 @@ export default mudConfig({ keySchema: { delegator: "address", delegatee: "address", - resourceSelector: "bytes32", + systemId: "bytes32", callDataHash: "bytes32", }, valueSchema: { @@ -185,10 +176,6 @@ export default mudConfig({ tableIdArgument: true, }, }, - enums: { - Resource: ["NONE", "NAMESPACE", "TABLE", "SYSTEM"], - }, - excludeSystems: [ // IUniqueEntitySystem is not part of the root namespace and // installed separately by UniqueEntityModule. diff --git a/packages/world/src/AccessControl.sol b/packages/world/src/AccessControl.sol index d99fd415ef..6cb5cc12ce 100644 --- a/packages/world/src/AccessControl.sol +++ b/packages/world/src/AccessControl.sol @@ -1,43 +1,43 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import { ResourceSelector } from "./ResourceSelector.sol"; +import { ResourceId, WorldResourceIdInstance } from "./WorldResourceId.sol"; import { IWorldErrors } from "./interfaces/IWorldErrors.sol"; import { ResourceAccess } from "./tables/ResourceAccess.sol"; import { NamespaceOwner } from "./tables/NamespaceOwner.sol"; library AccessControl { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; /** * Returns true if the caller has access to the namespace or name, false otherwise. */ - function hasAccess(bytes32 resourceSelector, address caller) internal view returns (bool) { + function hasAccess(ResourceId resourceId, address caller) internal view returns (bool) { return address(this) == caller || // First check if the World is calling itself - ResourceAccess._get(resourceSelector.getNamespace(), caller) || // Then check access based on the namespace - ResourceAccess._get(resourceSelector, caller); // If caller has no namespace access, check access on the name + ResourceAccess._get(ResourceId.unwrap(resourceId.getNamespaceId()), caller) || // Then check access based on the namespace + ResourceAccess._get(ResourceId.unwrap(resourceId), caller); // If caller has no namespace access, check access on the name } /** * Check for access at the given namespace or name. * Reverts with AccessDenied if the caller has no access. */ - function requireAccess(bytes32 resourceSelector, address caller) internal view { + function requireAccess(ResourceId resourceId, address caller) internal view { // Check if the given caller has access to the given namespace or name - if (!hasAccess(resourceSelector, caller)) { - revert IWorldErrors.AccessDenied(resourceSelector.toString(), caller); + if (!hasAccess(resourceId, caller)) { + revert IWorldErrors.AccessDenied(resourceId.toString(), caller); } } /** - * Check for ownership of the namespace of the given resource selector. + * Check for ownership of the namespace of the given resource ID. * Reverts with AccessDenied if the check fails. */ - function requireOwner(bytes32 resourceSelector, address caller) internal view { - if (NamespaceOwner._get(resourceSelector.getNamespace()) != caller) { - revert IWorldErrors.AccessDenied(resourceSelector.toString(), caller); + function requireOwner(ResourceId resourceId, address caller) internal view { + if (NamespaceOwner._get(ResourceId.unwrap(resourceId.getNamespaceId())) != caller) { + revert IWorldErrors.AccessDenied(resourceId.toString(), caller); } } } diff --git a/packages/world/src/Delegation.sol b/packages/world/src/Delegation.sol index 14855a1ae0..191142f39c 100644 --- a/packages/world/src/Delegation.sol +++ b/packages/world/src/Delegation.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.0; import { UNLIMITED_DELEGATION } from "./constants.sol"; import { IDelegationControl } from "./interfaces/IDelegationControl.sol"; import { SystemCall } from "./SystemCall.sol"; +import { ResourceId } from "./WorldResourceId.sol"; type Delegation is bytes32; @@ -15,7 +16,7 @@ library DelegationInstance { } function isUnlimited(Delegation self) internal pure returns (bool) { - return Delegation.unwrap(self) == UNLIMITED_DELEGATION; + return Delegation.unwrap(self) == ResourceId.unwrap(UNLIMITED_DELEGATION); } function isLimited(Delegation self) internal pure returns (bool) { @@ -31,7 +32,7 @@ library DelegationInstance { Delegation self, address delegator, address delegatee, - bytes32 systemId, + ResourceId systemId, bytes memory callData ) internal returns (bool) { // Early return if there is an unlimited delegation @@ -43,7 +44,7 @@ library DelegationInstance { // Call the delegation control contract to check if the delegator has granted access to the delegatee (bool success, bytes memory data) = SystemCall.call({ caller: delegatee, - resourceSelector: Delegation.unwrap(self), + systemId: ResourceId.wrap(Delegation.unwrap(self)), callData: abi.encodeCall(IDelegationControl.verify, (delegator, systemId, callData)), value: 0 }); diff --git a/packages/world/src/ResourceSelector.sol b/packages/world/src/ResourceSelector.sol deleted file mode 100644 index 8ed6b39326..0000000000 --- a/packages/world/src/ResourceSelector.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; -import { ROOT_NAMESPACE, ROOT_NAME } from "./constants.sol"; -import { Bytes } from "@latticexyz/store/src/Bytes.sol"; - -bytes16 constant ROOT_NAMESPACE_STRING = bytes16("ROOT_NAMESPACE"); -bytes16 constant ROOT_NAME_STRING = bytes16("ROOT_NAME"); - -library ResourceSelector { - /** - * Create a 32-byte resource selector from a namespace and a name. - * - * A ResourceSelector is a 32-byte value that uniquely identifies a resource. - * The first 16 bytes represent the namespace, the last 16 bytes represent the name. - */ - function from(bytes16 namespace, bytes16 name) internal pure returns (bytes32) { - return bytes32(namespace) | (bytes32(name) >> 128); - } - - /** - * Create a 32-byte resource selector from a namespace. The selector points to the namespace's root name. - */ - function from(bytes16 namespace) internal pure returns (bytes32) { - return bytes32(namespace); - } - - /** - * Get the namespace of a ResourceSelector. - */ - function getNamespace(bytes32 resourceSelector) internal pure returns (bytes16) { - return bytes16(resourceSelector); - } - - /** - * Get the name of a ResourceSelector. - */ - function getName(bytes32 resourceSelector) internal pure returns (bytes16) { - return bytes16(resourceSelector << 128); - } - - /** - * Convert a selector to a string for more readable logs - */ - function toString(bytes32 resourceSelector) internal pure returns (string memory) { - bytes16 namespace = getNamespace(resourceSelector); - bytes16 name = getName(resourceSelector); - return - string( - abi.encodePacked( - namespace == ROOT_NAMESPACE ? ROOT_NAMESPACE_STRING : namespace, - "/", - name == ROOT_NAME ? ROOT_NAME_STRING : name - ) - ); - } - - /** - * Convert a selector to a trimmed string (no trailing `null` ASCII characters) - */ - function toTrimmedString(bytes16 selector) internal pure returns (string memory) { - uint256 length; - for (; length < 16; length++) if (Bytes.slice1(selector, length) == 0) break; - bytes memory packedSelector = abi.encodePacked(selector); - return string(Bytes.setLength(packedSelector, length)); - } -} diff --git a/packages/world/src/SystemCall.sol b/packages/world/src/SystemCall.sol index 27241b9a6b..568f47e4ee 100644 --- a/packages/world/src/SystemCall.sol +++ b/packages/world/src/SystemCall.sol @@ -3,10 +3,9 @@ pragma solidity >=0.8.0; import { Hook } from "@latticexyz/store/src/Hook.sol"; -import { ResourceSelector } from "./ResourceSelector.sol"; +import { ResourceId, WorldResourceIdInstance } from "./WorldResourceId.sol"; import { WorldContextProvider } from "./WorldContext.sol"; import { AccessControl } from "./AccessControl.sol"; -import { ResourceSelector } from "./ResourceSelector.sol"; import { ROOT_NAMESPACE } from "./constants.sol"; import { WorldContextProvider } from "./WorldContext.sol"; import { revertWithBytes } from "./revertWithBytes.sol"; @@ -21,36 +20,36 @@ import { SystemHooks } from "./modules/core/tables/SystemHooks.sol"; import { Balances } from "./modules/core/tables/Balances.sol"; library SystemCall { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; /** - * Calls a system via its resource selector and perform access control checks. + * Calls a system via its ID and perform access control checks. * Does not revert if the call fails, but returns a `success` flag along with the returndata. */ function call( address caller, uint256 value, - bytes32 resourceSelector, + ResourceId systemId, bytes memory callData ) internal returns (bool success, bytes memory data) { // Load the system data - (address systemAddress, bool publicAccess) = Systems._get(resourceSelector); + (address systemAddress, bool publicAccess) = Systems._get(ResourceId.unwrap(systemId)); // Check if the system exists - if (systemAddress == address(0)) revert IWorldErrors.ResourceNotFound(resourceSelector.toString()); + if (systemAddress == address(0)) revert IWorldErrors.ResourceNotFound(systemId, systemId.toString()); // Allow access if the system is public or the caller has access to the namespace or name - if (!publicAccess) AccessControl.requireAccess(resourceSelector, caller); + if (!publicAccess) AccessControl.requireAccess(systemId, caller); // If the msg.value is non-zero, update the namespace's balance if (value > 0) { - bytes16 namespace = resourceSelector.getNamespace(); - uint256 currentBalance = Balances._get(namespace); - Balances._set(namespace, currentBalance + value); + ResourceId namespaceId = systemId.getNamespaceId(); + uint256 currentBalance = Balances._get(ResourceId.unwrap(namespaceId)); + Balances._set(ResourceId.unwrap(namespaceId), currentBalance + value); } // Call the system and forward any return data - (success, data) = resourceSelector.getNamespace() == ROOT_NAMESPACE // Use delegatecall for root systems (= registered in the root namespace) + (success, data) = systemId.getNamespace() == ROOT_NAMESPACE // Use delegatecall for root systems (= registered in the root namespace) ? WorldContextProvider.delegatecallWithContext({ msgSender: caller, msgValue: value, @@ -66,52 +65,52 @@ library SystemCall { } /** - * Calls a system via its resource selector, perform access control checks and trigger hooks registered for the system. + * Calls a system via its ID, perform access control checks and trigger hooks registered for the system. * Does not revert if the call fails, but returns a `success` flag along with the returndata. */ function callWithHooks( address caller, - bytes32 resourceSelector, + ResourceId systemId, bytes memory callData, uint256 value ) internal returns (bool success, bytes memory data) { // Get system hooks - bytes21[] memory hooks = SystemHooks._get(resourceSelector); + bytes21[] memory hooks = SystemHooks._get(ResourceId.unwrap(systemId)); // Call onBeforeCallSystem hooks (before calling the system) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(BEFORE_CALL_SYSTEM)) { - ISystemHook(hook.getAddress()).onBeforeCallSystem(caller, resourceSelector, callData); + ISystemHook(hook.getAddress()).onBeforeCallSystem(caller, systemId, callData); } } // Call the system and forward any return data - (success, data) = call({ caller: caller, value: value, resourceSelector: resourceSelector, callData: callData }); + (success, data) = call({ caller: caller, value: value, systemId: systemId, callData: callData }); // Call onAfterCallSystem hooks (after calling the system) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(AFTER_CALL_SYSTEM)) { - ISystemHook(hook.getAddress()).onAfterCallSystem(caller, resourceSelector, callData); + ISystemHook(hook.getAddress()).onAfterCallSystem(caller, systemId, callData); } } } /** - * Calls a system via its resource selector, perform access control checks and trigger hooks registered for the system. + * Calls a system via its ID, perform access control checks and trigger hooks registered for the system. * Reverts if the call fails. */ function callWithHooksOrRevert( address caller, - bytes32 resourceSelector, + ResourceId systemId, bytes memory callData, uint256 value ) internal returns (bytes memory data) { (bool success, bytes memory returnData) = callWithHooks({ caller: caller, value: value, - resourceSelector: resourceSelector, + systemId: systemId, callData: callData }); if (!success) revertWithBytes(returnData); diff --git a/packages/world/src/Utils.sol b/packages/world/src/Utils.sol index b54e5d7653..af6e23a62c 100644 --- a/packages/world/src/Utils.sol +++ b/packages/world/src/Utils.sol @@ -2,10 +2,12 @@ pragma solidity >=0.8.0; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; -import { ResourceSelector } from "./ResourceSelector.sol"; +import { ResourceId, WorldResourceIdInstance } from "./WorldResourceId.sol"; import { SystemRegistry } from "./index.sol"; library Utils { + using WorldResourceIdInstance for ResourceId; + /** * Get the namespace of this system. * Must be used within the context of a system (either directly, or within libraries called by a system). @@ -17,8 +19,8 @@ library Utils { if (StoreSwitch.getStoreAddress() == address(this)) { return ""; } else { - bytes32 resourceSelector = SystemRegistry.get(address(this)); - return ResourceSelector.getNamespace(resourceSelector); + ResourceId systemId = ResourceId.wrap(SystemRegistry.get(address(this))); + return systemId.getNamespace(); } } } diff --git a/packages/world/src/World.sol b/packages/world/src/World.sol index 73464c011b..f24bf892e1 100644 --- a/packages/world/src/World.sol +++ b/packages/world/src/World.sol @@ -12,8 +12,8 @@ import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; import { WORLD_VERSION } from "./version.sol"; import { System } from "./System.sol"; -import { ResourceSelector } from "./ResourceSelector.sol"; -import { ROOT_NAMESPACE, ROOT_NAME } from "./constants.sol"; +import { ResourceId, WorldResourceIdInstance } from "./WorldResourceId.sol"; +import { ROOT_NAMESPACE_ID, ROOT_NAMESPACE, ROOT_NAME } from "./constants.sol"; import { AccessControl } from "./AccessControl.sol"; import { SystemCall } from "./SystemCall.sol"; import { WorldContextProvider } from "./WorldContext.sol"; @@ -36,7 +36,7 @@ import { Balances } from "./modules/core/tables/Balances.sol"; import { CORE_MODULE_NAME } from "./modules/core/constants.sol"; contract World is StoreRead, IStoreData, IWorldKernel { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; address public immutable creator; function worldVersion() public pure returns (bytes32) { @@ -55,7 +55,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { function initialize(IModule coreModule) public { // Only the initial creator of the World can initialize it if (msg.sender != creator) { - revert AccessDenied(ResourceSelector.from(ROOT_NAMESPACE).toString(), msg.sender); + revert AccessDenied(ROOT_NAMESPACE_ID.toString(), msg.sender); } // The World can only be initialized once @@ -73,7 +73,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { * The module is delegatecalled and installed in the root namespace. */ function installRootModule(IModule module, bytes memory args) public { - AccessControl.requireOwner(ROOT_NAMESPACE, msg.sender); + AccessControl.requireOwner(ROOT_NAMESPACE_ID, msg.sender); _installRootModule(module, args); } @@ -103,7 +103,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { * Requires the caller to have access to the table's namespace or name (encoded in the tableId). */ function setRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, bytes calldata staticData, PackedCounter encodedLengths, @@ -118,7 +118,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { } function spliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint48 start, uint40 deleteCount, @@ -132,7 +132,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { } function spliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, @@ -151,7 +151,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { * Requires the caller to have access to the table's namespace or name (encoded in the tableId). */ function setField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, bytes calldata data, @@ -169,7 +169,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { * Requires the caller to have access to the table's namespace or name (encoded in the tableId). */ function pushToField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, bytes calldata dataToPush, @@ -187,7 +187,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { * Requires the caller to have access to the table's namespace or name (encoded in the tableId). */ function popFromField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, uint256 byteLengthToPop, @@ -205,7 +205,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { * Requires the caller to have access to the table's namespace or name (encoded in the tableId). */ function updateInField( - bytes32 tableId, + ResourceId tableId, bytes32[] calldata keyTuple, uint8 fieldIndex, uint256 startByteIndex, @@ -223,7 +223,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { * Delete a record in the table at the given tableId. * Requires the caller to have access to the namespace or name. */ - function deleteRecord(bytes32 tableId, bytes32[] calldata keyTuple, FieldLayout fieldLayout) public virtual { + function deleteRecord(ResourceId tableId, bytes32[] calldata keyTuple, FieldLayout fieldLayout) public virtual { // Require access to namespace or name AccessControl.requireAccess(tableId, msg.sender); @@ -238,40 +238,40 @@ contract World is StoreRead, IStoreData, IWorldKernel { ************************************************************************/ /** - * Call the system at the given resourceSelector. - * If the system is not public, the caller must have access to the namespace or name (encoded in the resourceSelector). + * Call the system at the given system ID. + * If the system is not public, the caller must have access to the namespace or name (encoded in the system ID). */ - function call(bytes32 resourceSelector, bytes memory callData) external payable virtual returns (bytes memory) { - return SystemCall.callWithHooksOrRevert(msg.sender, resourceSelector, callData, msg.value); + function call(ResourceId systemId, bytes memory callData) external payable virtual returns (bytes memory) { + return SystemCall.callWithHooksOrRevert(msg.sender, systemId, callData, msg.value); } /** - * Call the system at the given resourceSelector on behalf of the given delegator. - * If the system is not public, the delegator must have access to the namespace or name (encoded in the resourceSelector). + * Call the system at the given system ID on behalf of the given delegator. + * If the system is not public, the delegator must have access to the namespace or name (encoded in the system ID). */ function callFrom( address delegator, - bytes32 resourceSelector, + ResourceId systemId, bytes memory callData ) external payable virtual returns (bytes memory) { // If the delegator is the caller, call the system directly if (delegator == msg.sender) { - return SystemCall.callWithHooksOrRevert(msg.sender, resourceSelector, callData, msg.value); + return SystemCall.callWithHooksOrRevert(msg.sender, systemId, callData, msg.value); } // Check if there is an explicit authorization for this caller to perform actions on behalf of the delegator Delegation explicitDelegation = Delegation.wrap(Delegations._get({ delegator: delegator, delegatee: msg.sender })); - if (explicitDelegation.verify(delegator, msg.sender, resourceSelector, callData)) { + if (explicitDelegation.verify(delegator, msg.sender, systemId, callData)) { // forward the call as `delegator` - return SystemCall.callWithHooksOrRevert(delegator, resourceSelector, callData, msg.value); + return SystemCall.callWithHooksOrRevert(delegator, systemId, callData, msg.value); } // Check if the delegator has a fallback delegation control set Delegation fallbackDelegation = Delegation.wrap(Delegations._get({ delegator: delegator, delegatee: address(0) })); - if (fallbackDelegation.verify(delegator, msg.sender, resourceSelector, callData)) { + if (fallbackDelegation.verify(delegator, msg.sender, systemId, callData)) { // forward the call with `from` as `msgSender` - return SystemCall.callWithHooksOrRevert(delegator, resourceSelector, callData, msg.value); + return SystemCall.callWithHooksOrRevert(delegator, systemId, callData, msg.value); } revert DelegationNotFound(delegator, msg.sender); @@ -287,23 +287,28 @@ contract World is StoreRead, IStoreData, IWorldKernel { * ETH sent to the World without calldata is added to the root namespace's balance */ receive() external payable { - uint256 rootBalance = Balances._get(ROOT_NAMESPACE); - Balances._set(ROOT_NAMESPACE, rootBalance + msg.value); + uint256 rootBalance = Balances._get(ResourceId.unwrap(ROOT_NAMESPACE_ID)); + Balances._set(ResourceId.unwrap(ROOT_NAMESPACE_ID), rootBalance + msg.value); } /** * Fallback function to call registered function selectors */ fallback() external payable { - (bytes32 resourceSelector, bytes4 systemFunctionSelector) = FunctionSelectors._get(msg.sig); + (bytes32 systemId, bytes4 systemFunctionSelector) = FunctionSelectors._get(msg.sig); - if (resourceSelector == 0) revert FunctionSelectorNotFound(msg.sig); + if (systemId == 0) revert FunctionSelectorNotFound(msg.sig); // Replace function selector in the calldata with the system function selector bytes memory callData = Bytes.setBytes4(msg.data, 0, systemFunctionSelector); // Call the function and forward the call data - bytes memory returnData = SystemCall.callWithHooksOrRevert(msg.sender, resourceSelector, callData, msg.value); + bytes memory returnData = SystemCall.callWithHooksOrRevert( + msg.sender, + ResourceId.wrap(systemId), + callData, + msg.value + ); // If the call was successful, return the return data assembly { diff --git a/packages/world/src/WorldResourceId.sol b/packages/world/src/WorldResourceId.sol new file mode 100644 index 0000000000..db24aba8b9 --- /dev/null +++ b/packages/world/src/WorldResourceId.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { ResourceId, ResourceIdInstance, TYPE_BYTES } 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; + +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); + +library WorldResourceIdLib { + /** + * Create a 32-byte resource ID from a namespace, name and type. + * + * A resource ID is a 32-byte value that uniquely identifies a resource. + * The first 14 bytes represent the namespace, + * the next 16 bytes represent the name, + * the last 2 bytes represent the type. + */ + 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)) + ); + } + + /** + * 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))); + } + + /** + * Convert a padded string to a trimmed string (no trailing `null` ASCII characters) + */ + function toTrimmedString(bytes16 paddedString) internal pure returns (string memory) { + uint256 length; + for (; length < 16; length++) if (Bytes.slice1(paddedString, length) == 0) break; + bytes memory packedSelector = abi.encodePacked(paddedString); + return string(Bytes.setLength(packedSelector, length)); + } +} + +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)); + } + + /** + * Get the namespace resource ID corresponding to the namespace of a resource ID. + */ + function getNamespaceId(ResourceId resourceId) internal pure returns (ResourceId) { + return ResourceId.wrap((ResourceId.unwrap(resourceId) & NAMESPACE_MASK) | MASK_RESOURCE_NAMESPACE); + } + + /** + * 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)); + } + + /** + * Convert a resource ID to a string for more readable logs + */ + function toString(ResourceId resourceId) internal pure returns (string memory) { + bytes2 resourceType = ResourceIdInstance.getType(resourceId); + bytes14 resourceNamespace = getNamespace(resourceId); + bytes16 resourceName = getName(resourceId); + return + string( + abi.encodePacked( + resourceType, + ":", + resourceNamespace == ROOT_NAMESPACE ? ROOT_NAMESPACE_STRING : resourceNamespace, + ":", + resourceName == ROOT_NAME ? ROOT_NAME_STRING : resourceName + ) + ); + } +} diff --git a/packages/world/src/common.sol b/packages/world/src/common.sol deleted file mode 100644 index 6c4b0ff193..0000000000 --- a/packages/world/src/common.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; - -/* Autogenerated file. Do not edit manually. */ -enum Resource { - NONE, - NAMESPACE, - TABLE, - SYSTEM -} diff --git a/packages/world/src/constants.sol b/packages/world/src/constants.sol index a4a2538803..5f7e4ff646 100644 --- a/packages/world/src/constants.sol +++ b/packages/world/src/constants.sol @@ -1,6 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -bytes16 constant ROOT_NAMESPACE = 0; -bytes16 constant ROOT_NAME = 0; -bytes32 constant UNLIMITED_DELEGATION = bytes32(abi.encodePacked(ROOT_NAMESPACE, bytes16("unlimited.d"))); +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + +import { RESOURCE_SYSTEM, RESOURCE_NAMESPACE } from "./worldResourceTypes.sol"; + +bytes14 constant ROOT_NAMESPACE = ""; +bytes16 constant ROOT_NAME = ""; + +ResourceId constant ROOT_NAMESPACE_ID = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_NAMESPACE, ROOT_NAMESPACE, ROOT_NAME)) +); + +ResourceId constant UNLIMITED_DELEGATION = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_SYSTEM, ROOT_NAMESPACE, bytes16("unlimited"))) +); diff --git a/packages/world/src/factories/WorldFactory.sol b/packages/world/src/factories/WorldFactory.sol index 752ade4ddb..87af0543ed 100644 --- a/packages/world/src/factories/WorldFactory.sol +++ b/packages/world/src/factories/WorldFactory.sol @@ -6,7 +6,7 @@ import { World } from "../World.sol"; import { IWorldFactory } from "./IWorldFactory.sol"; import { IBaseWorld } from "../interfaces/IBaseWorld.sol"; import { IModule } from "../interfaces/IModule.sol"; -import { ROOT_NAMESPACE } from "../constants.sol"; +import { ROOT_NAMESPACE_ID } from "../constants.sol"; contract WorldFactory is IWorldFactory { IModule public coreModule; @@ -27,7 +27,7 @@ contract WorldFactory is IWorldFactory { // Initialize the World and transfer ownership to the caller world.initialize(coreModule); - world.transferOwnership(ROOT_NAMESPACE, msg.sender); + world.transferOwnership(ROOT_NAMESPACE_ID, msg.sender); emit WorldDeployed(worldAddress); } diff --git a/packages/world/src/index.sol b/packages/world/src/index.sol index 021a7371bf..2e852c4973 100644 --- a/packages/world/src/index.sol +++ b/packages/world/src/index.sol @@ -11,7 +11,6 @@ import { Balances, BalancesTableId } from "./modules/core/tables/Balances.sol"; import { Systems, SystemsTableId } from "./modules/core/tables/Systems.sol"; import { SystemRegistry, SystemRegistryTableId } from "./modules/core/tables/SystemRegistry.sol"; import { SystemHooks, SystemHooksTableId } from "./modules/core/tables/SystemHooks.sol"; -import { ResourceType, ResourceTypeTableId } from "./modules/core/tables/ResourceType.sol"; import { FunctionSelectors, FunctionSelectorsTableId } from "./modules/core/tables/FunctionSelectors.sol"; import { KeysWithValue } from "./modules/keyswithvalue/tables/KeysWithValue.sol"; import { KeysInTable, KeysInTableData, KeysInTableTableId } from "./modules/keysintable/tables/KeysInTable.sol"; diff --git a/packages/world/src/interfaces/IAccessManagementSystem.sol b/packages/world/src/interfaces/IAccessManagementSystem.sol index 8f443689d5..2e2c56e5a2 100644 --- a/packages/world/src/interfaces/IAccessManagementSystem.sol +++ b/packages/world/src/interfaces/IAccessManagementSystem.sol @@ -3,10 +3,12 @@ pragma solidity >=0.8.0; /* Autogenerated file. Do not edit manually. */ +import { ResourceId } from "./../WorldResourceId.sol"; + interface IAccessManagementSystem { - function grantAccess(bytes32 resourceSelector, address grantee) external; + function grantAccess(ResourceId resourceId, address grantee) external; - function revokeAccess(bytes32 resourceSelector, address grantee) external; + function revokeAccess(ResourceId resourceId, address grantee) external; - function transferOwnership(bytes16 namespace, address newOwner) external; + function transferOwnership(ResourceId namespaceId, address newOwner) external; } diff --git a/packages/world/src/interfaces/IBalanceTransferSystem.sol b/packages/world/src/interfaces/IBalanceTransferSystem.sol index eddb986957..a00a3bc15c 100644 --- a/packages/world/src/interfaces/IBalanceTransferSystem.sol +++ b/packages/world/src/interfaces/IBalanceTransferSystem.sol @@ -3,8 +3,10 @@ pragma solidity >=0.8.0; /* Autogenerated file. Do not edit manually. */ +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + interface IBalanceTransferSystem { - function transferBalanceToNamespace(bytes16 fromNamespace, bytes16 toNamespace, uint256 amount) external; + function transferBalanceToNamespace(ResourceId fromNamespaceId, ResourceId toNamespaceId, uint256 amount) external; - function transferBalanceToAddress(bytes16 fromNamespace, address toAddress, uint256 amount) external; + function transferBalanceToAddress(ResourceId fromNamespaceId, address toAddress, uint256 amount) external; } diff --git a/packages/world/src/interfaces/IDelegationControl.sol b/packages/world/src/interfaces/IDelegationControl.sol index 6f68af9b32..ab528c291b 100644 --- a/packages/world/src/interfaces/IDelegationControl.sol +++ b/packages/world/src/interfaces/IDelegationControl.sol @@ -2,11 +2,12 @@ pragma solidity >=0.8.0; import { IWorldContextConsumer, WORLD_CONTEXT_CONSUMER_INTERFACE_ID } from "./IWorldContextConsumer.sol"; +import { ResourceId } from "../WorldResourceId.sol"; // ERC-165 Interface ID (see https://eips.ethereum.org/EIPS/eip-165) bytes4 constant DELEGATION_CONTROL_INTERFACE_ID = IDelegationControl.verify.selector ^ WORLD_CONTEXT_CONSUMER_INTERFACE_ID; interface IDelegationControl is IWorldContextConsumer { - function verify(address delegator, bytes32 systemId, bytes memory callData) external returns (bool); + function verify(address delegator, ResourceId systemId, bytes memory callData) external returns (bool); } diff --git a/packages/world/src/interfaces/IModule.sol b/packages/world/src/interfaces/IModule.sol index a4eb728608..8a79abd7db 100644 --- a/packages/world/src/interfaces/IModule.sol +++ b/packages/world/src/interfaces/IModule.sol @@ -10,7 +10,6 @@ bytes4 constant MODULE_INTERFACE_ID = IModule.getName.selector ^ ERC165_INTERFACE_ID; interface IModule is IERC165 { - error RequiredModuleNotFound(string resourceSelector); error RootInstallModeNotSupported(); error NonRootInstallNotSupported(); diff --git a/packages/world/src/interfaces/ISystemHook.sol b/packages/world/src/interfaces/ISystemHook.sol index a09c15f796..d6bde335c0 100644 --- a/packages/world/src/interfaces/ISystemHook.sol +++ b/packages/world/src/interfaces/ISystemHook.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0; import { IERC165, ERC165_INTERFACE_ID } from "./IERC165.sol"; +import { ResourceId } from "../WorldResourceId.sol"; // ERC-165 Interface ID (see https://eips.ethereum.org/EIPS/eip-165) bytes4 constant SYSTEM_HOOK_INTERFACE_ID = ISystemHook.onBeforeCallSystem.selector ^ @@ -9,7 +10,7 @@ bytes4 constant SYSTEM_HOOK_INTERFACE_ID = ISystemHook.onBeforeCallSystem.select ERC165_INTERFACE_ID; interface ISystemHook is IERC165 { - function onBeforeCallSystem(address msgSender, bytes32 resourceSelector, bytes memory callData) external; + function onBeforeCallSystem(address msgSender, ResourceId systemId, bytes memory callData) external; - function onAfterCallSystem(address msgSender, bytes32 resourceSelector, bytes memory callData) external; + function onAfterCallSystem(address msgSender, ResourceId systemId, bytes memory callData) external; } diff --git a/packages/world/src/interfaces/IWorldErrors.sol b/packages/world/src/interfaces/IWorldErrors.sol index 8804a161e9..ef421ff6b7 100644 --- a/packages/world/src/interfaces/IWorldErrors.sol +++ b/packages/world/src/interfaces/IWorldErrors.sol @@ -1,16 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + interface IWorldErrors { error WorldAlreadyInitialized(); - error ResourceExists(string resource); - error ResourceNotFound(string resource); + error ResourceExists(ResourceId resourceId, string resourceIdString); + error ResourceNotFound(ResourceId resourceId, string resourceIdString); error AccessDenied(string resource, address caller); - error InvalidSelector(string resource); + error InvalidResourceId(ResourceId resourceId, string resourceIdString); error SystemExists(address system); error FunctionSelectorExists(bytes4 functionSelector); error FunctionSelectorNotFound(bytes4 functionSelector); error DelegationNotFound(address delegator, address delegatee); error InsufficientBalance(uint256 balance, uint256 amount); error InterfaceNotSupported(address contractAddress, bytes4 interfaceId); + error InvalidResourceType(bytes2 expected, ResourceId resourceId, string resourceIdString); } diff --git a/packages/world/src/interfaces/IWorldKernel.sol b/packages/world/src/interfaces/IWorldKernel.sol index 72395d553d..ccb0909b11 100644 --- a/packages/world/src/interfaces/IWorldKernel.sol +++ b/packages/world/src/interfaces/IWorldKernel.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.0; import { IWorldErrors } from "./IWorldErrors.sol"; import { IModule } from "./IModule.sol"; +import { ResourceId } from "../WorldResourceId.sol"; interface IWorldModuleInstallation { /** @@ -15,18 +16,18 @@ interface IWorldModuleInstallation { interface IWorldCall { /** - * Call the system at the given resourceSelector. - * If the system is not public, the caller must have access to the namespace or name (encoded in the resourceSelector). + * Call the system at the given system ID. + * If the system is not public, the caller must have access to the namespace or name (encoded in the system ID). */ - function call(bytes32 resourceSelector, bytes memory callData) external payable returns (bytes memory); + function call(ResourceId systemId, bytes memory callData) external payable returns (bytes memory); /** - * Call the system at the given resourceSelector on behalf of the given delegator. - * If the system is not public, the delegator must have access to the namespace or name (encoded in the resourceSelector). + * Call the system at the given system ID on behalf of the given delegator. + * If the system is not public, the delegator must have access to the namespace or name (encoded in the system ID). */ function callFrom( address delegator, - bytes32 resourceSelector, + ResourceId systemId, bytes memory callData ) external payable returns (bytes memory); } diff --git a/packages/world/src/interfaces/IWorldRegistrationSystem.sol b/packages/world/src/interfaces/IWorldRegistrationSystem.sol index eda464a074..46638d3ee6 100644 --- a/packages/world/src/interfaces/IWorldRegistrationSystem.sol +++ b/packages/world/src/interfaces/IWorldRegistrationSystem.sol @@ -3,29 +3,30 @@ pragma solidity >=0.8.0; /* Autogenerated file. Do not edit manually. */ +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; import { ISystemHook } from "./ISystemHook.sol"; import { WorldContextConsumer } from "./../WorldContext.sol"; interface IWorldRegistrationSystem { - function registerNamespace(bytes16 namespace) external; + function registerNamespace(ResourceId namespaceId) external; - function registerSystemHook(bytes32 resourceSelector, ISystemHook hookAddress, uint8 enabledHooksBitmap) external; + function registerSystemHook(ResourceId systemId, ISystemHook hookAddress, uint8 enabledHooksBitmap) external; - function unregisterSystemHook(bytes32 resourceSelector, ISystemHook hookAddress) external; + function unregisterSystemHook(ResourceId systemId, ISystemHook hookAddress) external; - function registerSystem(bytes32 resourceSelector, WorldContextConsumer system, bool publicAccess) external; + function registerSystem(ResourceId systemId, WorldContextConsumer system, bool publicAccess) external; function registerFunctionSelector( - bytes32 resourceSelector, + ResourceId systemId, string memory systemFunctionName, string memory systemFunctionArguments ) external returns (bytes4 worldFunctionSelector); function registerRootFunctionSelector( - bytes32 resourceSelector, + ResourceId systemId, bytes4 worldFunctionSelector, bytes4 systemFunctionSelector ) external returns (bytes4); - function registerDelegation(address delegatee, bytes32 delegationControlId, bytes memory initCallData) external; + function registerDelegation(address delegatee, ResourceId delegationControlId, bytes memory initCallData) external; } diff --git a/packages/world/src/modules/core/CoreModule.sol b/packages/world/src/modules/core/CoreModule.sol index 9e8698d72a..bdbaca2226 100644 --- a/packages/world/src/modules/core/CoreModule.sol +++ b/packages/world/src/modules/core/CoreModule.sol @@ -2,15 +2,16 @@ pragma solidity >=0.8.0; import { WorldContextProvider } from "../../WorldContext.sol"; -import { ROOT_NAMESPACE } from "../../constants.sol"; -import { Resource } from "../../common.sol"; +import { ROOT_NAMESPACE, ROOT_NAMESPACE_ID } from "../../constants.sol"; import { Module } from "../../Module.sol"; import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; import { IStoreEphemeral } from "@latticexyz/store/src/IStore.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; -import { ResourceSelector } from "../../ResourceSelector.sol"; +import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol"; +import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../../WorldResourceId.sol"; +import { RESOURCE_SYSTEM } from "../../worldResourceTypes.sol"; import { NamespaceOwner } from "../../tables/NamespaceOwner.sol"; import { ResourceAccess } from "../../tables/ResourceAccess.sol"; @@ -22,7 +23,6 @@ import { CORE_MODULE_NAME, CORE_SYSTEM_NAME } from "./constants.sol"; import { Systems } from "./tables/Systems.sol"; import { FunctionSelectors } from "./tables/FunctionSelectors.sol"; -import { ResourceType } from "./tables/ResourceType.sol"; import { SystemHooks } from "./tables/SystemHooks.sol"; import { SystemRegistry } from "./tables/SystemRegistry.sol"; import { Balances } from "./tables/Balances.sol"; @@ -74,11 +74,10 @@ contract CoreModule is Module { FunctionSelectors.register(); SystemHooks.register(); SystemRegistry.register(); - ResourceType.register(); - NamespaceOwner._set(ROOT_NAMESPACE, _msgSender()); - ResourceAccess._set(ROOT_NAMESPACE, _msgSender(), true); - ResourceType._set(ROOT_NAMESPACE, Resource.NAMESPACE); + ResourceIds._setExists(ResourceId.unwrap(ROOT_NAMESPACE_ID), true); + NamespaceOwner._set(ResourceId.unwrap(ROOT_NAMESPACE_ID), _msgSender()); + ResourceAccess._set(ResourceId.unwrap(ROOT_NAMESPACE_ID), _msgSender(), true); } /** @@ -92,7 +91,11 @@ contract CoreModule is Module { target: coreSystem, callData: abi.encodeCall( WorldRegistrationSystem.registerSystem, - (ResourceSelector.from(ROOT_NAMESPACE, CORE_SYSTEM_NAME), CoreSystem(coreSystem), true) + ( + WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: ROOT_NAMESPACE, name: CORE_SYSTEM_NAME }), + CoreSystem(coreSystem), + true + ) ) }); } @@ -136,7 +139,11 @@ contract CoreModule is Module { target: coreSystem, callData: abi.encodeCall( WorldRegistrationSystem.registerRootFunctionSelector, - (ResourceSelector.from(ROOT_NAMESPACE, CORE_SYSTEM_NAME), functionSelectors[i], functionSelectors[i]) + ( + WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: ROOT_NAMESPACE, name: CORE_SYSTEM_NAME }), + functionSelectors[i], + functionSelectors[i] + ) ) }); } diff --git a/packages/world/src/modules/core/implementations/AccessManagementSystem.sol b/packages/world/src/modules/core/implementations/AccessManagementSystem.sol index cff47dd2db..feb058a0d9 100644 --- a/packages/world/src/modules/core/implementations/AccessManagementSystem.sol +++ b/packages/world/src/modules/core/implementations/AccessManagementSystem.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0; import { IModule } from "../../../interfaces/IModule.sol"; import { System } from "../../../System.sol"; import { AccessControl } from "../../../AccessControl.sol"; -import { ResourceSelector } from "../../../ResourceSelector.sol"; +import { ResourceId, WorldResourceIdLib } from "../../../WorldResourceId.sol"; import { ResourceAccess } from "../../../tables/ResourceAccess.sol"; import { InstalledModules } from "../../../tables/InstalledModules.sol"; import { NamespaceOwner } from "../../../tables/NamespaceOwner.sol"; @@ -14,27 +14,27 @@ import { NamespaceOwner } from "../../../tables/NamespaceOwner.sol"; */ contract AccessManagementSystem is System { /** - * Grant access to the resource at the given namespace and name. + * Grant access to the resource at the given resource ID. * Requires the caller to own the namespace. */ - function grantAccess(bytes32 resourceSelector, address grantee) public virtual { + function grantAccess(ResourceId resourceId, address grantee) public virtual { // Require the caller to own the namespace - AccessControl.requireOwner(resourceSelector, _msgSender()); + AccessControl.requireOwner(resourceId, _msgSender()); // Grant access to the given resource - ResourceAccess._set(resourceSelector, grantee, true); + ResourceAccess._set(ResourceId.unwrap(resourceId), grantee, true); } /** - * Revoke access from the resource at the given namespace and name. + * Revoke access from the resource at the given resource ID. * Requires the caller to own the namespace. */ - function revokeAccess(bytes32 resourceSelector, address grantee) public virtual { + function revokeAccess(ResourceId resourceId, address grantee) public virtual { // Require the caller to own the namespace - AccessControl.requireOwner(resourceSelector, _msgSender()); + AccessControl.requireOwner(resourceId, _msgSender()); // Revoke access from the given resource - ResourceAccess._deleteRecord(resourceSelector, grantee); + ResourceAccess._deleteRecord(ResourceId.unwrap(resourceId), grantee); } /** @@ -42,17 +42,17 @@ contract AccessManagementSystem is System { * Revoke ResourceAccess for previous owner and grant to newOwner. * Requires the caller to own the namespace. */ - function transferOwnership(bytes16 namespace, address newOwner) public virtual { + function transferOwnership(ResourceId namespaceId, address newOwner) public virtual { // Require the caller to own the namespace - AccessControl.requireOwner(namespace, _msgSender()); + AccessControl.requireOwner(namespaceId, _msgSender()); // Set namespace new owner - NamespaceOwner._set(namespace, newOwner); + NamespaceOwner._set(ResourceId.unwrap(namespaceId), newOwner); // Revoke access from old owner - ResourceAccess._deleteRecord(namespace, _msgSender()); + ResourceAccess._deleteRecord(ResourceId.unwrap(namespaceId), _msgSender()); // Grant access to new owner - ResourceAccess._set(namespace, newOwner, true); + ResourceAccess._set(ResourceId.unwrap(namespaceId), newOwner, true); } } diff --git a/packages/world/src/modules/core/implementations/BalanceTransferSystem.sol b/packages/world/src/modules/core/implementations/BalanceTransferSystem.sol index 9f0fdde1cd..5cbbb5a5cf 100644 --- a/packages/world/src/modules/core/implementations/BalanceTransferSystem.sol +++ b/packages/world/src/modules/core/implementations/BalanceTransferSystem.sol @@ -1,50 +1,63 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; +import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; + import { System } from "../../../System.sol"; import { revertWithBytes } from "../../../revertWithBytes.sol"; -import { ResourceSelector } from "../../../ResourceSelector.sol"; +import { WorldResourceIdLib, WorldResourceIdInstance } from "../../../WorldResourceId.sol"; import { AccessControl } from "../../../AccessControl.sol"; +import { RESOURCE_NAMESPACE } from "../../../worldResourceTypes.sol"; import { IWorldErrors } from "../../../interfaces/IWorldErrors.sol"; import { Balances } from "../tables/Balances.sol"; contract BalanceTransferSystem is System, IWorldErrors { - using ResourceSelector for bytes32; + using ResourceIdInstance for ResourceId; + using WorldResourceIdInstance for ResourceId; /** * Transfer balance to another namespace in the World */ - function transferBalanceToNamespace(bytes16 fromNamespace, bytes16 toNamespace, uint256 amount) public virtual { + function transferBalanceToNamespace( + ResourceId fromNamespaceId, + ResourceId toNamespaceId, + uint256 amount + ) public virtual { + // Require the target ID to be a namespace ID + if (toNamespaceId.getType() != RESOURCE_NAMESPACE) { + revert InvalidResourceType(RESOURCE_NAMESPACE, toNamespaceId, toNamespaceId.toString()); + } + // Require caller to have access to the namespace - AccessControl.requireAccess(fromNamespace, _msgSender()); + AccessControl.requireAccess(fromNamespaceId, _msgSender()); // Get current namespace balance - uint256 balance = Balances._get(fromNamespace); + uint256 balance = Balances._get(ResourceId.unwrap(fromNamespaceId)); // Require the balance balance to be greater or equal to the amount to transfer if (amount > balance) revert InsufficientBalance(balance, amount); // Update the balances - Balances._set(fromNamespace, balance - amount); - Balances._set(toNamespace, Balances._get(toNamespace) + amount); + Balances._set(ResourceId.unwrap(fromNamespaceId), balance - amount); + Balances._set(ResourceId.unwrap(toNamespaceId), Balances._get(ResourceId.unwrap(toNamespaceId)) + amount); } /** * Transfer balance out of the World */ - function transferBalanceToAddress(bytes16 fromNamespace, address toAddress, uint256 amount) public virtual { + function transferBalanceToAddress(ResourceId fromNamespaceId, address toAddress, uint256 amount) public virtual { // Require caller to have access to the namespace - AccessControl.requireAccess(fromNamespace, _msgSender()); + AccessControl.requireAccess(fromNamespaceId, _msgSender()); // Get current namespace balance - uint256 balance = Balances._get(fromNamespace); + uint256 balance = Balances._get(ResourceId.unwrap(fromNamespaceId)); // Require the balance balance to be greater or equal to the amount to transfer if (amount > balance) revert InsufficientBalance(balance, amount); // Update the balances - Balances._set(fromNamespace, balance - amount); + Balances._set(ResourceId.unwrap(fromNamespaceId), balance - amount); // Transfer the balance to the given address, revert on failure (bool success, bytes memory data) = payable(toAddress).call{ value: amount }(""); diff --git a/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol b/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol index 35f2309d8c..e5726d495f 100644 --- a/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol +++ b/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol @@ -6,18 +6,18 @@ import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; import { System } from "../../../System.sol"; -import { ResourceSelector } from "../../../ResourceSelector.sol"; +import { ResourceId, WorldResourceIdInstance } from "../../../WorldResourceId.sol"; import { AccessControl } from "../../../AccessControl.sol"; contract EphemeralRecordSystem is IStoreEphemeral, System { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; /** * Emit the ephemeral event without modifying storage at the given namespace and name. - * Requires the caller to have access to the namespace or name (encoded in the resource selector) + * Requires the caller to have access to the namespace or name (encoded in the table ID) */ function emitEphemeralRecord( - bytes32 resourceSelector, + ResourceId tableId, bytes32[] calldata keyTuple, bytes calldata staticData, PackedCounter encodedLengths, @@ -25,9 +25,9 @@ contract EphemeralRecordSystem is IStoreEphemeral, System { FieldLayout fieldLayout ) public virtual { // Require access to the namespace or name - AccessControl.requireAccess(resourceSelector, msg.sender); + AccessControl.requireAccess(tableId, msg.sender); // Set the record - StoreCore.emitEphemeralRecord(resourceSelector, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); + StoreCore.emitEphemeralRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); } } diff --git a/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol b/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol index f79d328b9c..b86a42fabe 100644 --- a/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol @@ -5,19 +5,19 @@ import { IStoreHook, STORE_HOOK_INTERFACE_ID } from "@latticexyz/store/src/IStor import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema } from "@latticexyz/store/src/Schema.sol"; +import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol"; import { System } from "../../../System.sol"; -import { ResourceSelector } from "../../../ResourceSelector.sol"; -import { Resource } from "../../../common.sol"; +import { ResourceId, WorldResourceIdInstance } from "../../../WorldResourceId.sol"; import { ROOT_NAMESPACE, ROOT_NAME } from "../../../constants.sol"; import { AccessControl } from "../../../AccessControl.sol"; import { requireInterface } from "../../../requireInterface.sol"; +import { revertWithBytes } from "../../../revertWithBytes.sol"; import { WorldContextProvider } from "../../../WorldContext.sol"; import { NamespaceOwner } from "../../../tables/NamespaceOwner.sol"; import { ResourceAccess } from "../../../tables/ResourceAccess.sol"; import { IWorldErrors } from "../../../interfaces/IWorldErrors.sol"; -import { ResourceType } from "../tables/ResourceType.sol"; import { SystemHooks } from "../tables/SystemHooks.sol"; import { SystemRegistry } from "../tables/SystemRegistry.sol"; import { Systems } from "../tables/Systems.sol"; @@ -31,13 +31,13 @@ import { WorldRegistrationSystem } from "./WorldRegistrationSystem.sol"; * Functions related to registering table resources in the World. */ contract StoreRegistrationSystem is System, IWorldErrors { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; /** * Register a table with the given config */ function registerTable( - bytes32 resourceSelector, + ResourceId tableId, FieldLayout fieldLayout, Schema keySchema, Schema valueSchema, @@ -45,42 +45,31 @@ contract StoreRegistrationSystem is System, IWorldErrors { string[] calldata fieldNames ) public virtual { // Require the name to not be the namespace's root name - if (resourceSelector.getName() == ROOT_NAME) revert InvalidSelector(resourceSelector.toString()); + if (tableId.getName() == ROOT_NAME) revert InvalidResourceId(tableId, tableId.toString()); // If the namespace doesn't exist yet, register it - bytes16 namespace = resourceSelector.getNamespace(); - if (ResourceType._get(namespace) == Resource.NONE) { - // We can't call IBaseWorld(this).registerNamespace directly because it would be handled like - // an external call, so msg.sender would be the address of the World contract - (address systemAddress, ) = Systems._get(ResourceSelector.from(ROOT_NAMESPACE, CORE_SYSTEM_NAME)); - WorldContextProvider.delegatecallWithContextOrRevert({ - msgSender: _msgSender(), - msgValue: 0, - target: systemAddress, - callData: abi.encodeCall(WorldRegistrationSystem.registerNamespace, (namespace)) - }); + ResourceId namespaceId = tableId.getNamespaceId(); + if (!ResourceIds._getExists(ResourceId.unwrap(namespaceId))) { + // Since this is a root system, we're in the context of the World contract already, + // so we can use delegatecall to register the namespace + (bool success, bytes memory data) = address(this).delegatecall( + abi.encodeCall(WorldRegistrationSystem.registerNamespace, (namespaceId)) + ); + if (!success) revertWithBytes(data); } else { // otherwise require caller to own the namespace - AccessControl.requireOwner(namespace, _msgSender()); + AccessControl.requireOwner(namespaceId, _msgSender()); } - // Require no resource to exist at this selector yet - if (ResourceType._get(resourceSelector) != Resource.NONE) { - revert ResourceExists(resourceSelector.toString()); - } - - // Store the table resource type - ResourceType._set(resourceSelector, Resource.TABLE); - // Register the table - StoreCore.registerTable(resourceSelector, fieldLayout, keySchema, valueSchema, keyNames, fieldNames); + StoreCore.registerTable(tableId, fieldLayout, keySchema, valueSchema, keyNames, fieldNames); } /** * Register a hook for the given tableId. * Requires the caller to own the namespace. */ - function registerStoreHook(bytes32 tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) public virtual { + function registerStoreHook(ResourceId tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) public virtual { // Require the hook to implement the store hook interface requireInterface(address(hookAddress), STORE_HOOK_INTERFACE_ID); @@ -95,7 +84,7 @@ contract StoreRegistrationSystem is System, IWorldErrors { * Unregister a hook for the given tableId. * Requires the caller to own the namespace. */ - function unregisterStoreHook(bytes32 tableId, IStoreHook hookAddress) public virtual { + function unregisterStoreHook(ResourceId tableId, IStoreHook hookAddress) public virtual { // Require caller to own the namespace AccessControl.requireOwner(tableId, _msgSender()); diff --git a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol index 58ecdea46f..6e0f75971b 100644 --- a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol @@ -2,13 +2,15 @@ pragma solidity >=0.8.0; import { Hook, HookLib } from "@latticexyz/store/src/Hook.sol"; +import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; +import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol"; import { System } from "../../../System.sol"; import { WorldContextConsumer, WORLD_CONTEXT_CONSUMER_INTERFACE_ID } from "../../../WorldContext.sol"; -import { ResourceSelector } from "../../../ResourceSelector.sol"; -import { Resource } from "../../../common.sol"; +import { WorldResourceIdLib, WorldResourceIdInstance } from "../../../WorldResourceId.sol"; import { SystemCall } from "../../../SystemCall.sol"; -import { ROOT_NAMESPACE, ROOT_NAME, UNLIMITED_DELEGATION } from "../../../constants.sol"; +import { ROOT_NAMESPACE_ID, ROOT_NAME, UNLIMITED_DELEGATION } from "../../../constants.sol"; +import { RESOURCE_NAMESPACE, RESOURCE_SYSTEM } from "../../../worldResourceTypes.sol"; import { AccessControl } from "../../../AccessControl.sol"; import { requireInterface } from "../../../requireInterface.sol"; import { NamespaceOwner } from "../../../tables/NamespaceOwner.sol"; @@ -18,7 +20,6 @@ import { ISystemHook, SYSTEM_HOOK_INTERFACE_ID } from "../../../interfaces/ISyst import { IWorldErrors } from "../../../interfaces/IWorldErrors.sol"; import { IDelegationControl, DELEGATION_CONTROL_INTERFACE_ID } from "../../../interfaces/IDelegationControl.sol"; -import { ResourceType } from "../tables/ResourceType.sol"; import { SystemHooks, SystemHooksTableId } from "../tables/SystemHooks.sol"; import { SystemRegistry } from "../tables/SystemRegistry.sol"; import { Systems } from "../tables/Systems.sol"; @@ -29,54 +30,59 @@ import { FunctionSelectors } from "../tables/FunctionSelectors.sol"; * Registering tables is implemented in StoreRegistrationSystem.sol */ contract WorldRegistrationSystem is System, IWorldErrors { - using ResourceSelector for bytes32; + using ResourceIdInstance for ResourceId; + using WorldResourceIdInstance for ResourceId; /** * Register a new namespace */ - function registerNamespace(bytes16 namespace) public virtual { - bytes32 resourceSelector = ResourceSelector.from(namespace); + function registerNamespace(ResourceId namespaceId) public virtual { + // Require the provided namespace ID to have type RESOURCE_NAMESPACE + if (namespaceId.getType() != RESOURCE_NAMESPACE) { + revert InvalidResourceType(RESOURCE_NAMESPACE, namespaceId, namespaceId.toString()); + } // Require namespace to not exist yet - if (ResourceType._get(namespace) != Resource.NONE) revert ResourceExists(resourceSelector.toString()); + if (ResourceIds._getExists(ResourceId.unwrap(namespaceId))) { + revert ResourceExists(namespaceId, namespaceId.toString()); + } - // Register namespace resource - ResourceType._set(namespace, Resource.NAMESPACE); + // Register namespace resource ID + ResourceIds._setExists(ResourceId.unwrap(namespaceId), true); // Register caller as the namespace owner - NamespaceOwner._set(namespace, _msgSender()); + NamespaceOwner._set(ResourceId.unwrap(namespaceId), _msgSender()); // Give caller access to the new namespace - ResourceAccess._set(resourceSelector, _msgSender(), true); + ResourceAccess._set(ResourceId.unwrap(namespaceId), _msgSender(), true); } /** - * Register a hook for the system at the given resource selector + * Register a hook for the system at the given system ID */ - function registerSystemHook( - bytes32 resourceSelector, - ISystemHook hookAddress, - uint8 enabledHooksBitmap - ) public virtual { + function registerSystemHook(ResourceId systemId, ISystemHook hookAddress, uint8 enabledHooksBitmap) public virtual { // Require the provided address to implement the ISystemHook interface requireInterface(address(hookAddress), SYSTEM_HOOK_INTERFACE_ID); // Require caller to own the namespace - AccessControl.requireOwner(resourceSelector, _msgSender()); + AccessControl.requireOwner(systemId, _msgSender()); // Register the hook - SystemHooks.push(resourceSelector, Hook.unwrap(HookLib.encode(address(hookAddress), enabledHooksBitmap))); + SystemHooks.push( + ResourceId.unwrap(systemId), + Hook.unwrap(HookLib.encode(address(hookAddress), enabledHooksBitmap)) + ); } /** - * Unregister the given hook for the system at the given resource selector + * Unregister the given hook for the system at the given system ID */ - function unregisterSystemHook(bytes32 resourceSelector, ISystemHook hookAddress) public virtual { + function unregisterSystemHook(ResourceId systemId, ISystemHook hookAddress) public virtual { // Require caller to own the namespace - AccessControl.requireOwner(resourceSelector, _msgSender()); + AccessControl.requireOwner(systemId, _msgSender()); - // Remove the hook from the list of hooks for this resourceSelector in the system hooks table - HookLib.filterListByAddress(SystemHooksTableId, resourceSelector, address(hookAddress)); + // Remove the hook from the list of hooks for this system in the system hooks table + HookLib.filterListByAddress(SystemHooksTableId, systemId, address(hookAddress)); } /** @@ -88,54 +94,56 @@ contract WorldRegistrationSystem is System, IWorldErrors { * Note: this function doesn't check whether a system already exists at the given selector, * making it possible to upgrade systems. */ - function registerSystem(bytes32 resourceSelector, WorldContextConsumer system, bool publicAccess) public virtual { + function registerSystem(ResourceId systemId, WorldContextConsumer system, bool publicAccess) public virtual { + // Require the provided system ID to have type RESOURCE_SYSTEM + if (systemId.getType() != RESOURCE_SYSTEM) { + revert InvalidResourceType(RESOURCE_SYSTEM, systemId, systemId.toString()); + } + // Require the provided address to implement the WorldContextConsumer interface requireInterface(address(system), WORLD_CONTEXT_CONSUMER_INTERFACE_ID); // Require the name to not be the namespace's root name - if (resourceSelector.getName() == ROOT_NAME) revert InvalidSelector(resourceSelector.toString()); + if (systemId.getName() == ROOT_NAME) revert InvalidResourceId(systemId, systemId.toString()); - // Require this system to not be registered at a different resource selector yet - bytes32 existingResourceSelector = SystemRegistry._get(address(system)); - if (existingResourceSelector != 0 && existingResourceSelector != resourceSelector) { + // Require this system to not be registered at a different system ID yet + bytes32 existingSystemId = SystemRegistry._get(address(system)); + if (existingSystemId != 0 && existingSystemId != ResourceId.unwrap(systemId)) { revert SystemExists(address(system)); } // If the namespace doesn't exist yet, register it - // otherwise require caller to own the namespace - bytes16 namespace = resourceSelector.getNamespace(); - if (ResourceType._get(namespace) == Resource.NONE) registerNamespace(namespace); - else AccessControl.requireOwner(namespace, _msgSender()); - - // Require no resource other than a system to exist at this selector yet - Resource resourceType = ResourceType._get(resourceSelector); - if (resourceType != Resource.NONE && resourceType != Resource.SYSTEM) { - revert ResourceExists(resourceSelector.toString()); + ResourceId namespaceId = systemId.getNamespaceId(); + if (!ResourceIds._getExists(ResourceId.unwrap(namespaceId))) { + registerNamespace(namespaceId); + } else { + // otherwise require caller to own the namespace + AccessControl.requireOwner(namespaceId, _msgSender()); } - // Check if a system already exists at this resource selector - address existingSystem = Systems._getSystem(resourceSelector); + // Check if a system already exists at this system ID + address existingSystem = Systems._getSystem(ResourceId.unwrap(systemId)); - // If there is an existing system with this resource selector, remove it + // If there is an existing system with this system ID, remove it if (existingSystem != address(0)) { // Remove the existing system from the system registry SystemRegistry._deleteRecord(existingSystem); // Remove the existing system's access to its namespace - ResourceAccess._deleteRecord(namespace, existingSystem); + ResourceAccess._deleteRecord(ResourceId.unwrap(namespaceId), existingSystem); } else { - // Otherwise, this is a new system, so register its resource type - ResourceType._set(resourceSelector, Resource.SYSTEM); + // Otherwise, this is a new system, so register its resource ID + ResourceIds._setExists(ResourceId.unwrap(systemId), true); } - // Systems = mapping from resourceSelector to system address and publicAccess - Systems._set(resourceSelector, address(system), publicAccess); + // Systems = mapping from system ID to system address and public access flag + Systems._set(ResourceId.unwrap(systemId), address(system), publicAccess); - // SystemRegistry = mapping from system address to resourceSelector - SystemRegistry._set(address(system), resourceSelector); + // SystemRegistry = mapping from system address to system ID + SystemRegistry._set(address(system), ResourceId.unwrap(systemId)); // Grant the system access to its namespace - ResourceAccess._set(namespace, address(system), true); + ResourceAccess._set(ResourceId.unwrap(namespaceId), address(system), true); } /** @@ -146,31 +154,31 @@ contract WorldRegistrationSystem is System, IWorldErrors { * TODO: replace separate systemFunctionName and systemFunctionArguments with a signature argument */ function registerFunctionSelector( - bytes32 resourceSelector, + ResourceId systemId, string memory systemFunctionName, string memory systemFunctionArguments ) public returns (bytes4 worldFunctionSelector) { // Require the caller to own the namespace - AccessControl.requireOwner(resourceSelector, _msgSender()); + AccessControl.requireOwner(systemId, _msgSender()); // Compute global function selector - string memory namespaceString = ResourceSelector.toTrimmedString(resourceSelector.getNamespace()); - string memory nameString = ResourceSelector.toTrimmedString(resourceSelector.getName()); + string memory namespaceString = WorldResourceIdLib.toTrimmedString(systemId.getNamespace()); + string memory nameString = WorldResourceIdLib.toTrimmedString(systemId.getName()); worldFunctionSelector = bytes4( keccak256(abi.encodePacked(namespaceString, "_", nameString, "_", systemFunctionName, systemFunctionArguments)) ); // Require the function selector to be globally unique - bytes32 existingResourceSelector = FunctionSelectors._getResourceSelector(worldFunctionSelector); + bytes32 existingSystemId = FunctionSelectors._getSystemId(worldFunctionSelector); - if (existingResourceSelector != 0) revert FunctionSelectorExists(worldFunctionSelector); + if (existingSystemId != 0) revert FunctionSelectorExists(worldFunctionSelector); // Register the function selector bytes memory systemFunctionSignature = abi.encodePacked(systemFunctionName, systemFunctionArguments); bytes4 systemFunctionSelector = systemFunctionSignature.length == 0 ? bytes4(0) // Save gas by storing 0x0 for empty function signatures (= fallback function) : bytes4(keccak256(systemFunctionSignature)); - FunctionSelectors._set(worldFunctionSelector, resourceSelector, systemFunctionSelector); + FunctionSelectors._set(worldFunctionSelector, ResourceId.unwrap(systemId), systemFunctionSelector); } /** @@ -181,20 +189,20 @@ contract WorldRegistrationSystem is System, IWorldErrors { * (see https://github.com/latticexyz/mud/issues/444) */ function registerRootFunctionSelector( - bytes32 resourceSelector, + ResourceId systemId, bytes4 worldFunctionSelector, bytes4 systemFunctionSelector ) public returns (bytes4) { // Require the caller to own the root namespace - AccessControl.requireOwner(ROOT_NAMESPACE, _msgSender()); + AccessControl.requireOwner(ROOT_NAMESPACE_ID, _msgSender()); // Require the function selector to be globally unique - bytes32 existingResourceSelector = FunctionSelectors._getResourceSelector(worldFunctionSelector); + bytes32 existingSystemId = FunctionSelectors._getSystemId(worldFunctionSelector); - if (existingResourceSelector != 0) revert FunctionSelectorExists(worldFunctionSelector); + if (existingSystemId != 0) revert FunctionSelectorExists(worldFunctionSelector); // Register the function selector - FunctionSelectors._set(worldFunctionSelector, resourceSelector, systemFunctionSelector); + FunctionSelectors._set(worldFunctionSelector, ResourceId.unwrap(systemId), systemFunctionSelector); return worldFunctionSelector; } @@ -202,23 +210,22 @@ contract WorldRegistrationSystem is System, IWorldErrors { /** * Register a delegation from the caller to the given delegatee. */ - function registerDelegation(address delegatee, bytes32 delegationControlId, bytes memory initCallData) public { + function registerDelegation(address delegatee, ResourceId delegationControlId, bytes memory initCallData) public { // Store the delegation control contract address - Delegations.set({ delegator: _msgSender(), delegatee: delegatee, delegationControlId: delegationControlId }); + Delegations.set({ + delegator: _msgSender(), + delegatee: delegatee, + delegationControlId: ResourceId.unwrap(delegationControlId) + }); // If the delegation is not unlimited... - if (delegationControlId != UNLIMITED_DELEGATION && initCallData.length > 0) { + if (ResourceId.unwrap(delegationControlId) != ResourceId.unwrap(UNLIMITED_DELEGATION) && initCallData.length > 0) { // Require the delegationControl contract to implement the IDelegationControl interface - (address delegationControl, ) = Systems._get(delegationControlId); + (address delegationControl, ) = Systems._get(ResourceId.unwrap(delegationControlId)); requireInterface(delegationControl, DELEGATION_CONTROL_INTERFACE_ID); // Call the delegation control contract's init function - SystemCall.call({ - caller: _msgSender(), - resourceSelector: delegationControlId, - callData: initCallData, - value: 0 - }); + SystemCall.call({ caller: _msgSender(), systemId: delegationControlId, callData: initCallData, value: 0 }); } } } diff --git a/packages/world/src/modules/core/tables/Balances.sol b/packages/world/src/modules/core/tables/Balances.sol index d2f043c64f..abdb7903f5 100644 --- a/packages/world/src/modules/core/tables/Balances.sol +++ b/packages/world/src/modules/core/tables/Balances.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Balances"))); -bytes32 constant BalancesTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Balances"))) +); +ResourceId constant BalancesTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0020010020000000000000000000000000000000000000000000000000000000 @@ -34,7 +38,7 @@ library Balances { /** Get the table's key schema */ function getKeySchema() internal pure returns (Schema) { SchemaType[] memory _keySchema = new SchemaType[](1); - _keySchema[0] = SchemaType.BYTES16; + _keySchema[0] = SchemaType.BYTES32; return SchemaLib.encode(_keySchema); } @@ -50,7 +54,7 @@ library Balances { /** Get the table's key names */ function getKeyNames() internal pure returns (string[] memory keyNames) { keyNames = new string[](1); - keyNames[0] = "namespace"; + keyNames[0] = "namespaceId"; } /** Get the table's field names */ @@ -75,103 +79,103 @@ library Balances { } /** Get balance */ - function getBalance(bytes16 namespace) internal view returns (uint256 balance) { + function getBalance(bytes32 namespaceId) internal view returns (uint256 balance) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); } /** Get balance */ - function _getBalance(bytes16 namespace) internal view returns (uint256 balance) { + function _getBalance(bytes32 namespaceId) internal view returns (uint256 balance) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); } /** Get balance (using the specified store) */ - function getBalance(IStore _store, bytes16 namespace) internal view returns (uint256 balance) { + function getBalance(IStore _store, bytes32 namespaceId) internal view returns (uint256 balance) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); } /** Get balance */ - function get(bytes16 namespace) internal view returns (uint256 balance) { + function get(bytes32 namespaceId) internal view returns (uint256 balance) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); } /** Get balance */ - function _get(bytes16 namespace) internal view returns (uint256 balance) { + function _get(bytes32 namespaceId) internal view returns (uint256 balance) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); } /** Get balance (using the specified store) */ - function get(IStore _store, bytes16 namespace) internal view returns (uint256 balance) { + function get(IStore _store, bytes32 namespaceId) internal view returns (uint256 balance) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); } /** Set balance */ - function setBalance(bytes16 namespace, uint256 balance) internal { + function setBalance(bytes32 namespaceId, uint256 balance) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); } /** Set balance */ - function _setBalance(bytes16 namespace, uint256 balance) internal { + function _setBalance(bytes32 namespaceId, uint256 balance) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); } /** Set balance (using the specified store) */ - function setBalance(IStore _store, bytes16 namespace, uint256 balance) internal { + function setBalance(IStore _store, bytes32 namespaceId, uint256 balance) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); } /** Set balance */ - function set(bytes16 namespace, uint256 balance) internal { + function set(bytes32 namespaceId, uint256 balance) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); } /** Set balance */ - function _set(bytes16 namespace, uint256 balance) internal { + function _set(bytes32 namespaceId, uint256 balance) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); } /** Set balance (using the specified store) */ - function set(IStore _store, bytes16 namespace, uint256 balance) internal { + function set(IStore _store, bytes32 namespaceId, uint256 balance) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); } @@ -192,33 +196,33 @@ library Balances { } /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(bytes16 namespace) internal pure returns (bytes32[] memory) { + function encodeKeyTuple(bytes32 namespaceId) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; return _keyTuple; } /* Delete all data for given keys */ - function deleteRecord(bytes16 namespace) internal { + function deleteRecord(bytes32 namespaceId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys */ - function _deleteRecord(bytes16 namespace) internal { + function _deleteRecord(bytes32 namespaceId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes16 namespace) internal { + function deleteRecord(IStore _store, bytes32 namespaceId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } diff --git a/packages/world/src/modules/core/tables/FunctionSelectors.sol b/packages/world/src/modules/core/tables/FunctionSelectors.sol index e92a0ff17b..19c200d122 100644 --- a/packages/world/src/modules/core/tables/FunctionSelectors.sol +++ b/packages/world/src/modules/core/tables/FunctionSelectors.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("FunctionSelector"))); -bytes32 constant FunctionSelectorsTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("FunctionSelector"))) +); +ResourceId constant FunctionSelectorsTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0024020020040000000000000000000000000000000000000000000000000000 @@ -57,7 +61,7 @@ library FunctionSelectors { /** Get the table's field names */ function getFieldNames() internal pure returns (string[] memory fieldNames) { fieldNames = new string[](2); - fieldNames[0] = "resourceSelector"; + fieldNames[0] = "systemId"; fieldNames[1] = "systemFunctionSelector"; } @@ -76,8 +80,8 @@ library FunctionSelectors { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } - /** Get resourceSelector */ - function getResourceSelector(bytes4 functionSelector) internal view returns (bytes32 resourceSelector) { + /** Get systemId */ + function getSystemId(bytes4 functionSelector) internal view returns (bytes32 systemId) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); @@ -85,8 +89,8 @@ library FunctionSelectors { return (bytes32(_blob)); } - /** Get resourceSelector */ - function _getResourceSelector(bytes4 functionSelector) internal view returns (bytes32 resourceSelector) { + /** Get systemId */ + function _getSystemId(bytes4 functionSelector) internal view returns (bytes32 systemId) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); @@ -94,11 +98,8 @@ library FunctionSelectors { return (bytes32(_blob)); } - /** Get resourceSelector (using the specified store) */ - function getResourceSelector( - IStore _store, - bytes4 functionSelector - ) internal view returns (bytes32 resourceSelector) { + /** Get systemId (using the specified store) */ + function getSystemId(IStore _store, bytes4 functionSelector) internal view returns (bytes32 systemId) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); @@ -106,28 +107,28 @@ library FunctionSelectors { return (bytes32(_blob)); } - /** Set resourceSelector */ - function setResourceSelector(bytes4 functionSelector, bytes32 resourceSelector) internal { + /** Set systemId */ + function setSystemId(bytes4 functionSelector, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((systemId)), _fieldLayout); } - /** Set resourceSelector */ - function _setResourceSelector(bytes4 functionSelector, bytes32 resourceSelector) internal { + /** Set systemId */ + function _setSystemId(bytes4 functionSelector, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((systemId)), _fieldLayout); } - /** Set resourceSelector (using the specified store) */ - function setResourceSelector(IStore _store, bytes4 functionSelector, bytes32 resourceSelector) internal { + /** Set systemId (using the specified store) */ + function setSystemId(IStore _store, bytes4 functionSelector, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((systemId)), _fieldLayout); } /** Get systemFunctionSelector */ @@ -185,9 +186,7 @@ library FunctionSelectors { } /** Get the full data */ - function get( - bytes4 functionSelector - ) internal view returns (bytes32 resourceSelector, bytes4 systemFunctionSelector) { + function get(bytes4 functionSelector) internal view returns (bytes32 systemId, bytes4 systemFunctionSelector) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); @@ -200,9 +199,7 @@ library FunctionSelectors { } /** Get the full data */ - function _get( - bytes4 functionSelector - ) internal view returns (bytes32 resourceSelector, bytes4 systemFunctionSelector) { + function _get(bytes4 functionSelector) internal view returns (bytes32 systemId, bytes4 systemFunctionSelector) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); @@ -218,7 +215,7 @@ library FunctionSelectors { function get( IStore _store, bytes4 functionSelector - ) internal view returns (bytes32 resourceSelector, bytes4 systemFunctionSelector) { + ) internal view returns (bytes32 systemId, bytes4 systemFunctionSelector) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); @@ -231,8 +228,8 @@ library FunctionSelectors { } /** Set the full data using individual values */ - function set(bytes4 functionSelector, bytes32 resourceSelector, bytes4 systemFunctionSelector) internal { - bytes memory _staticData = encodeStatic(resourceSelector, systemFunctionSelector); + function set(bytes4 functionSelector, bytes32 systemId, bytes4 systemFunctionSelector) internal { + bytes memory _staticData = encodeStatic(systemId, systemFunctionSelector); PackedCounter _encodedLengths; bytes memory _dynamicData; @@ -244,8 +241,8 @@ library FunctionSelectors { } /** Set the full data using individual values */ - function _set(bytes4 functionSelector, bytes32 resourceSelector, bytes4 systemFunctionSelector) internal { - bytes memory _staticData = encodeStatic(resourceSelector, systemFunctionSelector); + function _set(bytes4 functionSelector, bytes32 systemId, bytes4 systemFunctionSelector) internal { + bytes memory _staticData = encodeStatic(systemId, systemFunctionSelector); PackedCounter _encodedLengths; bytes memory _dynamicData; @@ -257,13 +254,8 @@ library FunctionSelectors { } /** Set the full data using individual values (using the specified store) */ - function set( - IStore _store, - bytes4 functionSelector, - bytes32 resourceSelector, - bytes4 systemFunctionSelector - ) internal { - bytes memory _staticData = encodeStatic(resourceSelector, systemFunctionSelector); + function set(IStore _store, bytes4 functionSelector, bytes32 systemId, bytes4 systemFunctionSelector) internal { + bytes memory _staticData = encodeStatic(systemId, systemFunctionSelector); PackedCounter _encodedLengths; bytes memory _dynamicData; @@ -278,10 +270,8 @@ library FunctionSelectors { * Decode the tightly packed blob of static data using this table's field layout * Undefined behaviour for invalid blobs */ - function decodeStatic( - bytes memory _blob - ) internal pure returns (bytes32 resourceSelector, bytes4 systemFunctionSelector) { - resourceSelector = (Bytes.slice32(_blob, 0)); + function decodeStatic(bytes memory _blob) internal pure returns (bytes32 systemId, bytes4 systemFunctionSelector) { + systemId = (Bytes.slice32(_blob, 0)); systemFunctionSelector = (Bytes.slice4(_blob, 32)); } @@ -294,21 +284,21 @@ library FunctionSelectors { bytes memory _staticData, PackedCounter, bytes memory - ) internal pure returns (bytes32 resourceSelector, bytes4 systemFunctionSelector) { - (resourceSelector, systemFunctionSelector) = decodeStatic(_staticData); + ) internal pure returns (bytes32 systemId, bytes4 systemFunctionSelector) { + (systemId, systemFunctionSelector) = decodeStatic(_staticData); } /** Tightly pack static data using this table's schema */ - function encodeStatic(bytes32 resourceSelector, bytes4 systemFunctionSelector) internal pure returns (bytes memory) { - return abi.encodePacked(resourceSelector, systemFunctionSelector); + function encodeStatic(bytes32 systemId, bytes4 systemFunctionSelector) internal pure returns (bytes memory) { + return abi.encodePacked(systemId, systemFunctionSelector); } /** Tightly pack full data using this table's field layout */ function encode( - bytes32 resourceSelector, + bytes32 systemId, bytes4 systemFunctionSelector ) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(resourceSelector, systemFunctionSelector); + bytes memory _staticData = encodeStatic(systemId, systemFunctionSelector); PackedCounter _encodedLengths; bytes memory _dynamicData; diff --git a/packages/world/src/modules/core/tables/ResourceType.sol b/packages/world/src/modules/core/tables/ResourceType.sol deleted file mode 100644 index 3eede246e2..0000000000 --- a/packages/world/src/modules/core/tables/ResourceType.sol +++ /dev/null @@ -1,228 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; - -/* Autogenerated file. Do not edit manually. */ - -// Import schema type -import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; - -// Import store internals -import { IStore } from "@latticexyz/store/src/IStore.sol"; -import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; -import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; -import { Bytes } from "@latticexyz/store/src/Bytes.sol"; -import { Memory } from "@latticexyz/store/src/Memory.sol"; -import { SliceLib } from "@latticexyz/store/src/Slice.sol"; -import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; -import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; -import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; -import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; - -// Import user types -import { Resource } from "./../../../common.sol"; - -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("ResourceType"))); -bytes32 constant ResourceTypeTableId = _tableId; - -FieldLayout constant _fieldLayout = FieldLayout.wrap( - 0x0001010001000000000000000000000000000000000000000000000000000000 -); - -library ResourceType { - /** Get the table values' field layout */ - function getFieldLayout() internal pure returns (FieldLayout) { - return _fieldLayout; - } - - /** Get the table's key schema */ - function getKeySchema() internal pure returns (Schema) { - SchemaType[] memory _keySchema = new SchemaType[](1); - _keySchema[0] = SchemaType.BYTES32; - - return SchemaLib.encode(_keySchema); - } - - /** Get the table's value schema */ - function getValueSchema() internal pure returns (Schema) { - SchemaType[] memory _valueSchema = new SchemaType[](1); - _valueSchema[0] = SchemaType.UINT8; - - return SchemaLib.encode(_valueSchema); - } - - /** Get the table's key names */ - function getKeyNames() internal pure returns (string[] memory keyNames) { - keyNames = new string[](1); - keyNames[0] = "resourceSelector"; - } - - /** Get the table's field names */ - function getFieldNames() internal pure returns (string[] memory fieldNames) { - fieldNames = new string[](1); - fieldNames[0] = "resourceType"; - } - - /** Register the table with its config */ - function register() internal { - StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); - } - - /** Register the table with its config */ - function _register() internal { - StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); - } - - /** Register the table with its config (using the specified store) */ - function register(IStore _store) internal { - _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); - } - - /** Get resourceType */ - function getResourceType(bytes32 resourceSelector) internal view returns (Resource resourceType) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); - return Resource(uint8(bytes1(_blob))); - } - - /** Get resourceType */ - function _getResourceType(bytes32 resourceSelector) internal view returns (Resource resourceType) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); - return Resource(uint8(bytes1(_blob))); - } - - /** Get resourceType (using the specified store) */ - function getResourceType(IStore _store, bytes32 resourceSelector) internal view returns (Resource resourceType) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); - return Resource(uint8(bytes1(_blob))); - } - - /** Get resourceType */ - function get(bytes32 resourceSelector) internal view returns (Resource resourceType) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); - return Resource(uint8(bytes1(_blob))); - } - - /** Get resourceType */ - function _get(bytes32 resourceSelector) internal view returns (Resource resourceType) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); - return Resource(uint8(bytes1(_blob))); - } - - /** Get resourceType (using the specified store) */ - function get(IStore _store, bytes32 resourceSelector) internal view returns (Resource resourceType) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); - return Resource(uint8(bytes1(_blob))); - } - - /** Set resourceType */ - function setResourceType(bytes32 resourceSelector, Resource resourceType) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), _fieldLayout); - } - - /** Set resourceType */ - function _setResourceType(bytes32 resourceSelector, Resource resourceType) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), _fieldLayout); - } - - /** Set resourceType (using the specified store) */ - function setResourceType(IStore _store, bytes32 resourceSelector, Resource resourceType) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), _fieldLayout); - } - - /** Set resourceType */ - function set(bytes32 resourceSelector, Resource resourceType) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), _fieldLayout); - } - - /** Set resourceType */ - function _set(bytes32 resourceSelector, Resource resourceType) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), _fieldLayout); - } - - /** Set resourceType (using the specified store) */ - function set(IStore _store, bytes32 resourceSelector, Resource resourceType) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), _fieldLayout); - } - - /** Tightly pack static data using this table's schema */ - function encodeStatic(Resource resourceType) internal pure returns (bytes memory) { - return abi.encodePacked(resourceType); - } - - /** Tightly pack full data using this table's field layout */ - function encode(Resource resourceType) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(resourceType); - - PackedCounter _encodedLengths; - bytes memory _dynamicData; - - return (_staticData, _encodedLengths, _dynamicData); - } - - /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(bytes32 resourceSelector) internal pure returns (bytes32[] memory) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - return _keyTuple; - } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 resourceSelector) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 resourceSelector) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 resourceSelector) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } -} diff --git a/packages/world/src/modules/core/tables/SystemHooks.sol b/packages/world/src/modules/core/tables/SystemHooks.sol index 8e7409166f..0201700a2d 100644 --- a/packages/world/src/modules/core/tables/SystemHooks.sol +++ b/packages/world/src/modules/core/tables/SystemHooks.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("SystemHooks"))); -bytes32 constant SystemHooksTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("SystemHooks"))) +); +ResourceId constant SystemHooksTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 @@ -50,7 +54,7 @@ library SystemHooks { /** Get the table's key names */ function getKeyNames() internal pure returns (string[] memory keyNames) { keyNames = new string[](1); - keyNames[0] = "resourceSelector"; + keyNames[0] = "systemId"; } /** Get the table's field names */ @@ -75,111 +79,111 @@ library SystemHooks { } /** Get value */ - function getValue(bytes32 resourceSelector) internal view returns (bytes21[] memory value) { + function getValue(bytes32 systemId) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } /** Get value */ - function _getValue(bytes32 resourceSelector) internal view returns (bytes21[] memory value) { + function _getValue(bytes32 systemId) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } /** Get value (using the specified store) */ - function getValue(IStore _store, bytes32 resourceSelector) internal view returns (bytes21[] memory value) { + function getValue(IStore _store, bytes32 systemId) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } /** Get value */ - function get(bytes32 resourceSelector) internal view returns (bytes21[] memory value) { + function get(bytes32 systemId) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } /** Get value */ - function _get(bytes32 resourceSelector) internal view returns (bytes21[] memory value) { + function _get(bytes32 systemId) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } /** Get value (using the specified store) */ - function get(IStore _store, bytes32 resourceSelector) internal view returns (bytes21[] memory value) { + function get(IStore _store, bytes32 systemId) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } /** Set value */ - function setValue(bytes32 resourceSelector, bytes21[] memory value) internal { + function setValue(bytes32 systemId, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value */ - function _setValue(bytes32 resourceSelector, bytes21[] memory value) internal { + function _setValue(bytes32 systemId, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value (using the specified store) */ - function setValue(IStore _store, bytes32 resourceSelector, bytes21[] memory value) internal { + function setValue(IStore _store, bytes32 systemId, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value */ - function set(bytes32 resourceSelector, bytes21[] memory value) internal { + function set(bytes32 systemId, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value */ - function _set(bytes32 resourceSelector, bytes21[] memory value) internal { + function _set(bytes32 systemId, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value (using the specified store) */ - function set(IStore _store, bytes32 resourceSelector, bytes21[] memory value) internal { + function set(IStore _store, bytes32 systemId, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Get the length of value */ - function lengthValue(bytes32 resourceSelector) internal view returns (uint256) { + function lengthValue(bytes32 systemId) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { @@ -188,9 +192,9 @@ library SystemHooks { } /** Get the length of value */ - function _lengthValue(bytes32 resourceSelector) internal view returns (uint256) { + function _lengthValue(bytes32 systemId) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { @@ -199,9 +203,9 @@ library SystemHooks { } /** Get the length of value (using the specified store) */ - function lengthValue(IStore _store, bytes32 resourceSelector) internal view returns (uint256) { + function lengthValue(IStore _store, bytes32 systemId) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { @@ -210,9 +214,9 @@ library SystemHooks { } /** Get the length of value */ - function length(bytes32 resourceSelector) internal view returns (uint256) { + function length(bytes32 systemId) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { @@ -221,9 +225,9 @@ library SystemHooks { } /** Get the length of value */ - function _length(bytes32 resourceSelector) internal view returns (uint256) { + function _length(bytes32 systemId) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { @@ -232,9 +236,9 @@ library SystemHooks { } /** Get the length of value (using the specified store) */ - function length(IStore _store, bytes32 resourceSelector) internal view returns (uint256) { + function length(IStore _store, bytes32 systemId) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { @@ -246,9 +250,9 @@ library SystemHooks { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function getItemValue(bytes32 resourceSelector, uint256 _index) internal view returns (bytes21) { + function getItemValue(bytes32 systemId, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { bytes memory _blob = StoreSwitch.getFieldSlice( @@ -267,9 +271,9 @@ library SystemHooks { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function _getItemValue(bytes32 resourceSelector, uint256 _index) internal view returns (bytes21) { + function _getItemValue(bytes32 systemId, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { bytes memory _blob = StoreCore.getFieldSlice( @@ -288,9 +292,9 @@ library SystemHooks { * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) */ - function getItemValue(IStore _store, bytes32 resourceSelector, uint256 _index) internal view returns (bytes21) { + function getItemValue(IStore _store, bytes32 systemId, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 21, (_index + 1) * 21); @@ -302,9 +306,9 @@ library SystemHooks { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function getItem(bytes32 resourceSelector, uint256 _index) internal view returns (bytes21) { + function getItem(bytes32 systemId, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { bytes memory _blob = StoreSwitch.getFieldSlice( @@ -323,9 +327,9 @@ library SystemHooks { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function _getItem(bytes32 resourceSelector, uint256 _index) internal view returns (bytes21) { + function _getItem(bytes32 systemId, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { bytes memory _blob = StoreCore.getFieldSlice( @@ -344,9 +348,9 @@ library SystemHooks { * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) */ - function getItem(IStore _store, bytes32 resourceSelector, uint256 _index) internal view returns (bytes21) { + function getItem(IStore _store, bytes32 systemId, uint256 _index) internal view returns (bytes21) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 21, (_index + 1) * 21); @@ -355,97 +359,97 @@ library SystemHooks { } /** Push an element to value */ - function pushValue(bytes32 resourceSelector, bytes21 _element) internal { + function pushValue(bytes32 systemId, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value */ - function _pushValue(bytes32 resourceSelector, bytes21 _element) internal { + function _pushValue(bytes32 systemId, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value (using the specified store) */ - function pushValue(IStore _store, bytes32 resourceSelector, bytes21 _element) internal { + function pushValue(IStore _store, bytes32 systemId, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value */ - function push(bytes32 resourceSelector, bytes21 _element) internal { + function push(bytes32 systemId, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value */ - function _push(bytes32 resourceSelector, bytes21 _element) internal { + function _push(bytes32 systemId, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value (using the specified store) */ - function push(IStore _store, bytes32 resourceSelector, bytes21 _element) internal { + function push(IStore _store, bytes32 systemId, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from value */ - function popValue(bytes32 resourceSelector) internal { + function popValue(bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** Pop an element from value */ - function _popValue(bytes32 resourceSelector) internal { + function _popValue(bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** Pop an element from value (using the specified store) */ - function popValue(IStore _store, bytes32 resourceSelector) internal { + function popValue(IStore _store, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** Pop an element from value */ - function pop(bytes32 resourceSelector) internal { + function pop(bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** Pop an element from value */ - function _pop(bytes32 resourceSelector) internal { + function _pop(bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** Pop an element from value (using the specified store) */ - function pop(IStore _store, bytes32 resourceSelector) internal { + function pop(IStore _store, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } @@ -454,9 +458,9 @@ library SystemHooks { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function updateValue(bytes32 resourceSelector, uint256 _index, bytes21 _element) internal { + function updateValue(bytes32 systemId, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); @@ -467,9 +471,9 @@ library SystemHooks { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function _updateValue(bytes32 resourceSelector, uint256 _index, bytes21 _element) internal { + function _updateValue(bytes32 systemId, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); @@ -480,9 +484,9 @@ library SystemHooks { * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function updateValue(IStore _store, bytes32 resourceSelector, uint256 _index, bytes21 _element) internal { + function updateValue(IStore _store, bytes32 systemId, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { _store.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); @@ -493,9 +497,9 @@ library SystemHooks { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function update(bytes32 resourceSelector, uint256 _index, bytes21 _element) internal { + function update(bytes32 systemId, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); @@ -506,9 +510,9 @@ library SystemHooks { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function _update(bytes32 resourceSelector, uint256 _index, bytes21 _element) internal { + function _update(bytes32 systemId, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); @@ -519,9 +523,9 @@ library SystemHooks { * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function update(IStore _store, bytes32 resourceSelector, uint256 _index, bytes21 _element) internal { + function update(IStore _store, bytes32 systemId, uint256 _index, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; unchecked { _store.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); @@ -551,33 +555,33 @@ library SystemHooks { } /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(bytes32 resourceSelector) internal pure returns (bytes32[] memory) { + function encodeKeyTuple(bytes32 systemId) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; return _keyTuple; } /* Delete all data for given keys */ - function deleteRecord(bytes32 resourceSelector) internal { + function deleteRecord(bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys */ - function _deleteRecord(bytes32 resourceSelector) internal { + function _deleteRecord(bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 resourceSelector) internal { + function deleteRecord(IStore _store, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } diff --git a/packages/world/src/modules/core/tables/SystemRegistry.sol b/packages/world/src/modules/core/tables/SystemRegistry.sol index 81a877f73d..58064ea817 100644 --- a/packages/world/src/modules/core/tables/SystemRegistry.sol +++ b/packages/world/src/modules/core/tables/SystemRegistry.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("SystemRegistry"))); -bytes32 constant SystemRegistryTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("SystemRegistry"))) +); +ResourceId constant SystemRegistryTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0020010020000000000000000000000000000000000000000000000000000000 @@ -56,7 +60,7 @@ library SystemRegistry { /** Get the table's field names */ function getFieldNames() internal pure returns (string[] memory fieldNames) { fieldNames = new string[](1); - fieldNames[0] = "resourceSelector"; + fieldNames[0] = "systemId"; } /** Register the table with its config */ @@ -74,8 +78,8 @@ library SystemRegistry { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } - /** Get resourceSelector */ - function getResourceSelector(address system) internal view returns (bytes32 resourceSelector) { + /** Get systemId */ + function getSystemId(address system) internal view returns (bytes32 systemId) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); @@ -83,8 +87,8 @@ library SystemRegistry { return (bytes32(_blob)); } - /** Get resourceSelector */ - function _getResourceSelector(address system) internal view returns (bytes32 resourceSelector) { + /** Get systemId */ + function _getSystemId(address system) internal view returns (bytes32 systemId) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); @@ -92,8 +96,8 @@ library SystemRegistry { return (bytes32(_blob)); } - /** Get resourceSelector (using the specified store) */ - function getResourceSelector(IStore _store, address system) internal view returns (bytes32 resourceSelector) { + /** Get systemId (using the specified store) */ + function getSystemId(IStore _store, address system) internal view returns (bytes32 systemId) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); @@ -101,8 +105,8 @@ library SystemRegistry { return (bytes32(_blob)); } - /** Get resourceSelector */ - function get(address system) internal view returns (bytes32 resourceSelector) { + /** Get systemId */ + function get(address system) internal view returns (bytes32 systemId) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); @@ -110,8 +114,8 @@ library SystemRegistry { return (bytes32(_blob)); } - /** Get resourceSelector */ - function _get(address system) internal view returns (bytes32 resourceSelector) { + /** Get systemId */ + function _get(address system) internal view returns (bytes32 systemId) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); @@ -119,8 +123,8 @@ library SystemRegistry { return (bytes32(_blob)); } - /** Get resourceSelector (using the specified store) */ - function get(IStore _store, address system) internal view returns (bytes32 resourceSelector) { + /** Get systemId (using the specified store) */ + function get(IStore _store, address system) internal view returns (bytes32 systemId) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); @@ -128,62 +132,62 @@ library SystemRegistry { return (bytes32(_blob)); } - /** Set resourceSelector */ - function setResourceSelector(address system, bytes32 resourceSelector) internal { + /** Set systemId */ + function setSystemId(address system, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((systemId)), _fieldLayout); } - /** Set resourceSelector */ - function _setResourceSelector(address system, bytes32 resourceSelector) internal { + /** Set systemId */ + function _setSystemId(address system, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((systemId)), _fieldLayout); } - /** Set resourceSelector (using the specified store) */ - function setResourceSelector(IStore _store, address system, bytes32 resourceSelector) internal { + /** Set systemId (using the specified store) */ + function setSystemId(IStore _store, address system, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((systemId)), _fieldLayout); } - /** Set resourceSelector */ - function set(address system, bytes32 resourceSelector) internal { + /** Set systemId */ + function set(address system, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((systemId)), _fieldLayout); } - /** Set resourceSelector */ - function _set(address system, bytes32 resourceSelector) internal { + /** Set systemId */ + function _set(address system, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((systemId)), _fieldLayout); } - /** Set resourceSelector (using the specified store) */ - function set(IStore _store, address system, bytes32 resourceSelector) internal { + /** Set systemId (using the specified store) */ + function set(IStore _store, address system, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((systemId)), _fieldLayout); } /** Tightly pack static data using this table's schema */ - function encodeStatic(bytes32 resourceSelector) internal pure returns (bytes memory) { - return abi.encodePacked(resourceSelector); + function encodeStatic(bytes32 systemId) internal pure returns (bytes memory) { + return abi.encodePacked(systemId); } /** Tightly pack full data using this table's field layout */ - function encode(bytes32 resourceSelector) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(resourceSelector); + function encode(bytes32 systemId) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(systemId); PackedCounter _encodedLengths; bytes memory _dynamicData; diff --git a/packages/world/src/modules/core/tables/Systems.sol b/packages/world/src/modules/core/tables/Systems.sol index 8a60905326..2da7769044 100644 --- a/packages/world/src/modules/core/tables/Systems.sol +++ b/packages/world/src/modules/core/tables/Systems.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Systems"))); -bytes32 constant SystemsTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Systems"))) +); +ResourceId constant SystemsTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0015020014010000000000000000000000000000000000000000000000000000 @@ -51,7 +55,7 @@ library Systems { /** Get the table's key names */ function getKeyNames() internal pure returns (string[] memory keyNames) { keyNames = new string[](1); - keyNames[0] = "resourceSelector"; + keyNames[0] = "systemId"; } /** Get the table's field names */ @@ -77,111 +81,111 @@ library Systems { } /** Get system */ - function getSystem(bytes32 resourceSelector) internal view returns (address system) { + function getSystem(bytes32 systemId) internal view returns (address system) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (address(bytes20(_blob))); } /** Get system */ - function _getSystem(bytes32 resourceSelector) internal view returns (address system) { + function _getSystem(bytes32 systemId) internal view returns (address system) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (address(bytes20(_blob))); } /** Get system (using the specified store) */ - function getSystem(IStore _store, bytes32 resourceSelector) internal view returns (address system) { + function getSystem(IStore _store, bytes32 systemId) internal view returns (address system) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (address(bytes20(_blob))); } /** Set system */ - function setSystem(bytes32 resourceSelector, address system) internal { + function setSystem(bytes32 systemId, address system) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((system)), _fieldLayout); } /** Set system */ - function _setSystem(bytes32 resourceSelector, address system) internal { + function _setSystem(bytes32 systemId, address system) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((system)), _fieldLayout); } /** Set system (using the specified store) */ - function setSystem(IStore _store, bytes32 resourceSelector, address system) internal { + function setSystem(IStore _store, bytes32 systemId, address system) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((system)), _fieldLayout); } /** Get publicAccess */ - function getPublicAccess(bytes32 resourceSelector) internal view returns (bool publicAccess) { + function getPublicAccess(bytes32 systemId) internal view returns (bool publicAccess) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); return (_toBool(uint8(bytes1(_blob)))); } /** Get publicAccess */ - function _getPublicAccess(bytes32 resourceSelector) internal view returns (bool publicAccess) { + function _getPublicAccess(bytes32 systemId) internal view returns (bool publicAccess) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); return (_toBool(uint8(bytes1(_blob)))); } /** Get publicAccess (using the specified store) */ - function getPublicAccess(IStore _store, bytes32 resourceSelector) internal view returns (bool publicAccess) { + function getPublicAccess(IStore _store, bytes32 systemId) internal view returns (bool publicAccess) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); return (_toBool(uint8(bytes1(_blob)))); } /** Set publicAccess */ - function setPublicAccess(bytes32 resourceSelector, bool publicAccess) internal { + function setPublicAccess(bytes32 systemId, bool publicAccess) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((publicAccess)), _fieldLayout); } /** Set publicAccess */ - function _setPublicAccess(bytes32 resourceSelector, bool publicAccess) internal { + function _setPublicAccess(bytes32 systemId, bool publicAccess) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.setField(_tableId, _keyTuple, 1, abi.encodePacked((publicAccess)), _fieldLayout); } /** Set publicAccess (using the specified store) */ - function setPublicAccess(IStore _store, bytes32 resourceSelector, bool publicAccess) internal { + function setPublicAccess(IStore _store, bytes32 systemId, bool publicAccess) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((publicAccess)), _fieldLayout); } /** Get the full data */ - function get(bytes32 resourceSelector) internal view returns (address system, bool publicAccess) { + function get(bytes32 systemId) internal view returns (address system, bool publicAccess) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( _tableId, @@ -192,9 +196,9 @@ library Systems { } /** Get the full data */ - function _get(bytes32 resourceSelector) internal view returns (address system, bool publicAccess) { + function _get(bytes32 systemId) internal view returns (address system, bool publicAccess) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( _tableId, @@ -205,9 +209,9 @@ library Systems { } /** Get the full data (using the specified store) */ - function get(IStore _store, bytes32 resourceSelector) internal view returns (address system, bool publicAccess) { + function get(IStore _store, bytes32 systemId) internal view returns (address system, bool publicAccess) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = _store.getRecord( _tableId, @@ -218,40 +222,40 @@ library Systems { } /** Set the full data using individual values */ - function set(bytes32 resourceSelector, address system, bool publicAccess) internal { + function set(bytes32 systemId, address system, bool publicAccess) internal { bytes memory _staticData = encodeStatic(system, publicAccess); PackedCounter _encodedLengths; bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values */ - function _set(bytes32 resourceSelector, address system, bool publicAccess) internal { + function _set(bytes32 systemId, address system, bool publicAccess) internal { bytes memory _staticData = encodeStatic(system, publicAccess); PackedCounter _encodedLengths; bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ - function set(IStore _store, bytes32 resourceSelector, address system, bool publicAccess) internal { + function set(IStore _store, bytes32 systemId, address system, bool publicAccess) internal { bytes memory _staticData = encodeStatic(system, publicAccess); PackedCounter _encodedLengths; bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } @@ -294,33 +298,33 @@ library Systems { } /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(bytes32 resourceSelector) internal pure returns (bytes32[] memory) { + function encodeKeyTuple(bytes32 systemId) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; return _keyTuple; } /* Delete all data for given keys */ - function deleteRecord(bytes32 resourceSelector) internal { + function deleteRecord(bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys */ - function _deleteRecord(bytes32 resourceSelector) internal { + function _deleteRecord(bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 resourceSelector) internal { + function deleteRecord(IStore _store, bytes32 systemId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = systemId; _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } diff --git a/packages/world/src/modules/keysintable/KeysInTableHook.sol b/packages/world/src/modules/keysintable/KeysInTableHook.sol index 69113cc5a8..0d8681456d 100644 --- a/packages/world/src/modules/keysintable/KeysInTableHook.sol +++ b/packages/world/src/modules/keysintable/KeysInTableHook.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.0; import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; import { StoreHook } from "@latticexyz/store/src/StoreHook.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; import { KeysInTable } from "./tables/KeysInTable.sol"; import { UsedKeysIndex } from "./tables/UsedKeysIndex.sol"; @@ -12,24 +13,24 @@ import { UsedKeysIndex } from "./tables/UsedKeysIndex.sol"; * Note: if a table with composite keys is used, only the first five keys of the tuple are indexed */ contract KeysInTableHook is StoreHook { - function handleSet(bytes32 tableId, bytes32[] memory keyTuple) internal { + function handleSet(ResourceId tableId, bytes32[] memory keyTuple) internal { bytes32 keysHash = keccak256(abi.encode(keyTuple)); // If the keyTuple has not yet been set in the table... - if (!UsedKeysIndex.getHas(tableId, keysHash)) { - uint40 length = uint40(KeysInTable.lengthKeys0(tableId)); + if (!UsedKeysIndex.getHas(ResourceId.unwrap(tableId), keysHash)) { + uint40 length = uint40(KeysInTable.lengthKeys0(ResourceId.unwrap(tableId))); // Push the keyTuple to the list of keys in this table if (keyTuple.length > 0) { - KeysInTable.pushKeys0(tableId, keyTuple[0]); + KeysInTable.pushKeys0(ResourceId.unwrap(tableId), keyTuple[0]); if (keyTuple.length > 1) { - KeysInTable.pushKeys1(tableId, keyTuple[1]); + KeysInTable.pushKeys1(ResourceId.unwrap(tableId), keyTuple[1]); if (keyTuple.length > 2) { - KeysInTable.pushKeys2(tableId, keyTuple[2]); + KeysInTable.pushKeys2(ResourceId.unwrap(tableId), keyTuple[2]); if (keyTuple.length > 3) { - KeysInTable.pushKeys3(tableId, keyTuple[3]); + KeysInTable.pushKeys3(ResourceId.unwrap(tableId), keyTuple[3]); if (keyTuple.length > 4) { - KeysInTable.pushKeys4(tableId, keyTuple[4]); + KeysInTable.pushKeys4(ResourceId.unwrap(tableId), keyTuple[4]); } } } @@ -37,12 +38,12 @@ contract KeysInTableHook is StoreHook { } // Update the index to avoid duplicating this keyTuple in the array - UsedKeysIndex.set(tableId, keysHash, true, length); + UsedKeysIndex.set(ResourceId.unwrap(tableId), keysHash, true, length); } } function onBeforeSetRecord( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, bytes memory, PackedCounter, @@ -53,7 +54,7 @@ contract KeysInTableHook is StoreHook { } function onAfterSpliceStaticData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint48, uint40, @@ -63,7 +64,7 @@ contract KeysInTableHook is StoreHook { } function onAfterSpliceDynamicData( - bytes32 tableId, + ResourceId tableId, bytes32[] memory keyTuple, uint8, uint40, @@ -74,58 +75,58 @@ contract KeysInTableHook is StoreHook { handleSet(tableId, keyTuple); } - function onBeforeDeleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout) public override { + function onBeforeDeleteRecord(ResourceId tableId, bytes32[] memory keyTuple, FieldLayout) public override { bytes32 keysHash = keccak256(abi.encode(keyTuple)); - (bool has, uint40 index) = UsedKeysIndex.get(tableId, keysHash); + (bool has, uint40 index) = UsedKeysIndex.get(ResourceId.unwrap(tableId), keysHash); // If the keyTuple was part of the table... if (has) { // Delete the index as the keyTuple is not in the table anymore - UsedKeysIndex.deleteRecord(tableId, keysHash); + UsedKeysIndex.deleteRecord(ResourceId.unwrap(tableId), keysHash); - uint40 length = uint40(KeysInTable.lengthKeys0(tableId)); + uint40 length = uint40(KeysInTable.lengthKeys0(ResourceId.unwrap(tableId))); if (length == 1) { // Delete the list of keys in this table - KeysInTable.deleteRecord(tableId); + KeysInTable.deleteRecord(ResourceId.unwrap(tableId)); } else { if (keyTuple.length > 0) { bytes32[] memory lastKeyTuple = new bytes32[](keyTuple.length); - bytes32 lastKey = KeysInTable.getItemKeys0(tableId, length - 1); + bytes32 lastKey = KeysInTable.getItemKeys0(ResourceId.unwrap(tableId), length - 1); lastKeyTuple[0] = lastKey; // Remove the keyTuple from the list of keys in this table - KeysInTable.updateKeys0(tableId, index, lastKey); - KeysInTable.popKeys0(tableId); + KeysInTable.updateKeys0(ResourceId.unwrap(tableId), index, lastKey); + KeysInTable.popKeys0(ResourceId.unwrap(tableId)); if (keyTuple.length > 1) { - lastKey = KeysInTable.getItemKeys1(tableId, length - 1); + lastKey = KeysInTable.getItemKeys1(ResourceId.unwrap(tableId), length - 1); lastKeyTuple[1] = lastKey; - KeysInTable.updateKeys1(tableId, index, lastKey); - KeysInTable.popKeys1(tableId); + KeysInTable.updateKeys1(ResourceId.unwrap(tableId), index, lastKey); + KeysInTable.popKeys1(ResourceId.unwrap(tableId)); if (keyTuple.length > 2) { - lastKey = KeysInTable.getItemKeys2(tableId, length - 1); + lastKey = KeysInTable.getItemKeys2(ResourceId.unwrap(tableId), length - 1); lastKeyTuple[2] = lastKey; - KeysInTable.updateKeys2(tableId, index, lastKey); - KeysInTable.popKeys2(tableId); + KeysInTable.updateKeys2(ResourceId.unwrap(tableId), index, lastKey); + KeysInTable.popKeys2(ResourceId.unwrap(tableId)); if (keyTuple.length > 3) { - lastKey = KeysInTable.getItemKeys3(tableId, length - 1); + lastKey = KeysInTable.getItemKeys3(ResourceId.unwrap(tableId), length - 1); lastKeyTuple[3] = lastKey; - KeysInTable.updateKeys3(tableId, index, lastKey); - KeysInTable.popKeys3(tableId); + KeysInTable.updateKeys3(ResourceId.unwrap(tableId), index, lastKey); + KeysInTable.popKeys3(ResourceId.unwrap(tableId)); if (keyTuple.length > 4) { - lastKey = KeysInTable.getItemKeys4(tableId, length - 1); + lastKey = KeysInTable.getItemKeys4(ResourceId.unwrap(tableId), length - 1); lastKeyTuple[4] = lastKey; - KeysInTable.updateKeys4(tableId, index, lastKey); - KeysInTable.popKeys4(tableId); + KeysInTable.updateKeys4(ResourceId.unwrap(tableId), index, lastKey); + KeysInTable.popKeys4(ResourceId.unwrap(tableId)); } } } @@ -133,7 +134,7 @@ contract KeysInTableHook is StoreHook { // Update the index of lastKeyTuple after swapping it with the deleted keyTuple bytes32 lastKeyHash = keccak256(abi.encode(lastKeyTuple)); - UsedKeysIndex.setIndex(tableId, lastKeyHash, index); + UsedKeysIndex.setIndex(ResourceId.unwrap(tableId), lastKeyHash, index); } } } diff --git a/packages/world/src/modules/keysintable/KeysInTableModule.sol b/packages/world/src/modules/keysintable/KeysInTableModule.sol index cd6d0b9f7d..b0357b7dd0 100644 --- a/packages/world/src/modules/keysintable/KeysInTableModule.sol +++ b/packages/world/src/modules/keysintable/KeysInTableModule.sol @@ -2,14 +2,13 @@ pragma solidity >=0.8.0; import { BEFORE_SET_RECORD, AFTER_SPLICE_STATIC_DATA, AFTER_SPLICE_DYNAMIC_DATA, BEFORE_DELETE_RECORD } from "@latticexyz/store/src/storeHookTypes.sol"; +import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol"; -import { ResourceType } from "../core/tables/ResourceType.sol"; -import { Resource } from "../../common.sol"; import { Module } from "../../Module.sol"; import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; -import { ResourceSelector } from "../../ResourceSelector.sol"; +import { ResourceId, WorldResourceIdInstance } from "../../WorldResourceId.sol"; import { revertWithBytes } from "../../revertWithBytes.sol"; import { KeysInTableHook } from "./KeysInTableHook.sol"; @@ -27,7 +26,7 @@ import { UsedKeysIndex, UsedKeysIndexTableId } from "./tables/UsedKeysIndex.sol" * TODO: add support for `install` (via `World.installModule`) by using `callFrom` with the `msgSender()` */ contract KeysInTableModule is Module { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; // The KeysInTableHook is deployed once and infers the target table id // from the source table id (passed as argument to the hook methods) @@ -39,7 +38,7 @@ contract KeysInTableModule is Module { function installRoot(bytes memory args) public override { // Extract source table id from args - bytes32 sourceTableId = abi.decode(args, (bytes32)); + ResourceId sourceTableId = ResourceId.wrap(abi.decode(args, (bytes32))); IBaseWorld world = IBaseWorld(_world()); @@ -47,7 +46,7 @@ contract KeysInTableModule is Module { bool success; bytes memory returnData; - if (ResourceType.get(KeysInTableTableId) == Resource.NONE) { + if (!ResourceIds._getExists(ResourceId.unwrap(KeysInTableTableId))) { // Register the tables (success, returnData) = address(world).delegatecall( abi.encodeCall( diff --git a/packages/world/src/modules/keysintable/getKeysInTable.sol b/packages/world/src/modules/keysintable/getKeysInTable.sol index c6b709f5fc..06d7bcf41b 100644 --- a/packages/world/src/modules/keysintable/getKeysInTable.sol +++ b/packages/world/src/modules/keysintable/getKeysInTable.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.0; import { IStore } from "@latticexyz/store/src/IStore.sol"; import { Schema } from "@latticexyz/store/src/Schema.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; import { KeysInTable } from "./tables/KeysInTable.sol"; @@ -13,29 +14,29 @@ import { KeysInTable } from "./tables/KeysInTable.sol"; * Note: this util can only be called within the context of a Store (e.g. from a System or Module). * For usage outside of a Store, use the overload that takes an explicit store argument. */ -function getKeysInTable(bytes32 tableId) view returns (bytes32[][] memory keyTuples) { +function getKeysInTable(ResourceId tableId) view returns (bytes32[][] memory keyTuples) { /** * Note: this module only supports up to 5 composite keys. */ Schema keySchema = StoreSwitch.getKeySchema(tableId); uint256 numFields = keySchema.numFields(); - uint256 length = KeysInTable.lengthKeys0(tableId); + uint256 length = KeysInTable.lengthKeys0(ResourceId.unwrap(tableId)); keyTuples = new bytes32[][](length); for (uint256 i; i < length; i++) { keyTuples[i] = new bytes32[](numFields); // the length of the key tuple depends on the key schema if (numFields > 0) { - keyTuples[i][0] = KeysInTable.getItemKeys0(tableId, i); + keyTuples[i][0] = KeysInTable.getItemKeys0(ResourceId.unwrap(tableId), i); if (numFields > 1) { - keyTuples[i][1] = KeysInTable.getItemKeys1(tableId, i); + keyTuples[i][1] = KeysInTable.getItemKeys1(ResourceId.unwrap(tableId), i); if (numFields > 2) { - keyTuples[i][2] = KeysInTable.getItemKeys2(tableId, i); + keyTuples[i][2] = KeysInTable.getItemKeys2(ResourceId.unwrap(tableId), i); if (numFields > 3) { - keyTuples[i][3] = KeysInTable.getItemKeys3(tableId, i); + keyTuples[i][3] = KeysInTable.getItemKeys3(ResourceId.unwrap(tableId), i); if (numFields > 4) { - keyTuples[i][4] = KeysInTable.getItemKeys4(tableId, i); + keyTuples[i][4] = KeysInTable.getItemKeys4(ResourceId.unwrap(tableId), i); } } } @@ -47,7 +48,7 @@ function getKeysInTable(bytes32 tableId) view returns (bytes32[][] memory keyTup /** * Get a list of keys in the given table for the given store. */ -function getKeysInTable(IStore store, bytes32 tableId) view returns (bytes32[][] memory keyTuples) { +function getKeysInTable(IStore store, ResourceId tableId) view returns (bytes32[][] memory keyTuples) { /** * Note: this module only supports up to 5 composite keys. */ @@ -55,22 +56,22 @@ function getKeysInTable(IStore store, bytes32 tableId) view returns (bytes32[][] Schema keySchema = store.getKeySchema(tableId); uint256 numFields = keySchema.numFields(); - uint256 length = KeysInTable.lengthKeys0(store, tableId); + uint256 length = KeysInTable.lengthKeys0(store, ResourceId.unwrap(tableId)); keyTuples = new bytes32[][](length); for (uint256 i; i < length; i++) { keyTuples[i] = new bytes32[](numFields); // the length of the key tuple depends on the key schema if (numFields > 0) { - keyTuples[i][0] = KeysInTable.getItemKeys0(store, tableId, i); + keyTuples[i][0] = KeysInTable.getItemKeys0(store, ResourceId.unwrap(tableId), i); if (numFields > 1) { - keyTuples[i][1] = KeysInTable.getItemKeys1(store, tableId, i); + keyTuples[i][1] = KeysInTable.getItemKeys1(store, ResourceId.unwrap(tableId), i); if (numFields > 2) { - keyTuples[i][2] = KeysInTable.getItemKeys2(store, tableId, i); + keyTuples[i][2] = KeysInTable.getItemKeys2(store, ResourceId.unwrap(tableId), i); if (numFields > 3) { - keyTuples[i][3] = KeysInTable.getItemKeys3(store, tableId, i); + keyTuples[i][3] = KeysInTable.getItemKeys3(store, ResourceId.unwrap(tableId), i); if (numFields > 4) { - keyTuples[i][4] = KeysInTable.getItemKeys4(store, tableId, i); + keyTuples[i][4] = KeysInTable.getItemKeys4(store, ResourceId.unwrap(tableId), i); } } } diff --git a/packages/world/src/modules/keysintable/hasKey.sol b/packages/world/src/modules/keysintable/hasKey.sol index 637439047e..0efd658135 100644 --- a/packages/world/src/modules/keysintable/hasKey.sol +++ b/packages/world/src/modules/keysintable/hasKey.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0; import { IStore } from "@latticexyz/store/src/IStore.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; import { UsedKeysIndex } from "./tables/UsedKeysIndex.sol"; @@ -11,17 +12,17 @@ import { UsedKeysIndex } from "./tables/UsedKeysIndex.sol"; * Note: this util can only be called within the context of a Store (e.g. from a System or Module). * For usage outside of a Store, use the overload that takes an explicit store argument. */ -function hasKey(bytes32 tableId, bytes32[] memory keyTuple) view returns (bool) { +function hasKey(ResourceId tableId, bytes32[] memory keyTuple) view returns (bool) { bytes32 keysHash = keccak256(abi.encode(keyTuple)); - return UsedKeysIndex.getHas(tableId, keysHash); + return UsedKeysIndex.getHas(ResourceId.unwrap(tableId), keysHash); } /** * Get whether the keyTuple is in the given table for the given store. */ -function hasKey(IStore store, bytes32 tableId, bytes32[] memory keyTuple) view returns (bool) { +function hasKey(IStore store, ResourceId tableId, bytes32[] memory keyTuple) view returns (bool) { bytes32 keysHash = keccak256(abi.encode(keyTuple)); - return UsedKeysIndex.getHas(store, tableId, keysHash); + return UsedKeysIndex.getHas(store, ResourceId.unwrap(tableId), keysHash); } diff --git a/packages/world/src/modules/keysintable/query.sol b/packages/world/src/modules/keysintable/query.sol index 53769a113e..3dbd72bc50 100644 --- a/packages/world/src/modules/keysintable/query.sol +++ b/packages/world/src/modules/keysintable/query.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.0; import { IStore } from "@latticexyz/store/src/IStore.sol"; import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; import { getKeysInTable } from "./getKeysInTable.sol"; import { getKeysWithValue } from "../keyswithvalue/getKeysWithValue.sol"; @@ -17,7 +18,7 @@ enum QueryType { struct QueryFragment { QueryType queryType; - bytes32 tableId; + ResourceId tableId; bytes value; } diff --git a/packages/world/src/modules/keysintable/tables/KeysInTable.sol b/packages/world/src/modules/keysintable/tables/KeysInTable.sol index 7de0288cc7..b51ca0c922 100644 --- a/packages/world/src/modules/keysintable/tables/KeysInTable.sol +++ b/packages/world/src/modules/keysintable/tables/KeysInTable.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("KeysInTable"))); -bytes32 constant KeysInTableTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("KeysInTable"))) +); +ResourceId constant KeysInTableTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000500000000000000000000000000000000000000000000000000000000 diff --git a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol index f674c7aadc..d4c75eddb8 100644 --- a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol +++ b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("UsedKeysIndex"))); -bytes32 constant UsedKeysIndexTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("UsedKeysIndex"))) +); +ResourceId constant UsedKeysIndexTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0006020001050000000000000000000000000000000000000000000000000000 diff --git a/packages/world/src/modules/keyswithvalue/KeysWithValueHook.sol b/packages/world/src/modules/keyswithvalue/KeysWithValueHook.sol index d666a3f4fa..b945b7ec3d 100644 --- a/packages/world/src/modules/keyswithvalue/KeysWithValueHook.sol +++ b/packages/world/src/modules/keyswithvalue/KeysWithValueHook.sol @@ -9,12 +9,12 @@ import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { Tables } from "@latticexyz/store/src/codegen/tables/Tables.sol"; import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; -import { ResourceSelector } from "../../ResourceSelector.sol"; +import { ResourceId, WorldResourceIdInstance } from "../../WorldResourceId.sol"; import { MODULE_NAMESPACE } from "./constants.sol"; import { KeysWithValue } from "./tables/KeysWithValue.sol"; import { ArrayLib } from "../utils/ArrayLib.sol"; -import { getTargetTableSelector } from "../utils/getTargetTableSelector.sol"; +import { getTargetTableId } from "./getTargetTableId.sol"; /** * This is a very naive and inefficient implementation for now. @@ -25,21 +25,21 @@ import { getTargetTableSelector } from "../utils/getTargetTableSelector.sol"; */ contract KeysWithValueHook is StoreHook { using ArrayLib for bytes32[]; - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; function _world() internal view returns (IBaseWorld) { return IBaseWorld(StoreSwitch.getStoreAddress()); } function onBeforeSetRecord( - bytes32 sourceTableId, + ResourceId sourceTableId, bytes32[] memory keyTuple, bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData, FieldLayout fieldLayout ) public override { - bytes32 targetTableId = getTargetTableSelector(MODULE_NAMESPACE, sourceTableId); + ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId); // Get the previous value bytes32 previousValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout); @@ -58,35 +58,35 @@ contract KeysWithValueHook is StoreHook { } function onBeforeSpliceStaticData( - bytes32 sourceTableId, + ResourceId sourceTableId, bytes32[] memory keyTuple, uint48, uint40, bytes memory ) public override { // Remove the key from the list of keys with the previous value - FieldLayout fieldLayout = FieldLayout.wrap(Tables.getFieldLayout(sourceTableId)); + FieldLayout fieldLayout = FieldLayout.wrap(Tables.getFieldLayout(ResourceId.unwrap(sourceTableId))); bytes32 previousValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout); - bytes32 targetTableId = getTargetTableSelector(MODULE_NAMESPACE, sourceTableId); + ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId); _removeKeyFromList(targetTableId, keyTuple[0], previousValue); } function onAfterSpliceStaticData( - bytes32 sourceTableId, + ResourceId sourceTableId, bytes32[] memory keyTuple, uint48, uint40, bytes memory ) public override { // Add the key to the list of keys with the new value - FieldLayout fieldLayout = FieldLayout.wrap(Tables.getFieldLayout(sourceTableId)); + FieldLayout fieldLayout = FieldLayout.wrap(Tables.getFieldLayout(ResourceId.unwrap(sourceTableId))); bytes32 newValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout); - bytes32 targetTableId = getTargetTableSelector(MODULE_NAMESPACE, sourceTableId); + ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId); KeysWithValue.push(targetTableId, newValue, keyTuple[0]); } function onBeforeSpliceDynamicData( - bytes32 sourceTableId, + ResourceId sourceTableId, bytes32[] memory keyTuple, uint8, uint40, @@ -95,14 +95,14 @@ contract KeysWithValueHook is StoreHook { PackedCounter ) public override { // Remove the key from the list of keys with the previous value - FieldLayout fieldLayout = FieldLayout.wrap(Tables.getFieldLayout(sourceTableId)); + FieldLayout fieldLayout = FieldLayout.wrap(Tables.getFieldLayout(ResourceId.unwrap(sourceTableId))); bytes32 previousValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout); - bytes32 targetTableId = getTargetTableSelector(MODULE_NAMESPACE, sourceTableId); + ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId); _removeKeyFromList(targetTableId, keyTuple[0], previousValue); } function onAfterSpliceDynamicData( - bytes32 sourceTableId, + ResourceId sourceTableId, bytes32[] memory keyTuple, uint8, uint40, @@ -111,25 +111,25 @@ contract KeysWithValueHook is StoreHook { PackedCounter ) public override { // Add the key to the list of keys with the new value - FieldLayout fieldLayout = FieldLayout.wrap(Tables.getFieldLayout(sourceTableId)); + FieldLayout fieldLayout = FieldLayout.wrap(Tables.getFieldLayout(ResourceId.unwrap(sourceTableId))); bytes32 newValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout); - bytes32 targetTableId = getTargetTableSelector(MODULE_NAMESPACE, sourceTableId); + ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId); KeysWithValue.push(targetTableId, newValue, keyTuple[0]); } function onBeforeDeleteRecord( - bytes32 sourceTableId, + ResourceId sourceTableId, bytes32[] memory keyTuple, FieldLayout fieldLayout ) public override { // Remove the key from the list of keys with the previous value bytes32 previousValue = _getRecordValueHash(sourceTableId, keyTuple, fieldLayout); - bytes32 targetTableId = getTargetTableSelector(MODULE_NAMESPACE, sourceTableId); + ResourceId targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId); _removeKeyFromList(targetTableId, keyTuple[0], previousValue); } function _getRecordValueHash( - bytes32 sourceTableId, + ResourceId sourceTableId, bytes32[] memory keyTuple, FieldLayout fieldLayout ) internal view returns (bytes32 valueHash) { @@ -145,7 +145,7 @@ contract KeysWithValueHook is StoreHook { } } - function _removeKeyFromList(bytes32 targetTableId, bytes32 key, bytes32 valueHash) internal { + function _removeKeyFromList(ResourceId targetTableId, bytes32 key, bytes32 valueHash) internal { // Get the keys with the previous value excluding the current key bytes32[] memory keysWithPreviousValue = KeysWithValue.get(targetTableId, valueHash).filter(key); diff --git a/packages/world/src/modules/keyswithvalue/KeysWithValueModule.sol b/packages/world/src/modules/keyswithvalue/KeysWithValueModule.sol index 65774a0093..d6b210666f 100644 --- a/packages/world/src/modules/keyswithvalue/KeysWithValueModule.sol +++ b/packages/world/src/modules/keyswithvalue/KeysWithValueModule.sol @@ -8,13 +8,13 @@ import { Module } from "../../Module.sol"; import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; import { WorldContextConsumer } from "../../WorldContext.sol"; -import { ResourceSelector } from "../../ResourceSelector.sol"; +import { ResourceId, WorldResourceIdInstance } from "../../WorldResourceId.sol"; import { revertWithBytes } from "../../revertWithBytes.sol"; import { MODULE_NAMESPACE } from "./constants.sol"; import { KeysWithValueHook } from "./KeysWithValueHook.sol"; import { KeysWithValue } from "./tables/KeysWithValue.sol"; -import { getTargetTableSelector } from "../utils/getTargetTableSelector.sol"; +import { getTargetTableId } from "./getTargetTableId.sol"; /** * This module deploys a hook that is called when a value is set in the `sourceTableId` @@ -28,7 +28,7 @@ import { getTargetTableSelector } from "../utils/getTargetTableSelector.sol"; * TODO: add support for `install` (via `World.installModule`) by using `callFrom` with the `msgSender()` */ contract KeysWithValueModule is Module { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; // The KeysWithValueHook is deployed once and infers the target table id // from the source table id (passed as argument to the hook methods) @@ -40,8 +40,8 @@ contract KeysWithValueModule is Module { function installRoot(bytes memory args) public { // Extract source table id from args - bytes32 sourceTableId = abi.decode(args, (bytes32)); - bytes32 targetTableSelector = getTargetTableSelector(MODULE_NAMESPACE, sourceTableId); + ResourceId sourceTableId = ResourceId.wrap(abi.decode(args, (bytes32))); + ResourceId targetTableSelector = getTargetTableId(MODULE_NAMESPACE, sourceTableId); IBaseWorld world = IBaseWorld(_world()); diff --git a/packages/world/src/modules/keyswithvalue/constants.sol b/packages/world/src/modules/keyswithvalue/constants.sol index 17528e1ec8..b239bade58 100644 --- a/packages/world/src/modules/keyswithvalue/constants.sol +++ b/packages/world/src/modules/keyswithvalue/constants.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -// Limiting the module namespace to 8 bytes so the last 8 bytes +// Limiting the module namespace to 7 bytes so the remaining 7 bytes // can be used for an identifier of the source table namespace to avoid // collisions between tables with the same name in different namespaces -bytes8 constant MODULE_NAMESPACE = "keyswval"; +bytes7 constant MODULE_NAMESPACE = "keywval"; diff --git a/packages/world/src/modules/keyswithvalue/getKeysWithValue.sol b/packages/world/src/modules/keyswithvalue/getKeysWithValue.sol index e47fba0d10..07cebf75cd 100644 --- a/packages/world/src/modules/keyswithvalue/getKeysWithValue.sol +++ b/packages/world/src/modules/keyswithvalue/getKeysWithValue.sol @@ -3,10 +3,11 @@ pragma solidity >=0.8.0; import { IStore } from "@latticexyz/store/src/IStore.sol"; import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; import { MODULE_NAMESPACE } from "./constants.sol"; import { KeysWithValue } from "./tables/KeysWithValue.sol"; -import { getTargetTableSelector } from "../utils/getTargetTableSelector.sol"; +import { getTargetTableId } from "./getTargetTableId.sol"; /** * Get a list of keys with the given value. @@ -15,13 +16,13 @@ import { getTargetTableSelector } from "../utils/getTargetTableSelector.sol"; * For usage outside of a Store, use the overload that takes an explicit store argument. */ function getKeysWithValue( - bytes32 tableId, + ResourceId tableId, bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData ) view returns (bytes32[] memory keysWithValue) { // Get the corresponding reverse mapping table - bytes32 keysWithValueTableId = getTargetTableSelector(MODULE_NAMESPACE, tableId); + ResourceId keysWithValueTableId = getTargetTableId(MODULE_NAMESPACE, tableId); // Get the keys with the given value bytes memory value; @@ -38,13 +39,13 @@ function getKeysWithValue( */ function getKeysWithValue( IStore store, - bytes32 tableId, + ResourceId tableId, bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData ) view returns (bytes32[] memory keysWithValue) { // Get the corresponding reverse mapping table - bytes32 keysWithValueTableId = getTargetTableSelector(MODULE_NAMESPACE, tableId); + ResourceId keysWithValueTableId = getTargetTableId(MODULE_NAMESPACE, tableId); // Get the keys with the given value bytes memory value; diff --git a/packages/world/src/modules/keyswithvalue/getTargetTableId.sol b/packages/world/src/modules/keyswithvalue/getTargetTableId.sol new file mode 100644 index 0000000000..b972ff8208 --- /dev/null +++ b/packages/world/src/modules/keyswithvalue/getTargetTableId.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import { TYPE_BYTES } from "@latticexyz/store/src/ResourceId.sol"; +import { ResourceId, WorldResourceIdInstance, NAME_BYTES } 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; + +/** + * Get a deterministic selector for the reverse mapping table for the given source table. + * The selector is constructed as follows: + * - The first 2 bytes are the resource type + * - The next 7 bytes are the module namespace + * - The next 7 bytes are the first 7 bytes of the source table namespace + * -- This is to avoid collisions between tables with the same name in different namespaces + * (Note that collisions are still possible if the first 7 bytes of the namespace are the same, in which case installing the module fails) + * - The last 16 bytes are the source table name + */ +function getTargetTableId(bytes7 moduleNamespace, ResourceId sourceTableId) pure returns (ResourceId) { + bytes16 tableName = WorldResourceIdInstance.getName(sourceTableId); + bytes7 sourceTableNamespace = bytes7(WorldResourceIdInstance.getNamespace(sourceTableId)); + 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)) + ); +} diff --git a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol index 3024469cc6..24fce461aa 100644 --- a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol +++ b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol @@ -17,6 +17,8 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 @@ -57,23 +59,23 @@ library KeysWithValue { } /** Register the table with its config */ - function register(bytes32 _tableId) internal { + function register(ResourceId _tableId) internal { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config */ - function _register(bytes32 _tableId) internal { + function _register(ResourceId _tableId) internal { StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ - function register(IStore _store, bytes32 _tableId) internal { + function register(IStore _store, ResourceId _tableId) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get keysWithValue */ function getKeysWithValue( - bytes32 _tableId, + ResourceId _tableId, bytes32 valueHash ) internal view returns (bytes32[] memory keysWithValue) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -85,7 +87,7 @@ library KeysWithValue { /** Get keysWithValue */ function _getKeysWithValue( - bytes32 _tableId, + ResourceId _tableId, bytes32 valueHash ) internal view returns (bytes32[] memory keysWithValue) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -98,7 +100,7 @@ library KeysWithValue { /** Get keysWithValue (using the specified store) */ function getKeysWithValue( IStore _store, - bytes32 _tableId, + ResourceId _tableId, bytes32 valueHash ) internal view returns (bytes32[] memory keysWithValue) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -109,7 +111,7 @@ library KeysWithValue { } /** Get keysWithValue */ - function get(bytes32 _tableId, bytes32 valueHash) internal view returns (bytes32[] memory keysWithValue) { + function get(ResourceId _tableId, bytes32 valueHash) internal view returns (bytes32[] memory keysWithValue) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -118,7 +120,7 @@ library KeysWithValue { } /** Get keysWithValue */ - function _get(bytes32 _tableId, bytes32 valueHash) internal view returns (bytes32[] memory keysWithValue) { + function _get(ResourceId _tableId, bytes32 valueHash) internal view returns (bytes32[] memory keysWithValue) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -129,7 +131,7 @@ library KeysWithValue { /** Get keysWithValue (using the specified store) */ function get( IStore _store, - bytes32 _tableId, + ResourceId _tableId, bytes32 valueHash ) internal view returns (bytes32[] memory keysWithValue) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -140,7 +142,7 @@ library KeysWithValue { } /** Set keysWithValue */ - function setKeysWithValue(bytes32 _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { + function setKeysWithValue(ResourceId _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -148,7 +150,7 @@ library KeysWithValue { } /** Set keysWithValue */ - function _setKeysWithValue(bytes32 _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { + function _setKeysWithValue(ResourceId _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -158,7 +160,7 @@ library KeysWithValue { /** Set keysWithValue (using the specified store) */ function setKeysWithValue( IStore _store, - bytes32 _tableId, + ResourceId _tableId, bytes32 valueHash, bytes32[] memory keysWithValue ) internal { @@ -169,7 +171,7 @@ library KeysWithValue { } /** Set keysWithValue */ - function set(bytes32 _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { + function set(ResourceId _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -177,7 +179,7 @@ library KeysWithValue { } /** Set keysWithValue */ - function _set(bytes32 _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { + function _set(ResourceId _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -185,7 +187,7 @@ library KeysWithValue { } /** Set keysWithValue (using the specified store) */ - function set(IStore _store, bytes32 _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { + function set(IStore _store, ResourceId _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -193,7 +195,7 @@ library KeysWithValue { } /** Get the length of keysWithValue */ - function lengthKeysWithValue(bytes32 _tableId, bytes32 valueHash) internal view returns (uint256) { + function lengthKeysWithValue(ResourceId _tableId, bytes32 valueHash) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -204,7 +206,7 @@ library KeysWithValue { } /** Get the length of keysWithValue */ - function _lengthKeysWithValue(bytes32 _tableId, bytes32 valueHash) internal view returns (uint256) { + function _lengthKeysWithValue(ResourceId _tableId, bytes32 valueHash) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -215,7 +217,7 @@ library KeysWithValue { } /** Get the length of keysWithValue (using the specified store) */ - function lengthKeysWithValue(IStore _store, bytes32 _tableId, bytes32 valueHash) internal view returns (uint256) { + function lengthKeysWithValue(IStore _store, ResourceId _tableId, bytes32 valueHash) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -226,7 +228,7 @@ library KeysWithValue { } /** Get the length of keysWithValue */ - function length(bytes32 _tableId, bytes32 valueHash) internal view returns (uint256) { + function length(ResourceId _tableId, bytes32 valueHash) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -237,7 +239,7 @@ library KeysWithValue { } /** Get the length of keysWithValue */ - function _length(bytes32 _tableId, bytes32 valueHash) internal view returns (uint256) { + function _length(ResourceId _tableId, bytes32 valueHash) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -248,7 +250,7 @@ library KeysWithValue { } /** Get the length of keysWithValue (using the specified store) */ - function length(IStore _store, bytes32 _tableId, bytes32 valueHash) internal view returns (uint256) { + function length(IStore _store, ResourceId _tableId, bytes32 valueHash) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -262,7 +264,11 @@ library KeysWithValue { * Get an item of keysWithValue * (unchecked, returns invalid data if index overflows) */ - function getItemKeysWithValue(bytes32 _tableId, bytes32 valueHash, uint256 _index) internal view returns (bytes32) { + function getItemKeysWithValue( + ResourceId _tableId, + bytes32 valueHash, + uint256 _index + ) internal view returns (bytes32) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -283,7 +289,11 @@ library KeysWithValue { * Get an item of keysWithValue * (unchecked, returns invalid data if index overflows) */ - function _getItemKeysWithValue(bytes32 _tableId, bytes32 valueHash, uint256 _index) internal view returns (bytes32) { + function _getItemKeysWithValue( + ResourceId _tableId, + bytes32 valueHash, + uint256 _index + ) internal view returns (bytes32) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -306,7 +316,7 @@ library KeysWithValue { */ function getItemKeysWithValue( IStore _store, - bytes32 _tableId, + ResourceId _tableId, bytes32 valueHash, uint256 _index ) internal view returns (bytes32) { @@ -323,7 +333,7 @@ library KeysWithValue { * Get an item of keysWithValue * (unchecked, returns invalid data if index overflows) */ - function getItem(bytes32 _tableId, bytes32 valueHash, uint256 _index) internal view returns (bytes32) { + function getItem(ResourceId _tableId, bytes32 valueHash, uint256 _index) internal view returns (bytes32) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -344,7 +354,7 @@ library KeysWithValue { * Get an item of keysWithValue * (unchecked, returns invalid data if index overflows) */ - function _getItem(bytes32 _tableId, bytes32 valueHash, uint256 _index) internal view returns (bytes32) { + function _getItem(ResourceId _tableId, bytes32 valueHash, uint256 _index) internal view returns (bytes32) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -365,7 +375,12 @@ library KeysWithValue { * Get an item of keysWithValue (using the specified store) * (unchecked, returns invalid data if index overflows) */ - function getItem(IStore _store, bytes32 _tableId, bytes32 valueHash, uint256 _index) internal view returns (bytes32) { + function getItem( + IStore _store, + ResourceId _tableId, + bytes32 valueHash, + uint256 _index + ) internal view returns (bytes32) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -376,7 +391,7 @@ library KeysWithValue { } /** Push an element to keysWithValue */ - function pushKeysWithValue(bytes32 _tableId, bytes32 valueHash, bytes32 _element) internal { + function pushKeysWithValue(ResourceId _tableId, bytes32 valueHash, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -384,7 +399,7 @@ library KeysWithValue { } /** Push an element to keysWithValue */ - function _pushKeysWithValue(bytes32 _tableId, bytes32 valueHash, bytes32 _element) internal { + function _pushKeysWithValue(ResourceId _tableId, bytes32 valueHash, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -392,7 +407,7 @@ library KeysWithValue { } /** Push an element to keysWithValue (using the specified store) */ - function pushKeysWithValue(IStore _store, bytes32 _tableId, bytes32 valueHash, bytes32 _element) internal { + function pushKeysWithValue(IStore _store, ResourceId _tableId, bytes32 valueHash, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -400,7 +415,7 @@ library KeysWithValue { } /** Push an element to keysWithValue */ - function push(bytes32 _tableId, bytes32 valueHash, bytes32 _element) internal { + function push(ResourceId _tableId, bytes32 valueHash, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -408,7 +423,7 @@ library KeysWithValue { } /** Push an element to keysWithValue */ - function _push(bytes32 _tableId, bytes32 valueHash, bytes32 _element) internal { + function _push(ResourceId _tableId, bytes32 valueHash, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -416,7 +431,7 @@ library KeysWithValue { } /** Push an element to keysWithValue (using the specified store) */ - function push(IStore _store, bytes32 _tableId, bytes32 valueHash, bytes32 _element) internal { + function push(IStore _store, ResourceId _tableId, bytes32 valueHash, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -424,7 +439,7 @@ library KeysWithValue { } /** Pop an element from keysWithValue */ - function popKeysWithValue(bytes32 _tableId, bytes32 valueHash) internal { + function popKeysWithValue(ResourceId _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -432,7 +447,7 @@ library KeysWithValue { } /** Pop an element from keysWithValue */ - function _popKeysWithValue(bytes32 _tableId, bytes32 valueHash) internal { + function _popKeysWithValue(ResourceId _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -440,7 +455,7 @@ library KeysWithValue { } /** Pop an element from keysWithValue (using the specified store) */ - function popKeysWithValue(IStore _store, bytes32 _tableId, bytes32 valueHash) internal { + function popKeysWithValue(IStore _store, ResourceId _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -448,7 +463,7 @@ library KeysWithValue { } /** Pop an element from keysWithValue */ - function pop(bytes32 _tableId, bytes32 valueHash) internal { + function pop(ResourceId _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -456,7 +471,7 @@ library KeysWithValue { } /** Pop an element from keysWithValue */ - function _pop(bytes32 _tableId, bytes32 valueHash) internal { + function _pop(ResourceId _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -464,7 +479,7 @@ library KeysWithValue { } /** Pop an element from keysWithValue (using the specified store) */ - function pop(IStore _store, bytes32 _tableId, bytes32 valueHash) internal { + function pop(IStore _store, ResourceId _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -475,7 +490,7 @@ library KeysWithValue { * Update an element of keysWithValue at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function updateKeysWithValue(bytes32 _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { + function updateKeysWithValue(ResourceId _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -488,7 +503,7 @@ library KeysWithValue { * Update an element of keysWithValue at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function _updateKeysWithValue(bytes32 _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { + function _updateKeysWithValue(ResourceId _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -503,7 +518,7 @@ library KeysWithValue { */ function updateKeysWithValue( IStore _store, - bytes32 _tableId, + ResourceId _tableId, bytes32 valueHash, uint256 _index, bytes32 _element @@ -520,7 +535,7 @@ library KeysWithValue { * Update an element of keysWithValue at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function update(bytes32 _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { + function update(ResourceId _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -533,7 +548,7 @@ library KeysWithValue { * Update an element of keysWithValue at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function _update(bytes32 _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { + function _update(ResourceId _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -546,7 +561,7 @@ library KeysWithValue { * Update an element of keysWithValue (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function update(IStore _store, bytes32 _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { + function update(IStore _store, ResourceId _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -586,7 +601,7 @@ library KeysWithValue { } /* Delete all data for given keys */ - function deleteRecord(bytes32 _tableId, bytes32 valueHash) internal { + function deleteRecord(ResourceId _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -594,7 +609,7 @@ library KeysWithValue { } /* Delete all data for given keys */ - function _deleteRecord(bytes32 _tableId, bytes32 valueHash) internal { + function _deleteRecord(ResourceId _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; @@ -602,7 +617,7 @@ library KeysWithValue { } /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 _tableId, bytes32 valueHash) internal { + function deleteRecord(IStore _store, ResourceId _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; diff --git a/packages/world/src/modules/std-delegations/CallboundDelegationControl.sol b/packages/world/src/modules/std-delegations/CallboundDelegationControl.sol index fbb62081ee..c089ec7d4b 100644 --- a/packages/world/src/modules/std-delegations/CallboundDelegationControl.sol +++ b/packages/world/src/modules/std-delegations/CallboundDelegationControl.sol @@ -2,20 +2,21 @@ pragma solidity >=0.8.0; import { DelegationControl } from "../../DelegationControl.sol"; +import { ResourceId } from "../../WorldResourceId.sol"; import { CallboundDelegations } from "./tables/CallboundDelegations.sol"; contract CallboundDelegationControl is DelegationControl { /** * Verify a delegation by checking if the delegator has any available calls left in the CallboundDelegations table and decrementing the available calls if so. */ - function verify(address delegator, bytes32 resourceSelector, bytes memory callData) public returns (bool) { + function verify(address delegator, ResourceId systemId, bytes memory callData) public returns (bool) { bytes32 callDataHash = keccak256(callData); - // Get the number of available calls for the given delegator, resourceSelector and callData + // Get the number of available calls for the given delegator, systemId and callData uint256 availableCalls = CallboundDelegations.get({ delegator: delegator, delegatee: _msgSender(), - resourceSelector: resourceSelector, + systemId: ResourceId.unwrap(systemId), callDataHash: callDataHash }); @@ -24,7 +25,7 @@ contract CallboundDelegationControl is DelegationControl { CallboundDelegations.deleteRecord({ delegator: delegator, delegatee: _msgSender(), - resourceSelector: resourceSelector, + systemId: ResourceId.unwrap(systemId), callDataHash: callDataHash }); return true; @@ -38,7 +39,7 @@ contract CallboundDelegationControl is DelegationControl { CallboundDelegations.set({ delegator: delegator, delegatee: _msgSender(), - resourceSelector: resourceSelector, + systemId: ResourceId.unwrap(systemId), callDataHash: callDataHash, availableCalls: availableCalls }); @@ -51,11 +52,11 @@ contract CallboundDelegationControl is DelegationControl { /** * Initialize a delegation by setting the number of available calls in the CallboundDelegations table */ - function initDelegation(address delegatee, bytes32 resourceSelector, bytes memory callData, uint256 numCalls) public { + function initDelegation(address delegatee, ResourceId systemId, bytes memory callData, uint256 numCalls) public { CallboundDelegations.set({ delegator: _msgSender(), delegatee: delegatee, - resourceSelector: resourceSelector, + systemId: ResourceId.unwrap(systemId), callDataHash: keccak256(callData), availableCalls: numCalls }); diff --git a/packages/world/src/modules/std-delegations/StandardDelegationsModule.sol b/packages/world/src/modules/std-delegations/StandardDelegationsModule.sol index d1ba02718d..99f341ef3a 100644 --- a/packages/world/src/modules/std-delegations/StandardDelegationsModule.sol +++ b/packages/world/src/modules/std-delegations/StandardDelegationsModule.sol @@ -5,7 +5,6 @@ import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; import { Module } from "../../Module.sol"; import { WorldContextConsumer } from "../../WorldContext.sol"; -import { ResourceSelector } from "../../ResourceSelector.sol"; import { revertWithBytes } from "../../revertWithBytes.sol"; import { CallboundDelegationControl } from "./CallboundDelegationControl.sol"; diff --git a/packages/world/src/modules/std-delegations/TimeboundDelegationControl.sol b/packages/world/src/modules/std-delegations/TimeboundDelegationControl.sol index efeb00663e..e9f9e6114d 100644 --- a/packages/world/src/modules/std-delegations/TimeboundDelegationControl.sol +++ b/packages/world/src/modules/std-delegations/TimeboundDelegationControl.sol @@ -2,14 +2,15 @@ pragma solidity >=0.8.0; import { DelegationControl } from "../../DelegationControl.sol"; +import { ResourceId } from "../../WorldResourceId.sol"; import { TimeboundDelegations } from "./tables/TimeboundDelegations.sol"; contract TimeboundDelegationControl is DelegationControl { /** * Verify a delegation by checking if the current block timestamp is not larger than the max valid timestamp for the delegation. - * Note: the delegation control check ignores the resourceSelector and callData parameters. + * Note: the delegation control check ignores the systemId and callData parameters. */ - function verify(address delegator, bytes32, bytes memory) public view returns (bool) { + function verify(address delegator, ResourceId, bytes memory) public view returns (bool) { // Get the max valid timestamp for the given delegator uint256 maxTimestamp = TimeboundDelegations.get({ delegator: delegator, delegatee: _msgSender() }); diff --git a/packages/world/src/modules/std-delegations/constants.sol b/packages/world/src/modules/std-delegations/constants.sol index dfe282a288..96e65ec00a 100644 --- a/packages/world/src/modules/std-delegations/constants.sol +++ b/packages/world/src/modules/std-delegations/constants.sol @@ -1,12 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import { ResourceSelector } from "../../ResourceSelector.sol"; +import { ResourceId } from "../../WorldResourceId.sol"; +import { RESOURCE_SYSTEM } from "../../worldResourceTypes.sol"; import { ROOT_NAMESPACE } from "../../constants.sol"; bytes16 constant MODULE_NAME = bytes16("stddelegations.m"); // Callbound delegation -bytes32 constant CALLBOUND_DELEGATION = bytes32(abi.encodePacked(ROOT_NAMESPACE, bytes16("callbound.d"))); +ResourceId constant CALLBOUND_DELEGATION = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_SYSTEM, ROOT_NAMESPACE, bytes16("callbound"))) +); // Timebound delegation -bytes32 constant TIMEBOUND_DELEGATION = bytes32(abi.encodePacked(ROOT_NAMESPACE, bytes16("timebound.d"))); +ResourceId constant TIMEBOUND_DELEGATION = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_SYSTEM, ROOT_NAMESPACE, bytes16("timebound"))) +); diff --git a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol index 679c67d270..93c6ef192d 100644 --- a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("CallboundDelegat"))); -bytes32 constant CallboundDelegationsTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("CallboundDelegat"))) +); +ResourceId constant CallboundDelegationsTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0020010020000000000000000000000000000000000000000000000000000000 @@ -55,7 +59,7 @@ library CallboundDelegations { keyNames = new string[](4); keyNames[0] = "delegator"; keyNames[1] = "delegatee"; - keyNames[2] = "resourceSelector"; + keyNames[2] = "systemId"; keyNames[3] = "callDataHash"; } @@ -84,13 +88,13 @@ library CallboundDelegations { function getAvailableCalls( address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash ) internal view returns (uint256 availableCalls) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -101,13 +105,13 @@ library CallboundDelegations { function _getAvailableCalls( address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash ) internal view returns (uint256 availableCalls) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -119,13 +123,13 @@ library CallboundDelegations { IStore _store, address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash ) internal view returns (uint256 availableCalls) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -136,13 +140,13 @@ library CallboundDelegations { function get( address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash ) internal view returns (uint256 availableCalls) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -153,13 +157,13 @@ library CallboundDelegations { function _get( address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash ) internal view returns (uint256 availableCalls) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -171,13 +175,13 @@ library CallboundDelegations { IStore _store, address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash ) internal view returns (uint256 availableCalls) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -188,14 +192,14 @@ library CallboundDelegations { function setAvailableCalls( address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash, uint256 availableCalls ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); @@ -205,14 +209,14 @@ library CallboundDelegations { function _setAvailableCalls( address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash, uint256 availableCalls ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); @@ -223,14 +227,14 @@ library CallboundDelegations { IStore _store, address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash, uint256 availableCalls ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); @@ -240,14 +244,14 @@ library CallboundDelegations { function set( address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash, uint256 availableCalls ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); @@ -257,14 +261,14 @@ library CallboundDelegations { function _set( address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash, uint256 availableCalls ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); @@ -275,14 +279,14 @@ library CallboundDelegations { IStore _store, address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash, uint256 availableCalls ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); @@ -307,40 +311,35 @@ library CallboundDelegations { function encodeKeyTuple( address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash ) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; return _keyTuple; } /* Delete all data for given keys */ - function deleteRecord(address delegator, address delegatee, bytes32 resourceSelector, bytes32 callDataHash) internal { + function deleteRecord(address delegator, address delegatee, bytes32 systemId, bytes32 callDataHash) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys */ - function _deleteRecord( - address delegator, - address delegatee, - bytes32 resourceSelector, - bytes32 callDataHash - ) internal { + function _deleteRecord(address delegator, address delegatee, bytes32 systemId, bytes32 callDataHash) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); @@ -351,13 +350,13 @@ library CallboundDelegations { IStore _store, address delegator, address delegatee, - bytes32 resourceSelector, + bytes32 systemId, bytes32 callDataHash ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _keyTuple[2] = resourceSelector; + _keyTuple[2] = systemId; _keyTuple[3] = callDataHash; _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); diff --git a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol index 34e0f8ae48..7505e6a7c6 100644 --- a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("TimeboundDelegat"))); -bytes32 constant TimeboundDelegationsTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("TimeboundDelegat"))) +); +ResourceId constant TimeboundDelegationsTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0020010020000000000000000000000000000000000000000000000000000000 diff --git a/packages/world/src/modules/uniqueentity/UniqueEntityModule.sol b/packages/world/src/modules/uniqueentity/UniqueEntityModule.sol index f404c4b50a..1f7cb32045 100644 --- a/packages/world/src/modules/uniqueentity/UniqueEntityModule.sol +++ b/packages/world/src/modules/uniqueentity/UniqueEntityModule.sol @@ -5,12 +5,11 @@ import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; import { Module } from "../../Module.sol"; import { WorldContextConsumer } from "../../WorldContext.sol"; -import { ResourceSelector } from "../../ResourceSelector.sol"; import { UniqueEntity } from "./tables/UniqueEntity.sol"; import { UniqueEntitySystem } from "./UniqueEntitySystem.sol"; -import { NAMESPACE, MODULE_NAME, SYSTEM_NAME, TABLE_NAME } from "./constants.sol"; +import { MODULE_NAME, TABLE_ID, SYSTEM_ID } from "./constants.sol"; /** * This module creates a table that stores a nonce, and @@ -33,12 +32,12 @@ contract UniqueEntityModule is Module { IBaseWorld world = IBaseWorld(_world()); // Register table - UniqueEntity.register(world, ResourceSelector.from(NAMESPACE, TABLE_NAME)); + UniqueEntity.register(world, TABLE_ID); // Register system - world.registerSystem(ResourceSelector.from(NAMESPACE, SYSTEM_NAME), uniqueEntitySystem, true); + world.registerSystem(SYSTEM_ID, uniqueEntitySystem, true); // Register system's functions - world.registerFunctionSelector(ResourceSelector.from(NAMESPACE, SYSTEM_NAME), "getUniqueEntity", "()"); + world.registerFunctionSelector(SYSTEM_ID, "getUniqueEntity", "()"); } } diff --git a/packages/world/src/modules/uniqueentity/UniqueEntitySystem.sol b/packages/world/src/modules/uniqueentity/UniqueEntitySystem.sol index 3ef850f25e..35da06f17d 100644 --- a/packages/world/src/modules/uniqueentity/UniqueEntitySystem.sol +++ b/packages/world/src/modules/uniqueentity/UniqueEntitySystem.sol @@ -2,20 +2,16 @@ pragma solidity >=0.8.0; import { System } from "../../System.sol"; - +import { TABLE_ID } from "./constants.sol"; import { UniqueEntity } from "./tables/UniqueEntity.sol"; -import { NAMESPACE, TABLE_NAME } from "./constants.sol"; -import { ResourceSelector } from "../../ResourceSelector.sol"; - contract UniqueEntitySystem is System { /** * Increment and get an entity nonce. */ function getUniqueEntity() public virtual returns (bytes32) { - bytes32 tableId = ResourceSelector.from(NAMESPACE, TABLE_NAME); - uint256 uniqueEntity = UniqueEntity.get(tableId) + 1; - UniqueEntity.set(tableId, uniqueEntity); + uint256 uniqueEntity = UniqueEntity.get(TABLE_ID) + 1; + UniqueEntity.set(TABLE_ID, uniqueEntity); return bytes32(uniqueEntity); } diff --git a/packages/world/src/modules/uniqueentity/constants.sol b/packages/world/src/modules/uniqueentity/constants.sol index 772f4742e2..d35a2d1b63 100644 --- a/packages/world/src/modules/uniqueentity/constants.sol +++ b/packages/world/src/modules/uniqueentity/constants.sol @@ -1,7 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -bytes16 constant NAMESPACE = bytes16("uniqueEntity"); -bytes16 constant MODULE_NAME = bytes16("uniqueEntity.m"); +import { ResourceId } from "../../WorldResourceId.sol"; +import { RESOURCE_TABLE, RESOURCE_SYSTEM } from "../../worldResourceTypes.sol"; + +bytes14 constant NAMESPACE = bytes14("uniqueEntity"); +bytes16 constant MODULE_NAME = bytes16("uniqueEntity"); bytes16 constant SYSTEM_NAME = bytes16("system"); bytes16 constant TABLE_NAME = bytes16("table"); + +ResourceId constant TABLE_ID = ResourceId.wrap(bytes32(abi.encodePacked(RESOURCE_TABLE, NAMESPACE, TABLE_NAME))); +ResourceId constant SYSTEM_ID = ResourceId.wrap((bytes32(abi.encodePacked(RESOURCE_SYSTEM, NAMESPACE, SYSTEM_NAME)))); diff --git a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol index 4c9032669d..2e2982e647 100644 --- a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol +++ b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol @@ -17,6 +17,8 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0020010020000000000000000000000000000000000000000000000000000000 @@ -55,22 +57,22 @@ library UniqueEntity { } /** Register the table with its config */ - function register(bytes32 _tableId) internal { + function register(ResourceId _tableId) internal { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config */ - function _register(bytes32 _tableId) internal { + function _register(ResourceId _tableId) internal { StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ - function register(IStore _store, bytes32 _tableId) internal { + function register(IStore _store, ResourceId _tableId) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ - function getValue(bytes32 _tableId) internal view returns (uint256 value) { + function getValue(ResourceId _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -78,7 +80,7 @@ library UniqueEntity { } /** Get value */ - function _getValue(bytes32 _tableId) internal view returns (uint256 value) { + function _getValue(ResourceId _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -86,7 +88,7 @@ library UniqueEntity { } /** Get value (using the specified store) */ - function getValue(IStore _store, bytes32 _tableId) internal view returns (uint256 value) { + function getValue(IStore _store, ResourceId _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -94,7 +96,7 @@ library UniqueEntity { } /** Get value */ - function get(bytes32 _tableId) internal view returns (uint256 value) { + function get(ResourceId _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -102,7 +104,7 @@ library UniqueEntity { } /** Get value */ - function _get(bytes32 _tableId) internal view returns (uint256 value) { + function _get(ResourceId _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -110,7 +112,7 @@ library UniqueEntity { } /** Get value (using the specified store) */ - function get(IStore _store, bytes32 _tableId) internal view returns (uint256 value) { + function get(IStore _store, ResourceId _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -118,42 +120,42 @@ library UniqueEntity { } /** Set value */ - function setValue(bytes32 _tableId, uint256 value) internal { + function setValue(ResourceId _tableId, uint256 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value */ - function _setValue(bytes32 _tableId, uint256 value) internal { + function _setValue(ResourceId _tableId, uint256 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ - function setValue(IStore _store, bytes32 _tableId, uint256 value) internal { + function setValue(IStore _store, ResourceId _tableId, uint256 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value */ - function set(bytes32 _tableId, uint256 value) internal { + function set(ResourceId _tableId, uint256 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value */ - function _set(bytes32 _tableId, uint256 value) internal { + function _set(ResourceId _tableId, uint256 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ - function set(IStore _store, bytes32 _tableId, uint256 value) internal { + function set(IStore _store, ResourceId _tableId, uint256 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); @@ -182,21 +184,21 @@ library UniqueEntity { } /* Delete all data for given keys */ - function deleteRecord(bytes32 _tableId) internal { + function deleteRecord(ResourceId _tableId) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys */ - function _deleteRecord(bytes32 _tableId) internal { + function _deleteRecord(ResourceId _tableId) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 _tableId) internal { + function deleteRecord(IStore _store, ResourceId _tableId) internal { bytes32[] memory _keyTuple = new bytes32[](0); _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); diff --git a/packages/world/src/modules/utils/getTargetTableSelector.sol b/packages/world/src/modules/utils/getTargetTableSelector.sol deleted file mode 100644 index 84ff1035f0..0000000000 --- a/packages/world/src/modules/utils/getTargetTableSelector.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; -import { ResourceSelector } from "../../ResourceSelector.sol"; - -/** - * Get a deterministic selector for the reverse mapping table for the given source table. - * The selector is constructed as follows: - * - The first 8 bytes are the module namespace - * - The next 8 bytes are the first 8 bytes of the source table namespace - * -- This is to avoid collisions between tables with the same name in different namespaces - * (Note that collisions are still possible if the first 8 bytes of the namespace are the same, in which case installing the module fails) - * - The last 16 bytes are the source table name - */ -function getTargetTableSelector(bytes8 moduleNamespace, bytes32 sourceTableId) pure returns (bytes32) { - bytes16 tableName = ResourceSelector.getName(sourceTableId); - bytes8 sourceTableNamespace = bytes8(bytes32(sourceTableId)); - return bytes32(moduleNamespace) | (bytes32(sourceTableNamespace) >> 64) | (bytes32(tableName) >> 128); -} diff --git a/packages/world/src/tables/Delegations.sol b/packages/world/src/tables/Delegations.sol index 91e5be6c27..f39cb50e68 100644 --- a/packages/world/src/tables/Delegations.sol +++ b/packages/world/src/tables/Delegations.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Delegations"))); -bytes32 constant DelegationsTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Delegations"))) +); +ResourceId constant DelegationsTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0020010020000000000000000000000000000000000000000000000000000000 diff --git a/packages/world/src/tables/InstalledModules.sol b/packages/world/src/tables/InstalledModules.sol index 7d87929aec..babc79ad42 100644 --- a/packages/world/src/tables/InstalledModules.sol +++ b/packages/world/src/tables/InstalledModules.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("InstalledModules"))); -bytes32 constant InstalledModulesTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("InstalledModules"))) +); +ResourceId constant InstalledModulesTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0014010014000000000000000000000000000000000000000000000000000000 diff --git a/packages/world/src/tables/NamespaceOwner.sol b/packages/world/src/tables/NamespaceOwner.sol index f16a4f1b0c..6b9c4c6a99 100644 --- a/packages/world/src/tables/NamespaceOwner.sol +++ b/packages/world/src/tables/NamespaceOwner.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("NamespaceOwner"))); -bytes32 constant NamespaceOwnerTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("NamespaceOwner"))) +); +ResourceId constant NamespaceOwnerTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0014010014000000000000000000000000000000000000000000000000000000 @@ -34,7 +38,7 @@ library NamespaceOwner { /** Get the table's key schema */ function getKeySchema() internal pure returns (Schema) { SchemaType[] memory _keySchema = new SchemaType[](1); - _keySchema[0] = SchemaType.BYTES16; + _keySchema[0] = SchemaType.BYTES32; return SchemaLib.encode(_keySchema); } @@ -50,7 +54,7 @@ library NamespaceOwner { /** Get the table's key names */ function getKeyNames() internal pure returns (string[] memory keyNames) { keyNames = new string[](1); - keyNames[0] = "namespace"; + keyNames[0] = "namespaceId"; } /** Get the table's field names */ @@ -75,103 +79,103 @@ library NamespaceOwner { } /** Get owner */ - function getOwner(bytes16 namespace) internal view returns (address owner) { + function getOwner(bytes32 namespaceId) internal view returns (address owner) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (address(bytes20(_blob))); } /** Get owner */ - function _getOwner(bytes16 namespace) internal view returns (address owner) { + function _getOwner(bytes32 namespaceId) internal view returns (address owner) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (address(bytes20(_blob))); } /** Get owner (using the specified store) */ - function getOwner(IStore _store, bytes16 namespace) internal view returns (address owner) { + function getOwner(IStore _store, bytes32 namespaceId) internal view returns (address owner) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (address(bytes20(_blob))); } /** Get owner */ - function get(bytes16 namespace) internal view returns (address owner) { + function get(bytes32 namespaceId) internal view returns (address owner) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (address(bytes20(_blob))); } /** Get owner */ - function _get(bytes16 namespace) internal view returns (address owner) { + function _get(bytes32 namespaceId) internal view returns (address owner) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (address(bytes20(_blob))); } /** Get owner (using the specified store) */ - function get(IStore _store, bytes16 namespace) internal view returns (address owner) { + function get(IStore _store, bytes32 namespaceId) internal view returns (address owner) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (address(bytes20(_blob))); } /** Set owner */ - function setOwner(bytes16 namespace, address owner) internal { + function setOwner(bytes32 namespaceId, address owner) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); } /** Set owner */ - function _setOwner(bytes16 namespace, address owner) internal { + function _setOwner(bytes32 namespaceId, address owner) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); } /** Set owner (using the specified store) */ - function setOwner(IStore _store, bytes16 namespace, address owner) internal { + function setOwner(IStore _store, bytes32 namespaceId, address owner) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); } /** Set owner */ - function set(bytes16 namespace, address owner) internal { + function set(bytes32 namespaceId, address owner) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); } /** Set owner */ - function _set(bytes16 namespace, address owner) internal { + function _set(bytes32 namespaceId, address owner) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); } /** Set owner (using the specified store) */ - function set(IStore _store, bytes16 namespace, address owner) internal { + function set(IStore _store, bytes32 namespaceId, address owner) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); } @@ -192,33 +196,33 @@ library NamespaceOwner { } /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(bytes16 namespace) internal pure returns (bytes32[] memory) { + function encodeKeyTuple(bytes32 namespaceId) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; return _keyTuple; } /* Delete all data for given keys */ - function deleteRecord(bytes16 namespace) internal { + function deleteRecord(bytes32 namespaceId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys */ - function _deleteRecord(bytes16 namespace) internal { + function _deleteRecord(bytes32 namespaceId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes16 namespace) internal { + function deleteRecord(IStore _store, bytes32 namespaceId) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(namespace); + _keyTuple[0] = namespaceId; _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } diff --git a/packages/world/src/tables/ResourceAccess.sol b/packages/world/src/tables/ResourceAccess.sol index 8745ef7353..28613dbe6a 100644 --- a/packages/world/src/tables/ResourceAccess.sol +++ b/packages/world/src/tables/ResourceAccess.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("ResourceAccess"))); -bytes32 constant ResourceAccessTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("ResourceAccess"))) +); +ResourceId constant ResourceAccessTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0001010001000000000000000000000000000000000000000000000000000000 @@ -51,7 +55,7 @@ library ResourceAccess { /** Get the table's key names */ function getKeyNames() internal pure returns (string[] memory keyNames) { keyNames = new string[](2); - keyNames[0] = "resourceSelector"; + keyNames[0] = "resourceId"; keyNames[1] = "caller"; } @@ -77,9 +81,9 @@ library ResourceAccess { } /** Get access */ - function getAccess(bytes32 resourceSelector, address caller) internal view returns (bool access) { + function getAccess(bytes32 resourceId, address caller) internal view returns (bool access) { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -87,9 +91,9 @@ library ResourceAccess { } /** Get access */ - function _getAccess(bytes32 resourceSelector, address caller) internal view returns (bool access) { + function _getAccess(bytes32 resourceId, address caller) internal view returns (bool access) { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -97,9 +101,9 @@ library ResourceAccess { } /** Get access (using the specified store) */ - function getAccess(IStore _store, bytes32 resourceSelector, address caller) internal view returns (bool access) { + function getAccess(IStore _store, bytes32 resourceId, address caller) internal view returns (bool access) { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -107,9 +111,9 @@ library ResourceAccess { } /** Get access */ - function get(bytes32 resourceSelector, address caller) internal view returns (bool access) { + function get(bytes32 resourceId, address caller) internal view returns (bool access) { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -117,9 +121,9 @@ library ResourceAccess { } /** Get access */ - function _get(bytes32 resourceSelector, address caller) internal view returns (bool access) { + function _get(bytes32 resourceId, address caller) internal view returns (bool access) { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -127,9 +131,9 @@ library ResourceAccess { } /** Get access (using the specified store) */ - function get(IStore _store, bytes32 resourceSelector, address caller) internal view returns (bool access) { + function get(IStore _store, bytes32 resourceId, address caller) internal view returns (bool access) { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -137,54 +141,54 @@ library ResourceAccess { } /** Set access */ - function setAccess(bytes32 resourceSelector, address caller, bool access) internal { + function setAccess(bytes32 resourceId, address caller, bool access) internal { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); } /** Set access */ - function _setAccess(bytes32 resourceSelector, address caller, bool access) internal { + function _setAccess(bytes32 resourceId, address caller, bool access) internal { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); } /** Set access (using the specified store) */ - function setAccess(IStore _store, bytes32 resourceSelector, address caller, bool access) internal { + function setAccess(IStore _store, bytes32 resourceId, address caller, bool access) internal { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); } /** Set access */ - function set(bytes32 resourceSelector, address caller, bool access) internal { + function set(bytes32 resourceId, address caller, bool access) internal { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); } /** Set access */ - function _set(bytes32 resourceSelector, address caller, bool access) internal { + function _set(bytes32 resourceId, address caller, bool access) internal { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); } /** Set access (using the specified store) */ - function set(IStore _store, bytes32 resourceSelector, address caller, bool access) internal { + function set(IStore _store, bytes32 resourceId, address caller, bool access) internal { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); @@ -206,36 +210,36 @@ library ResourceAccess { } /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(bytes32 resourceSelector, address caller) internal pure returns (bytes32[] memory) { + function encodeKeyTuple(bytes32 resourceId, address caller) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); return _keyTuple; } /* Delete all data for given keys */ - function deleteRecord(bytes32 resourceSelector, address caller) internal { + function deleteRecord(bytes32 resourceId, address caller) internal { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys */ - function _deleteRecord(bytes32 resourceSelector, address caller) internal { + function _deleteRecord(bytes32 resourceId, address caller) internal { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 resourceSelector, address caller) internal { + function deleteRecord(IStore _store, bytes32 resourceId, address caller) internal { bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceSelector; + _keyTuple[0] = resourceId; _keyTuple[1] = bytes32(uint256(uint160(caller))); _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); diff --git a/packages/world/src/worldResourceTypes.sol b/packages/world/src/worldResourceTypes.sol new file mode 100644 index 0000000000..d7ec187b3a --- /dev/null +++ b/packages/world/src/worldResourceTypes.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; + +bytes2 constant RESOURCE_NAMESPACE = "ns"; +bytes2 constant RESOURCE_MODULE = "md"; +bytes2 constant RESOURCE_SYSTEM = "sy"; + +bytes32 constant MASK_RESOURCE_NAMESPACE = bytes32(RESOURCE_NAMESPACE); +bytes32 constant MASK_RESOURCE_MODULE = bytes32(RESOURCE_MODULE); +bytes32 constant MASK_RESOURCE_SYSTEM = bytes32(RESOURCE_SYSTEM); diff --git a/packages/world/test/AccessControl.t.sol b/packages/world/test/AccessControl.t.sol index feddf64c67..413706328f 100644 --- a/packages/world/test/AccessControl.t.sol +++ b/packages/world/test/AccessControl.t.sol @@ -8,85 +8,95 @@ import { StoreMock } from "@latticexyz/store/test/StoreMock.sol"; import { IWorldErrors } from "../src/interfaces/IWorldErrors.sol"; import { World } from "../src/World.sol"; import { AccessControl } from "../src/AccessControl.sol"; -import { ResourceSelector } from "../src/ResourceSelector.sol"; +import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../src/WorldResourceId.sol"; +import { RESOURCE_TABLE } from "../src/worldResourceTypes.sol"; import { ResourceAccess } from "../src/tables/ResourceAccess.sol"; import { NamespaceOwner } from "../src/tables/NamespaceOwner.sol"; contract AccessControlTest is Test, GasReporter, StoreMock { - bytes16 constant namespace = "namespace"; - bytes16 constant name = "name"; - address constant presetCaller = address(0x0123); - address constant caller = address(0x01); + using WorldResourceIdInstance for ResourceId; + + bytes14 private constant namespace = "namespace"; + bytes16 private constant name = "name"; + address private constant presetCaller = address(0x0123); + address private constant caller = address(0x01); + + ResourceId private _tableId; + ResourceId private _namespaceId; function setUp() public { ResourceAccess.register(); NamespaceOwner.register(); + _tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: name }); + _namespaceId = WorldResourceIdLib.encodeNamespace(namespace); NamespaceOwner.set(namespace, address(this)); - ResourceAccess.set(ResourceSelector.from(namespace, name), presetCaller, true); + ResourceAccess.set(ResourceId.unwrap(_tableId), presetCaller, true); } function testAccessControl() public { + ResourceId tableId = _tableId; + ResourceId namespaceId = _namespaceId; bool hasAccess; // Check that the caller has no access to the namespace or name startGasReport("AccessControl: hasAccess (cold)"); - hasAccess = AccessControl.hasAccess(ResourceSelector.from(namespace, name), caller); + hasAccess = AccessControl.hasAccess(tableId, caller); endGasReport(); - assertFalse(hasAccess); + assertFalse(hasAccess, "caller should not have access to the table"); // Grant access to the namespace - ResourceAccess.set(ResourceSelector.from(namespace, 0), caller, true); + ResourceAccess.set(ResourceId.unwrap(namespaceId), caller, true); // Check that the caller has access to the namespace or name startGasReport("AccessControl: hasAccess (warm, namespace only)"); - hasAccess = AccessControl.hasAccess(ResourceSelector.from(namespace, name), caller); + hasAccess = AccessControl.hasAccess(tableId, caller); endGasReport(); - assertTrue(hasAccess); + assertTrue(hasAccess, "caller should have access to the namespace"); // Revoke access to the namespace - ResourceAccess.set(ResourceSelector.from(namespace, 0), caller, false); + ResourceAccess.set(ResourceId.unwrap(namespaceId), caller, false); // Check that the caller has no access to the namespace or name startGasReport("AccessControl: hasAccess (warm)"); - hasAccess = AccessControl.hasAccess(ResourceSelector.from(namespace, name), caller); + hasAccess = AccessControl.hasAccess(tableId, caller); endGasReport(); - assertFalse(hasAccess); + assertFalse(hasAccess, "access to the namespace should have been revoked"); // Grant access to the name - ResourceAccess.set(ResourceSelector.from(namespace, name), caller, true); + ResourceAccess.set(ResourceId.unwrap(tableId), caller, true); // Check that the caller has access to the name - assertTrue(AccessControl.hasAccess(ResourceSelector.from(namespace, name), caller)); + assertTrue(AccessControl.hasAccess(tableId, caller), "access to the table should have been granted"); // Revoke access to the name - ResourceAccess.set(ResourceSelector.from(namespace, name), caller, false); + ResourceAccess.set(ResourceId.unwrap(tableId), caller, false); // Check that the caller has no access to the namespace or name - assertFalse(AccessControl.hasAccess(ResourceSelector.from(namespace, name), caller)); + assertFalse(AccessControl.hasAccess(tableId, caller), "access to the table should have been revoked"); } function testRequireAccess() public { - bytes32 resourceSelector = ResourceSelector.from(namespace, name); + ResourceId tableId = _tableId; + startGasReport("AccessControl: requireAccess (cold)"); - AccessControl.requireAccess(resourceSelector, presetCaller); + AccessControl.requireAccess(tableId, presetCaller); endGasReport(); startGasReport("AccessControl: requireAccess (warm)"); - AccessControl.requireAccess(resourceSelector, presetCaller); + AccessControl.requireAccess(tableId, presetCaller); endGasReport(); startGasReport("AccessControl: requireAccess (this address)"); - AccessControl.requireAccess(resourceSelector, address(this)); + AccessControl.requireAccess(tableId, address(this)); endGasReport(); } function testRequireAccessRevert() public { - bytes32 resourceSelector = ResourceSelector.from(namespace, name); - vm.expectRevert( - abi.encodeWithSelector(IWorldErrors.AccessDenied.selector, ResourceSelector.toString(resourceSelector), caller) - ); - AccessControl.requireAccess(resourceSelector, caller); + ResourceId tableId = _tableId; + + vm.expectRevert(abi.encodeWithSelector(IWorldErrors.AccessDenied.selector, tableId.toString(), caller)); + AccessControl.requireAccess(tableId, caller); } } diff --git a/packages/world/test/Factories.t.sol b/packages/world/test/Factories.t.sol index 5887d42ddb..a943d7a41f 100644 --- a/packages/world/test/Factories.t.sol +++ b/packages/world/test/Factories.t.sol @@ -6,13 +6,14 @@ import { Test, console } from "forge-std/Test.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { WORLD_VERSION } from "../src/version.sol"; import { World } from "../src/World.sol"; +import { ResourceId } from "../src/WorldResourceId.sol"; import { CoreModule } from "../src/modules/core/CoreModule.sol"; import { Create2Factory } from "../src/factories/Create2Factory.sol"; import { WorldFactory } from "../src/factories/WorldFactory.sol"; import { IWorldFactory } from "../src/factories/IWorldFactory.sol"; import { InstalledModules } from "../src/tables/InstalledModules.sol"; import { NamespaceOwner } from "../src/tables/NamespaceOwner.sol"; -import { ROOT_NAMESPACE } from "../src/constants.sol"; +import { ROOT_NAMESPACE_ID } from "../src/constants.sol"; contract FactoriesTest is Test { event ContractDeployed(address addr, uint256 salt); @@ -80,6 +81,6 @@ contract FactoriesTest is Test { assertEq(uint256(worldFactory.worldCount()), uint256(1)); // Confirm the msg.sender is owner of the root namespace of the new world - assertEq(NamespaceOwner.get(ROOT_NAMESPACE), address(this)); + assertEq(NamespaceOwner.get(ResourceId.unwrap(ROOT_NAMESPACE_ID)), address(this)); } } diff --git a/packages/world/test/KeysInTableModule.t.sol b/packages/world/test/KeysInTableModule.t.sol index 7789e33740..2c1061b3fb 100644 --- a/packages/world/test/KeysInTableModule.t.sol +++ b/packages/world/test/KeysInTableModule.t.sol @@ -13,8 +13,9 @@ import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol" import { World } from "../src/World.sol"; import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; -import { ResourceSelector } from "../src/ResourceSelector.sol"; +import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../src/WorldResourceId.sol"; import { ROOT_NAMESPACE } from "../src/constants.sol"; +import { RESOURCE_TABLE } from "../src/worldResourceTypes.sol"; import { CoreModule } from "../src/modules/core/CoreModule.sol"; import { KeysInTableModule } from "../src/modules/keysintable/KeysInTableModule.sol"; @@ -22,11 +23,12 @@ import { getKeysInTable } from "../src/modules/keysintable/getKeysInTable.sol"; import { hasKey } from "../src/modules/keysintable/hasKey.sol"; contract KeysInTableModuleTest is Test, GasReporter { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; + IBaseWorld private world; KeysInTableModule private keysInTableModule = new KeysInTableModule(); // Modules can be deployed once and installed multiple times - bytes16 private namespace = ROOT_NAMESPACE; + bytes14 private namespace = ROOT_NAMESPACE; bytes16 private name = bytes16("source"); bytes16 private singletonName = bytes16("singleton"); bytes16 private compositeName = bytes16("composite"); @@ -42,9 +44,11 @@ contract KeysInTableModuleTest is Test, GasReporter { Schema private tableKeySchema; Schema private singletonKeySchema; Schema private compositeKeySchema; - bytes32 private tableId = ResourceSelector.from(namespace, name); - bytes32 private singletonTableId = ResourceSelector.from(namespace, singletonName); - bytes32 private compositeTableId = ResourceSelector.from(namespace, compositeName); + ResourceId private tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: name }); + ResourceId private singletonTableId = + WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: singletonName }); + ResourceId private compositeTableId = + WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: compositeName }); uint256 private val1 = 123; uint256 private val2 = 42; @@ -205,7 +209,11 @@ contract KeysInTableModuleTest is Test, GasReporter { // Install the hook on the second table bytes16 sourceFile2 = bytes16("source2"); - bytes32 sourceTableId2 = ResourceSelector.from(namespace, sourceFile2); + ResourceId sourceTableId2 = WorldResourceIdLib.encode({ + typeId: RESOURCE_TABLE, + namespace: namespace, + name: sourceFile2 + }); world.registerTable( sourceTableId2, tableFieldLayout, diff --git a/packages/world/test/KeysWithValueModule.t.sol b/packages/world/test/KeysWithValueModule.t.sol index fa8e8e83d5..2996090f62 100644 --- a/packages/world/test/KeysWithValueModule.t.sol +++ b/packages/world/test/KeysWithValueModule.t.sol @@ -4,32 +4,36 @@ pragma solidity >=0.8.0; import { Test, console } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; +import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; + import { Schema } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; import { SchemaEncodeHelper } from "@latticexyz/store/test/SchemaEncodeHelper.sol"; -import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; - import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; import { FieldLayoutEncodeHelper } from "@latticexyz/store/test/FieldLayoutEncodeHelper.sol"; import { World } from "../src/World.sol"; import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; -import { ResourceSelector } from "../src/ResourceSelector.sol"; +import { WorldResourceIdLib, WorldResourceIdInstance, NAME_BYTES, TYPE_BYTES } from "../src/WorldResourceId.sol"; import { ROOT_NAMESPACE } from "../src/constants.sol"; +import { RESOURCE_TABLE } from "../src/worldResourceTypes.sol"; import { CoreModule } from "../src/modules/core/CoreModule.sol"; import { KeysWithValueModule } from "../src/modules/keyswithvalue/KeysWithValueModule.sol"; 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 { getTargetTableSelector } from "../src/modules/utils/getTargetTableSelector.sol"; +import { getTargetTableId, MODULE_NAMESPACE_BYTES, TABLE_NAMESPACE_BYTES, TYPE_BYTES } from "../src/modules/keyswithvalue/getTargetTableId.sol"; contract KeysWithValueModuleTest is Test, GasReporter { - using ResourceSelector for bytes32; + using ResourceIdInstance for ResourceId; + using WorldResourceIdInstance for ResourceId; + IBaseWorld world; KeysWithValueModule private keysWithValueModule = new KeysWithValueModule(); // Modules can be deployed once and installed multiple times - bytes16 private namespace = ROOT_NAMESPACE; + bytes14 private namespace = ROOT_NAMESPACE; bytes16 private sourceName = bytes16("source"); bytes32 private key1 = keccak256("test"); bytes32[] private keyTuple1; @@ -39,8 +43,8 @@ contract KeysWithValueModuleTest is Test, GasReporter { FieldLayout private sourceTableFieldLayout; Schema private sourceTableSchema; Schema private sourceTableKeySchema; - bytes32 private sourceTableId; - bytes32 private targetTableId; + ResourceId private sourceTableId; + ResourceId private targetTableId; function setUp() public { sourceTableFieldLayout = FieldLayoutEncodeHelper.encode(32, 0); @@ -52,8 +56,8 @@ contract KeysWithValueModuleTest is Test, GasReporter { keyTuple1[0] = key1; keyTuple2 = new bytes32[](1); keyTuple2[0] = key2; - sourceTableId = ResourceSelector.from(namespace, sourceName); - targetTableId = getTargetTableSelector(MODULE_NAMESPACE, sourceTableId); + sourceTableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: sourceName }); + targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId); } function _installKeysWithValueModule() internal { @@ -75,6 +79,10 @@ contract KeysWithValueModuleTest is Test, GasReporter { endGasReport(); } + function testMatchingByteSizes() public { + assertEq(MODULE_NAMESPACE_BYTES + TABLE_NAMESPACE_BYTES + NAME_BYTES + TYPE_BYTES, 32); + } + function testInstall() public { _installKeysWithValueModule(); // Set a value in the source table @@ -217,19 +225,30 @@ contract KeysWithValueModuleTest is Test, GasReporter { assertEq(keysWithValue[0], key1); } - function testGetTargetTableSelector() public { + function testGetTargetTableId() public { startGasReport("compute the target table selector"); - bytes32 targetTableSelector = getTargetTableSelector(MODULE_NAMESPACE, sourceTableId); + ResourceId _targetTableId = getTargetTableId(MODULE_NAMESPACE, sourceTableId); endGasReport(); - // The first 8 bytes are the module namespace - assertEq(bytes8(targetTableSelector), MODULE_NAMESPACE); + // The first 2 bytes are the resource type + assertEq(_targetTableId.getType(), RESOURCE_TABLE, "target table resource type does not match"); - // followed by the first 4 bytes of the source table namespace - assertEq(bytes8(targetTableSelector << 64), bytes8(namespace)); + // The next 7 bytes are the module namespace + assertEq( + bytes7(ResourceId.unwrap(_targetTableId) << (TYPE_BYTES * 8)), + 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(namespace), + "table namespace does not match" + ); // The last 16 bytes are the source name - assertEq(targetTableSelector.getName(), sourceName); + assertEq(_targetTableId.getName(), sourceName, "table name does not match"); } function testGetKeysWithValueGas() public { diff --git a/packages/world/test/StandardDelegationsModule.t.sol b/packages/world/test/StandardDelegationsModule.t.sol index 28006e43c4..5d1dd56e32 100644 --- a/packages/world/test/StandardDelegationsModule.t.sol +++ b/packages/world/test/StandardDelegationsModule.t.sol @@ -5,13 +5,17 @@ import { Test } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { World } from "../src/World.sol"; -import { ResourceSelector } from "../src/ResourceSelector.sol"; -import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; +import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../src/WorldResourceId.sol"; import { System } from "../src/System.sol"; +import { RESOURCE_SYSTEM } from "../src/worldResourceTypes.sol"; + +import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; import { IWorldErrors } from "../src/interfaces/IWorldErrors.sol"; import { DELEGATION_CONTROL_INTERFACE_ID } from "../src/interfaces/IDelegationControl.sol"; + import { CoreModule } from "../src/modules/core/CoreModule.sol"; import { Systems } from "../src/modules/core/tables/Systems.sol"; + import { StandardDelegationsModule } from "../src/modules/std-delegations/StandardDelegationsModule.sol"; import { CallboundDelegationControl } from "../src/modules/std-delegations/CallboundDelegationControl.sol"; import { TimeboundDelegationControl } from "../src/modules/std-delegations/TimeboundDelegationControl.sol"; @@ -21,7 +25,8 @@ import { WorldTestSystem } from "./World.t.sol"; contract StandardDelegationsModuleTest is Test, GasReporter { IBaseWorld private world; - bytes32 private systemResourceSelector = ResourceSelector.from("namespace", "testSystem"); + ResourceId private systemId = + WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "namespace", name: "testSystem" }); address private delegator = address(1); address private delegatee = address(2); @@ -32,7 +37,7 @@ contract StandardDelegationsModuleTest is Test, GasReporter { // Register a new system WorldTestSystem system = new WorldTestSystem(); - world.registerSystem(systemResourceSelector, system, true); + world.registerSystem(systemId, system, true); } function testCallFromCallboundDelegation() public { @@ -44,7 +49,7 @@ contract StandardDelegationsModuleTest is Test, GasReporter { CALLBOUND_DELEGATION, abi.encodeCall( CallboundDelegationControl.initDelegation, - (delegatee, systemResourceSelector, abi.encodeCall(WorldTestSystem.msgSender, ()), 1) + (delegatee, systemId, abi.encodeCall(WorldTestSystem.msgSender, ()), 1) ) ); endGasReport(); @@ -52,11 +57,7 @@ contract StandardDelegationsModuleTest is Test, GasReporter { // Call a system from the delegatee on behalf of the delegator vm.prank(delegatee); startGasReport("call a system via a callbound delegation"); - bytes memory returnData = world.callFrom( - delegator, - systemResourceSelector, - abi.encodeCall(WorldTestSystem.msgSender, ()) - ); + bytes memory returnData = world.callFrom(delegator, systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); endGasReport(); address returnedAddress = abi.decode(returnData, (address)); @@ -66,7 +67,7 @@ contract StandardDelegationsModuleTest is Test, GasReporter { // Expect the delegation to have been used up vm.prank(delegatee); vm.expectRevert(abi.encodeWithSelector(IWorldErrors.DelegationNotFound.selector, delegator, delegatee)); - world.callFrom(delegator, systemResourceSelector, abi.encodeCall(WorldTestSystem.msgSender, ())); + world.callFrom(delegator, systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); } function testCallFromTimeboundDelegation() public { @@ -88,11 +89,7 @@ contract StandardDelegationsModuleTest is Test, GasReporter { // Call a system from the delegatee on behalf of the delegator vm.prank(delegatee); startGasReport("call a system via a timebound delegation"); - bytes memory returnData = world.callFrom( - delegator, - systemResourceSelector, - abi.encodeCall(WorldTestSystem.msgSender, ()) - ); + bytes memory returnData = world.callFrom(delegator, systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); endGasReport(); address returnedAddress = abi.decode(returnData, (address)); @@ -102,19 +99,23 @@ contract StandardDelegationsModuleTest is Test, GasReporter { // Set the timestamp to maxTimestamp and expect the delegation to still be valid vm.warp(maxTimestamp); vm.prank(delegatee); - world.callFrom(delegator, systemResourceSelector, abi.encodeCall(WorldTestSystem.msgSender, ())); + world.callFrom(delegator, systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); // Set the timestamp to maxTimestamp+1 and expect the delegation to be expired vm.warp(maxTimestamp + 1); vm.prank(delegatee); vm.expectRevert(abi.encodeWithSelector(IWorldErrors.DelegationNotFound.selector, delegator, delegatee)); - world.callFrom(delegator, systemResourceSelector, abi.encodeCall(WorldTestSystem.msgSender, ())); + world.callFrom(delegator, systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); } function testRegisterDelegationRevertInterfaceNotSupported() public { // Register a system that is not a delegation control system System noDelegationControlSystem = new System(); - bytes32 noDelegationControlId = ResourceSelector.from("namespace", "noDelegation"); + ResourceId noDelegationControlId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "noDelegation" + }); world.registerSystem(noDelegationControlId, noDelegationControlSystem, true); // Expect the registration to revert if the system does not implement the delegation control interface diff --git a/packages/world/test/UniqueEntityModule.t.sol b/packages/world/test/UniqueEntityModule.t.sol index 22db658279..d9c24f2ec7 100644 --- a/packages/world/test/UniqueEntityModule.t.sol +++ b/packages/world/test/UniqueEntityModule.t.sol @@ -14,14 +14,15 @@ import { UniqueEntity } from "../src/modules/uniqueentity/tables/UniqueEntity.so import { getUniqueEntity } from "../src/modules/uniqueentity/getUniqueEntity.sol"; import { NAMESPACE, TABLE_NAME } from "../src/modules/uniqueentity/constants.sol"; -import { ResourceSelector } from "../src/ResourceSelector.sol"; +import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../src/WorldResourceId.sol"; +import { RESOURCE_TABLE } from "../src/worldResourceTypes.sol"; contract UniqueEntityModuleTest is Test, GasReporter { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; IBaseWorld world; UniqueEntityModule uniqueEntityModule = new UniqueEntityModule(); - bytes32 tableId = ResourceSelector.from(NAMESPACE, TABLE_NAME); + ResourceId _tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: NAMESPACE, name: TABLE_NAME }); function setUp() public { world = IBaseWorld(address(new World())); @@ -29,6 +30,8 @@ contract UniqueEntityModuleTest is Test, GasReporter { } function testInstall() public { + ResourceId tableId = _tableId; + startGasReport("install unique entity module"); world.installModule(uniqueEntityModule, new bytes(0)); endGasReport(); @@ -45,6 +48,8 @@ contract UniqueEntityModuleTest is Test, GasReporter { } function testInstallRoot() public { + ResourceId tableId = _tableId; + startGasReport("installRoot unique entity module"); world.installRootModule(uniqueEntityModule, new bytes(0)); endGasReport(); @@ -61,6 +66,8 @@ contract UniqueEntityModuleTest is Test, GasReporter { } function testPublicAccess() public { + ResourceId tableId = _tableId; + world.installModule(uniqueEntityModule, new bytes(0)); // Anyone should be able to call `getUniqueEntity` @@ -78,7 +85,7 @@ contract UniqueEntityModuleTest is Test, GasReporter { vm.expectRevert( abi.encodeWithSelector( IWorldErrors.AccessDenied.selector, - ResourceSelector.from(NAMESPACE, TABLE_NAME).toString(), + WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: NAMESPACE, name: TABLE_NAME }).toString(), alice ) ); diff --git a/packages/world/test/Utils.t.sol b/packages/world/test/Utils.t.sol index d3def80af0..98b7752ea3 100644 --- a/packages/world/test/Utils.t.sol +++ b/packages/world/test/Utils.t.sol @@ -7,7 +7,8 @@ import { Utils } from "../src/Utils.sol"; import { System } from "../src/System.sol"; import { World } from "../src/World.sol"; import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; -import { ResourceSelector } from "../src/ResourceSelector.sol"; +import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../src/WorldResourceId.sol"; +import { RESOURCE_SYSTEM } from "../src/worldResourceTypes.sol"; import { CoreModule } from "../src/modules/core/CoreModule.sol"; @@ -18,7 +19,7 @@ contract UtilsTestSystem is System { } contract UtilsTest is Test { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; IBaseWorld internal world; error SomeError(uint256 someValue, string someString); @@ -28,20 +29,19 @@ contract UtilsTest is Test { world.initialize(new CoreModule()); } - function _registerAndGetNamespace(bytes16 namespace) internal returns (bytes16 returnedNamespace) { + function _registerAndGetNamespace(bytes14 namespace) internal returns (bytes16 returnedNamespace) { UtilsTestSystem testSystem = new UtilsTestSystem(); bytes16 name = "testSystem"; - world.registerSystem(ResourceSelector.from(namespace, name), testSystem, true); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: name }); + world.registerSystem(systemId, testSystem, true); + + bytes memory data = world.call(systemId, abi.encodeCall(UtilsTestSystem.systemNamespace, ())); - bytes memory data = world.call( - ResourceSelector.from(namespace, name), - abi.encodeCall(UtilsTestSystem.systemNamespace, ()) - ); returnedNamespace = abi.decode(data, (bytes16)); } function testSystemNamespace() public { - bytes16 namespace; + bytes14 namespace; bytes16 returnedNamespace; namespace = ""; @@ -52,7 +52,7 @@ contract UtilsTest is Test { returnedNamespace = _registerAndGetNamespace(namespace); assertEq(returnedNamespace, namespace); - namespace = "maxlen_namespace"; + namespace = "max_len_nmspce"; returnedNamespace = _registerAndGetNamespace(namespace); assertEq(returnedNamespace, namespace); } diff --git a/packages/world/test/World.t.sol b/packages/world/test/World.t.sol index 9194959b2d..3b242852bc 100644 --- a/packages/world/test/World.t.sol +++ b/packages/world/test/World.t.sol @@ -8,13 +8,14 @@ import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol" import { IStoreHook, STORE_HOOK_INTERFACE_ID } from "@latticexyz/store/src/IStoreHook.sol"; import { StoreCore, StoreCoreInternal } from "@latticexyz/store/src/StoreCore.sol"; +import { IStoreErrors } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { FieldLayoutEncodeHelper } from "@latticexyz/store/test/FieldLayoutEncodeHelper.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { SchemaEncodeHelper } from "@latticexyz/store/test/SchemaEncodeHelper.sol"; -import { Tables, TablesTableId } from "@latticexyz/store/src/codegen/index.sol"; +import { Tables, ResourceIds, TablesTableId } from "@latticexyz/store/src/codegen/index.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { ALL, BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SPLICE_STATIC_DATA, AFTER_SPLICE_STATIC_DATA, BEFORE_SPLICE_DYNAMIC_DATA, AFTER_SPLICE_DYNAMIC_DATA, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "@latticexyz/store/src/storeHookTypes.sol"; import { RevertSubscriber } from "@latticexyz/store/test/RevertSubscriber.sol"; @@ -23,9 +24,9 @@ import { EchoSubscriber } from "@latticexyz/store/test/EchoSubscriber.sol"; import { WORLD_VERSION } from "../src/version.sol"; import { World } from "../src/World.sol"; import { System } from "../src/System.sol"; -import { ResourceSelector } from "../src/ResourceSelector.sol"; -import { ROOT_NAMESPACE, ROOT_NAME, UNLIMITED_DELEGATION } from "../src/constants.sol"; -import { Resource } from "../src/common.sol"; +import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../src/WorldResourceId.sol"; +import { ROOT_NAMESPACE, ROOT_NAME, ROOT_NAMESPACE_ID, UNLIMITED_DELEGATION } from "../src/constants.sol"; +import { RESOURCE_TABLE, RESOURCE_SYSTEM, RESOURCE_NAMESPACE } from "../src/worldResourceTypes.sol"; import { WorldContextProvider, WORLD_CONTEXT_CONSUMER_INTERFACE_ID } from "../src/WorldContext.sol"; import { SystemHook } from "../src/SystemHook.sol"; import { BEFORE_CALL_SYSTEM, AFTER_CALL_SYSTEM } from "../src/systemHookTypes.sol"; @@ -37,7 +38,6 @@ import { ResourceAccess } from "../src/tables/ResourceAccess.sol"; import { CoreModule } from "../src/modules/core/CoreModule.sol"; import { Systems } from "../src/modules/core/tables/Systems.sol"; import { SystemRegistry } from "../src/modules/core/tables/SystemRegistry.sol"; -import { ResourceType } from "../src/modules/core/tables/ResourceType.sol"; import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; import { IWorldErrors } from "../src/interfaces/IWorldErrors.sol"; @@ -88,9 +88,9 @@ contract WorldTestSystem is System { return returndata; } - function writeData(bytes16 namespace, bytes16 name, bool data) public { + function writeData(bytes14 namespace, bytes16 name, bool data) public { bytes32[] memory keyTuple = new bytes32[](0); - bytes32 tableId = ResourceSelector.from(namespace, name); + ResourceId tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: name }); FieldLayout fieldLayout = StoreSwitch.getFieldLayout(tableId); if (StoreSwitch.getStoreAddress() == address(this)) { @@ -136,29 +136,29 @@ contract PayableFallbackSystem is System { contract EchoSystemHook is SystemHook { event SystemHookCalled(bytes data); - function onBeforeCallSystem(address msgSender, bytes32 resourceSelector, bytes memory callData) public { - emit SystemHookCalled(abi.encode("before", msgSender, resourceSelector, callData)); + function onBeforeCallSystem(address msgSender, ResourceId systemId, bytes memory callData) public { + emit SystemHookCalled(abi.encode("before", msgSender, systemId, callData)); } - function onAfterCallSystem(address msgSender, bytes32 resourceSelector, bytes memory callData) public { - emit SystemHookCalled(abi.encode("after", msgSender, resourceSelector, callData)); + function onAfterCallSystem(address msgSender, ResourceId systemId, bytes memory callData) public { + emit SystemHookCalled(abi.encode("after", msgSender, systemId, callData)); } } contract RevertSystemHook is SystemHook { event SystemHookCalled(bytes data); - function onBeforeCallSystem(address, bytes32, bytes memory) public pure { + function onBeforeCallSystem(address, ResourceId, bytes memory) public pure { revert("onBeforeCallSystem"); } - function onAfterCallSystem(address, bytes32, bytes memory) public pure { + function onAfterCallSystem(address, ResourceId, bytes memory) public pure { revert("onAfterCallSystem"); } } contract WorldTest is Test, GasReporter { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; event HelloWorld(bytes32 indexed worldVersion); event HookCalled(bytes data); @@ -183,12 +183,12 @@ contract WorldTest is Test, GasReporter { } // Expect an error when trying to write from an address that doesn't have access - function _expectAccessDenied(address caller, bytes16 namespace, bytes16 name) internal { + function _expectAccessDenied(address caller, bytes14 namespace, bytes16 name, bytes2 resourceType) internal { vm.prank(caller); vm.expectRevert( abi.encodeWithSelector( IWorldErrors.AccessDenied.selector, - ResourceSelector.from(namespace, name).toString(), + WorldResourceIdLib.encode({ typeId: resourceType, namespace: namespace, name: name }).toString(), caller ) ); @@ -209,7 +209,7 @@ contract WorldTest is Test, GasReporter { vm.expectRevert( abi.encodeWithSelector( IWorldErrors.AccessDenied.selector, - ResourceSelector.from(ROOT_NAMESPACE).toString(), + WorldResourceIdLib.encodeNamespace(ROOT_NAMESPACE).toString(), address(0x4242) ) ); @@ -219,18 +219,30 @@ contract WorldTest is Test, GasReporter { newWorld.initialize(coreModule); // Should have registered the table data table (fka schema table) - assertEq(Tables.getFieldLayout(newWorld, TablesTableId), FieldLayout.unwrap(Tables.getFieldLayout())); - assertEq(Tables.getAbiEncodedKeyNames(newWorld, TablesTableId), abi.encode(Tables.getKeyNames())); - assertEq(Tables.getAbiEncodedFieldNames(newWorld, TablesTableId), abi.encode(Tables.getFieldNames())); + assertEq( + Tables.getFieldLayout(newWorld, ResourceId.unwrap(TablesTableId)), + FieldLayout.unwrap(Tables.getFieldLayout()) + ); + assertEq( + Tables.getAbiEncodedKeyNames(newWorld, ResourceId.unwrap(TablesTableId)), + abi.encode(Tables.getKeyNames()) + ); + assertEq( + Tables.getAbiEncodedFieldNames(newWorld, ResourceId.unwrap(TablesTableId)), + abi.encode(Tables.getFieldNames()) + ); // Should have registered the namespace owner table assertEq( - Tables.getFieldLayout(newWorld, NamespaceOwnerTableId), + Tables.getFieldLayout(newWorld, ResourceId.unwrap(NamespaceOwnerTableId)), FieldLayout.unwrap(NamespaceOwner.getFieldLayout()) ); - assertEq(Tables.getAbiEncodedKeyNames(newWorld, NamespaceOwnerTableId), abi.encode(NamespaceOwner.getKeyNames())); assertEq( - Tables.getAbiEncodedFieldNames(newWorld, NamespaceOwnerTableId), + Tables.getAbiEncodedKeyNames(newWorld, ResourceId.unwrap(NamespaceOwnerTableId)), + abi.encode(NamespaceOwner.getKeyNames()) + ); + assertEq( + Tables.getAbiEncodedFieldNames(newWorld, ResourceId.unwrap(NamespaceOwnerTableId)), abi.encode(NamespaceOwner.getFieldNames()) ); @@ -263,80 +275,135 @@ contract WorldTest is Test, GasReporter { function testRootNamespace() public { // Owner of root route should be the creator of the World - address rootOwner = NamespaceOwner.get(world, ROOT_NAMESPACE); + address rootOwner = NamespaceOwner.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)); assertEq(rootOwner, address(this)); // The creator of the World should have access to the root namespace - assertTrue(ResourceAccess.get(world, ROOT_NAMESPACE, address(this))); + assertTrue(ResourceAccess.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID), address(this))); } function testStoreAddress() public { // Register a system and use it to get storeAddress WorldTestSystem system = new WorldTestSystem(); - bytes32 resourceSelector = ResourceSelector.from("namespace", "testSystem"); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testSystem" + }); - world.registerSystem(resourceSelector, system, false); - bytes memory result = world.call(resourceSelector, abi.encodeCall(WorldTestSystem.getStoreAddress, ())); + world.registerSystem(systemId, system, false); + bytes memory result = world.call(systemId, abi.encodeCall(WorldTestSystem.getStoreAddress, ())); assertEq(abi.decode(result, (address)), address(world)); } function testRegisterNamespace() public { + bytes14 namespace = "testNamespace"; + ResourceId namespaceId = WorldResourceIdLib.encodeNamespace(namespace); startGasReport("Register a new namespace"); - world.registerNamespace("test"); + world.registerNamespace(namespaceId); endGasReport(); // Expect the caller to be the namespace owner - assertEq(NamespaceOwner.get(world, "test"), address(this), "caller should be namespace owner"); + assertEq( + NamespaceOwner.get(world, ResourceId.unwrap(namespaceId)), + address(this), + "caller should be namespace owner" + ); // Expect the caller to have access - assertEq(ResourceAccess.get(world, "test", address(this)), true, "caller should have access"); + assertEq( + ResourceAccess.get(world, ResourceId.unwrap(namespaceId), address(this)), + true, + "caller should have access" + ); + + // Expect the resource ID to have been registered + assertTrue(ResourceIds.getExists(world, ResourceId.unwrap(namespaceId))); // Expect an error when registering an existing namespace + vm.expectRevert(abi.encodeWithSelector(IWorldErrors.ResourceExists.selector, namespaceId, namespaceId.toString())); + world.registerNamespace(namespaceId); + } + + function testRegisterNamespaceRevertInvalidType() public { + ResourceId invalidNamespaceId = WorldResourceIdLib.encode({ + typeId: RESOURCE_TABLE, + namespace: "namespace", + name: "name" + }); + + // Expect an error when trying to register a namespace with an invalid type vm.expectRevert( - abi.encodeWithSelector(IWorldErrors.ResourceExists.selector, ResourceSelector.toString(bytes16("test"))) + abi.encodeWithSelector( + IWorldErrors.InvalidResourceType.selector, + RESOURCE_NAMESPACE, + invalidNamespaceId, + invalidNamespaceId.toString() + ) ); - world.registerNamespace("test"); + world.registerNamespace(invalidNamespaceId); } function testTransferNamespace() public { - world.registerNamespace("testTransfer"); + bytes14 namespace = "testTransfer"; + ResourceId namespaceId = WorldResourceIdLib.encodeNamespace(namespace); + + world.registerNamespace(namespaceId); // Expect the new owner to not be namespace owner before transfer assertFalse( - (NamespaceOwner.get(world, "testTransfer") == address(1)), + (NamespaceOwner.get(world, ResourceId.unwrap(namespaceId)) == address(1)), "new owner should not be namespace owner before transfer" ); // Expect the new owner to not have access before transfer assertEq( - ResourceAccess.get(world, "testTransfer", address(1)), + ResourceAccess.get(world, ResourceId.unwrap(namespaceId), address(1)), false, "new owner should not have access before transfer" ); - world.transferOwnership("testTransfer", address(1)); + world.transferOwnership(namespaceId, address(1)); + // Expect the new owner to be namespace owner - assertEq(NamespaceOwner.get(world, "testTransfer"), address(1), "new owner should be namespace owner"); + assertEq( + NamespaceOwner.get(world, ResourceId.unwrap(namespaceId)), + address(1), + "new owner should be namespace owner" + ); + // Expect the new owner to have access - assertEq(ResourceAccess.get(world, "testTransfer", address(1)), true, "new owner should have access"); + assertEq( + ResourceAccess.get(world, ResourceId.unwrap(namespaceId), address(1)), + true, + "new owner should have access" + ); + // Expect previous owner to no longer be owner assertFalse( - (NamespaceOwner.get(world, "testTransfer") == address(this)), + (NamespaceOwner.get(world, ResourceId.unwrap(namespaceId)) == address(this)), "caller should no longer be namespace owner" ); + // Expect previous owner to no longer have access - assertEq(ResourceAccess.get(world, "testTransfer", address(this)), false, "caller should no longer have access"); + assertEq( + ResourceAccess.get(world, ResourceId.unwrap(namespaceId), address(this)), + false, + "caller should no longer have access" + ); + // Expect revert if caller is not the owner - _expectAccessDenied(address(this), "testTransfer", 0); - world.transferOwnership("testTransfer", address(1)); + _expectAccessDenied(address(this), namespace, 0, RESOURCE_NAMESPACE); + world.transferOwnership(namespaceId, address(1)); } function testRegisterTable() public { FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(1, 32, 1); Schema valueSchema = SchemaEncodeHelper.encode(SchemaType.BOOL, SchemaType.UINT256, SchemaType.STRING); - bytes16 namespace = "testNamespace"; + bytes14 namespace = "testNamespace"; bytes16 tableName = "testTable"; - bytes32 tableSelector = ResourceSelector.from(namespace, tableName); + ResourceId namespaceId = WorldResourceIdLib.encodeNamespace(namespace); + ResourceId tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: tableName }); string[] memory keyNames = new string[](1); keyNames[0] = "key1"; string[] memory fieldNames = new string[](3); @@ -345,79 +412,113 @@ contract WorldTest is Test, GasReporter { fieldNames[2] = "value3"; startGasReport("Register a new table in the namespace"); - world.registerTable(tableSelector, fieldLayout, defaultKeySchema, valueSchema, keyNames, fieldNames); + world.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, keyNames, fieldNames); endGasReport(); // Expect the namespace to be created and owned by the caller - assertEq(NamespaceOwner.get(world, namespace), address(this), "namespace should be created by caller"); + assertEq( + NamespaceOwner.get(world, ResourceId.unwrap(namespaceId)), + address(this), + "namespace should be created by caller" + ); // Expect the table to be registered - assertEq(world.getFieldLayout(tableSelector).unwrap(), fieldLayout.unwrap(), "value schema should be registered"); + assertEq(world.getFieldLayout(tableId).unwrap(), fieldLayout.unwrap(), "value schema should be registered"); - bytes memory loadedKeyNames = Tables.getAbiEncodedKeyNames(world, tableSelector); + bytes memory loadedKeyNames = Tables.getAbiEncodedKeyNames(world, ResourceId.unwrap(tableId)); assertEq(loadedKeyNames, abi.encode(keyNames), "key names should be registered"); - bytes memory loadedfieldNames = Tables.getAbiEncodedFieldNames(world, tableSelector); + bytes memory loadedfieldNames = Tables.getAbiEncodedFieldNames(world, ResourceId.unwrap(tableId)); assertEq(loadedfieldNames, abi.encode(fieldNames), "value names should be registered"); // Expect an error when registering an existing table - vm.expectRevert(abi.encodeWithSelector(IWorldErrors.ResourceExists.selector, tableSelector.toString())); - world.registerTable(tableSelector, fieldLayout, defaultKeySchema, valueSchema, keyNames, fieldNames); + vm.expectRevert( + abi.encodeWithSelector( + IStoreErrors.StoreCore_TableAlreadyExists.selector, + tableId, + string(bytes.concat(ResourceId.unwrap(tableId))) + ) + ); + world.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, keyNames, fieldNames); // Expect an error when registering a table in a namespace that is not owned by the caller - bytes32 otherTableSelector = ResourceSelector.from(namespace, "otherTable"); - _expectAccessDenied(address(0x01), namespace, ""); - world.registerTable(otherTableSelector, fieldLayout, defaultKeySchema, valueSchema, keyNames, fieldNames); + ResourceId otherTableId = WorldResourceIdLib.encode({ + typeId: RESOURCE_TABLE, + namespace: namespace, + name: "otherTable" + }); + _expectAccessDenied(address(0x01), namespace, "", RESOURCE_NAMESPACE); + world.registerTable(otherTableId, fieldLayout, defaultKeySchema, valueSchema, keyNames, fieldNames); // Expect the World to not be allowed to call registerTable via an external call - _expectAccessDenied(address(world), namespace, ""); - world.registerTable(otherTableSelector, fieldLayout, defaultKeySchema, valueSchema, keyNames, fieldNames); + _expectAccessDenied(address(world), namespace, "", RESOURCE_NAMESPACE); + world.registerTable(otherTableId, fieldLayout, defaultKeySchema, valueSchema, keyNames, fieldNames); } function testRegisterSystem() public { System system = new System(); - bytes16 namespace = ""; + bytes14 namespace = ""; + ResourceId namespaceId = WorldResourceIdLib.encodeNamespace(namespace); bytes16 name = "testSystem"; - bytes32 resourceSelector = ResourceSelector.from(namespace, name); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: name }); - // !gasrepot Register a new system - world.registerSystem(resourceSelector, system, false); + startGasReport("register a system"); + world.registerSystem(systemId, system, false); + endGasReport(); // Expect the system to be registered - (address registeredAddress, bool publicAccess) = Systems.get(world, resourceSelector); + (address registeredAddress, bool publicAccess) = Systems.get(world, ResourceId.unwrap(systemId)); assertEq(registeredAddress, address(system)); + // Expect the system's resource ID to have been registered + assertTrue(ResourceIds.getExists(world, ResourceId.unwrap(systemId))); + // Expect the system namespace to be owned by the caller - address routeOwner = NamespaceOwner.get(world, ""); + address routeOwner = NamespaceOwner.get(world, ResourceId.unwrap(namespaceId)); assertEq(routeOwner, address(this)); // Expect the system to not be publicly accessible assertFalse(publicAccess); // Expect the system to be accessible by the caller - assertTrue(ResourceAccess.get({ _store: world, resourceSelector: "", caller: address(this) })); + assertTrue( + ResourceAccess.get({ _store: world, resourceId: ResourceId.unwrap(namespaceId), caller: address(this) }) + ); // Expect the system to not be accessible by another address - assertFalse(ResourceAccess.get({ _store: world, resourceSelector: "", caller: address(0x1) })); + assertFalse( + ResourceAccess.get({ _store: world, resourceId: ResourceId.unwrap(namespaceId), caller: address(0x1) }) + ); // Expect the system to have access to its own namespace - assertTrue(ResourceAccess.get({ _store: world, resourceSelector: "", caller: address(system) })); + assertTrue( + ResourceAccess.get({ _store: world, resourceId: ResourceId.unwrap(namespaceId), caller: address(system) }) + ); + ResourceId newNamespaceId = WorldResourceIdLib.encodeNamespace("newNamespace"); // Expect the namespace to be created if it doesn't exist yet - assertEq(NamespaceOwner.get(world, "newNamespace"), address(0)); - world.registerSystem(ResourceSelector.from("newNamespace", "testSystem"), new System(), false); - assertEq(NamespaceOwner.get(world, "newNamespace"), address(this)); + assertEq(NamespaceOwner.get(world, ResourceId.unwrap(newNamespaceId)), address(0)); + world.registerSystem( + WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "newNamespace", name: "testSystem" }), + new System(), + false + ); + assertEq(NamespaceOwner.get(world, ResourceId.unwrap(newNamespaceId)), address(this)); - // Expect an error when registering an existing system at a new resource selector + // Expect an error when registering an existing system at a new system ID vm.expectRevert(abi.encodeWithSelector(IWorldErrors.SystemExists.selector, address(system))); - world.registerSystem(ResourceSelector.from("", "newSystem"), system, true); + world.registerSystem( + WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "", name: "newSystem" }), + system, + true + ); // Don't expect an error when updating the public access of an existing system - world.registerSystem(resourceSelector, system, true); + world.registerSystem(systemId, system, true); - // Expect an error when registering a system at an existing resource selector of a different type + // Expect an error when registering a system at an existing resource ID of a different type System newSystem = new System(); - bytes32 tableId = ResourceSelector.from("", "testTable"); + ResourceId tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: "", name: "testTable" }); world.registerTable( tableId, Bool.getFieldLayout(), @@ -426,17 +527,27 @@ contract WorldTest is Test, GasReporter { new string[](1), new string[](1) ); - vm.expectRevert(abi.encodeWithSelector(IWorldErrors.ResourceExists.selector, tableId.toString())); + vm.expectRevert( + abi.encodeWithSelector(IWorldErrors.InvalidResourceType.selector, RESOURCE_SYSTEM, tableId, tableId.toString()) + ); world.registerSystem(tableId, newSystem, true); - // Expect an error when registering a system in a namespace is not owned by the caller + // Expect an error when registering a system in a namespace that is not owned by the caller System yetAnotherSystem = new System(); - _expectAccessDenied(address(0x01), "", ""); - world.registerSystem(ResourceSelector.from("", "rootSystem"), yetAnotherSystem, true); + _expectAccessDenied(address(0x01), "", "", RESOURCE_NAMESPACE); + world.registerSystem( + WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "", name: "rootSystem" }), + yetAnotherSystem, + true + ); // Expect the registration to fail when coming from the World (since the World address doesn't have access) - _expectAccessDenied(address(world), "", ""); - world.registerSystem(ResourceSelector.from("", "rootSystem"), yetAnotherSystem, true); + _expectAccessDenied(address(world), "", "", RESOURCE_NAMESPACE); + world.registerSystem( + WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "", name: "rootSystem" }), + yetAnotherSystem, + true + ); // Expect the registration to fail if the provided address does not implement the WorldContextConsumer interface vm.expectRevert( @@ -446,13 +557,22 @@ contract WorldTest is Test, GasReporter { WORLD_CONTEXT_CONSUMER_INTERFACE_ID ) ); - world.registerSystem(ResourceSelector.from("someNamespace", "invalidSystem"), System(address(world)), true); + world.registerSystem( + WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "someNamespace", name: "invalidSystem" }), + System(address(world)), + true + ); } function testUpgradeSystem() public { - bytes16 namespace = "testNamespace"; + bytes14 namespace = "testNamespace"; + ResourceId namespaceId = WorldResourceIdLib.encodeNamespace(namespace); bytes16 systemName = "testSystem"; - bytes32 systemId = ResourceSelector.from(namespace, systemName); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: namespace, + name: systemName + }); // Register a system System oldSystem = new System(); @@ -463,33 +583,39 @@ contract WorldTest is Test, GasReporter { world.registerSystem(systemId, newSystem, false); // Expect the system address and public access to be updated in the System table - (address registeredAddress, bool publicAccess) = Systems.get(world, systemId); - assertEq(registeredAddress, address(newSystem)); - assertEq(publicAccess, false); + (address registeredAddress, bool publicAccess) = Systems.get(world, ResourceId.unwrap(systemId)); + assertEq(registeredAddress, address(newSystem), "system address should be updated"); + assertEq(publicAccess, false, "public access should be updated"); // Expect the SystemRegistry table to not have a reference to the old system anymore bytes32 registeredSystemId = SystemRegistry.get(world, address(oldSystem)); - assertEq(registeredSystemId, bytes32(0)); + assertEq(registeredSystemId, bytes32(0), "old system should be removed from SystemRegistry"); // Expect the SystemRegistry table to have a reference to the new system registeredSystemId = SystemRegistry.get(world, address(newSystem)); - assertEq(registeredSystemId, systemId); + assertEq(registeredSystemId, ResourceId.unwrap(systemId), "new system should be added to SystemRegistry"); // Expect the old system to not have access to the namespace anymore - assertFalse(ResourceAccess.get(world, namespace, address(oldSystem))); + assertFalse( + ResourceAccess.get(world, ResourceId.unwrap(namespaceId), address(oldSystem)), + "old system should not have access to the namespace" + ); // Expect the new system to have access to the namespace - assertTrue(ResourceAccess.get(world, namespace, address(newSystem))); + assertTrue( + ResourceAccess.get(world, ResourceId.unwrap(namespaceId), address(newSystem)), + "new system should have access to the namespace" + ); - // Expect the resource type to still be SYSTEM - assertEq(uint8(ResourceType.get(world, systemId)), uint8(Resource.SYSTEM)); + // Expect the resource ID to still be registered + assertTrue(ResourceIds.getExists(world, ResourceId.unwrap(systemId)), "resource type should still be SYSTEM"); } - function testDuplicateSelectors() public { + function testInvalidIds() public { // Register a new table - bytes32 resourceSelector = ResourceSelector.from("namespace", "name"); + ResourceId tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: "namespace", name: "name" }); world.registerTable( - resourceSelector, + tableId, Bool.getFieldLayout(), defaultKeySchema, Bool.getValueSchema(), @@ -500,18 +626,44 @@ contract WorldTest is Test, GasReporter { // Deploy a new system System system = new System(); - // Expect an error when trying to register a system at the same selector - vm.expectRevert(abi.encodeWithSelector(IWorldErrors.ResourceExists.selector, resourceSelector.toString())); - world.registerSystem(resourceSelector, system, false); + // Expect an error when trying to register a system at the same ID + vm.expectRevert( + abi.encodeWithSelector(IWorldErrors.InvalidResourceType.selector, RESOURCE_SYSTEM, tableId, tableId.toString()) + ); + world.registerSystem(tableId, system, false); // Register a new system - bytes32 resourceSelector2 = ResourceSelector.from("namespace2", "name"); - world.registerSystem(resourceSelector2, new System(), false); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "namespace2", name: "name" }); + world.registerSystem(systemId, new System(), false); + + // Expect an error when trying to register a table at the same ID + vm.expectRevert( + abi.encodeWithSelector( + IStoreErrors.StoreCore_InvalidResourceType.selector, + RESOURCE_TABLE, + systemId, + string(abi.encodePacked(systemId)) + ) + ); + world.registerTable( + systemId, + Bool.getFieldLayout(), + defaultKeySchema, + Bool.getValueSchema(), + new string[](1), + new string[](1) + ); - // Expect an error when trying to register a table at the same selector - vm.expectRevert(abi.encodeWithSelector(IWorldErrors.ResourceExists.selector, resourceSelector2.toString())); + // Expect an error when trying to register a new table at an existing table ID + vm.expectRevert( + abi.encodeWithSelector( + IStoreErrors.StoreCore_TableAlreadyExists.selector, + ResourceId.unwrap(tableId), + string(bytes.concat(ResourceId.unwrap(tableId))) + ) + ); world.registerTable( - resourceSelector2, + tableId, Bool.getFieldLayout(), defaultKeySchema, Bool.getValueSchema(), @@ -529,7 +681,11 @@ contract WorldTest is Test, GasReporter { } function testSetRecord() public { - bytes32 tableId = ResourceSelector.from("testSetRecord", "testTable"); + ResourceId tableId = WorldResourceIdLib.encode({ + typeId: RESOURCE_TABLE, + namespace: "testSetRecord", + name: "testTable" + }); // Register a new table world.registerTable( tableId, @@ -548,7 +704,7 @@ contract WorldTest is Test, GasReporter { assertTrue(Bool.get(world, tableId)); // Expect an error when trying to write from an address that doesn't have access - _expectAccessDenied(address(0x01), "testSetRecord", "testTable"); + _expectAccessDenied(address(0x01), "testSetRecord", "testTable", RESOURCE_TABLE); Bool.set(world, tableId, true); // Expect the World to have access @@ -557,9 +713,9 @@ contract WorldTest is Test, GasReporter { } function testSetField() public { - bytes16 namespace = "testSetField"; + bytes14 namespace = "testSetField"; bytes16 name = "testTable"; - bytes32 tableId = ResourceSelector.from(namespace, name); + ResourceId tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: name }); FieldLayout fieldLayout = Bool.getFieldLayout(); Schema valueSchema = Bool.getValueSchema(); @@ -574,7 +730,7 @@ contract WorldTest is Test, GasReporter { assertTrue(Bool.get(world, tableId)); // Expect an error when trying to write from an address that doesn't have access - _expectAccessDenied(address(0x01), "testSetField", "testTable"); + _expectAccessDenied(address(0x01), "testSetField", "testTable", RESOURCE_TABLE); world.setField(tableId, singletonKey, 0, abi.encodePacked(true), fieldLayout); // Expect the World to have access @@ -583,9 +739,9 @@ contract WorldTest is Test, GasReporter { } function testPushToField() public { - bytes16 namespace = "testPushToField"; + bytes14 namespace = "testPushField"; bytes16 name = "testTable"; - bytes32 tableId = ResourceSelector.from(namespace, name); + ResourceId tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: name }); FieldLayout fieldLayout = AddressArray.getFieldLayout(); Schema valueSchema = AddressArray.getValueSchema(); @@ -616,7 +772,7 @@ contract WorldTest is Test, GasReporter { assertEq(AddressArray.get(world, tableId, key), dataToPush); // Expect an error when trying to write from an address that doesn't have access - _expectAccessDenied(address(0x01), namespace, name); + _expectAccessDenied(address(0x01), namespace, name, RESOURCE_TABLE); world.pushToField(tableId, keyTuple, 0, encodedData, fieldLayout); // Expect the World to have access @@ -625,9 +781,9 @@ contract WorldTest is Test, GasReporter { } function testDeleteRecord() public { - bytes16 namespace = "testDeleteRecord"; + bytes14 namespace = "testDeleteReco"; bytes16 name = "testTable"; - bytes32 tableId = ResourceSelector.from(namespace, name); + ResourceId tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: name }); FieldLayout fieldLayout = Bool.getFieldLayout(); Schema valueSchema = Bool.getValueSchema(); @@ -665,7 +821,7 @@ contract WorldTest is Test, GasReporter { assertTrue(Bool.get(world, tableId)); // Expect an error when trying to delete from an address that doesn't have access - _expectAccessDenied(address(0x02), "testDeleteRecord", "testTable"); + _expectAccessDenied(address(0x02), namespace, name, RESOURCE_TABLE); world.deleteRecord(tableId, singletonKey, fieldLayout); // Expect the World to have access @@ -676,19 +832,23 @@ contract WorldTest is Test, GasReporter { function testCall() public { // Register a new system WorldTestSystem system = new WorldTestSystem(); - bytes32 resourceSelector = ResourceSelector.from("namespace", "testSystem"); - world.registerSystem(resourceSelector, system, false); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testSystem" + }); + world.registerSystem(systemId, system, false); // Call a system function without arguments via the World startGasReport("call a system via the World"); - bytes memory result = world.call(resourceSelector, abi.encodeCall(WorldTestSystem.msgSender, ())); + bytes memory result = world.call(systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); endGasReport(); // Expect the system to have received the caller's address assertEq(address(uint160(uint256(bytes32(result)))), address(this)); // Call a system function with arguments via the World - result = world.call(resourceSelector, abi.encodeCall(WorldTestSystem.echo, (bytes32(uint256(0x123))))); + result = world.call(systemId, abi.encodeCall(WorldTestSystem.echo, (bytes32(uint256(0x123))))); // Expect the return data to be decodeable as a tuple (address returnedAddress, bytes32 returnedBytes32) = abi.decode(result, (address, bytes32)); @@ -701,33 +861,34 @@ contract WorldTest is Test, GasReporter { assertEq(returnStruct.input, bytes32(uint256(0x123))); // Expect an error when trying to call a private system from an address that doesn't have access - _expectAccessDenied(address(0x01), "namespace", "testSystem"); - world.call(resourceSelector, abi.encodeCall(WorldTestSystem.msgSender, ())); + _expectAccessDenied(address(0x01), "namespace", "testSystem", RESOURCE_SYSTEM); + world.call(systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); // Expect the World to have access vm.prank(address(world)); - world.call(resourceSelector, abi.encodeCall(WorldTestSystem.msgSender, ())); + world.call(systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); // Expect errors from the system to be forwarded vm.expectRevert(abi.encodeWithSelector(WorldTestSystem.WorldTestSystemError.selector, "test error")); - world.call(resourceSelector, abi.encodeCall(WorldTestSystem.err, ("test error"))); + world.call(systemId, abi.encodeCall(WorldTestSystem.err, ("test error"))); // Register another system in the same namespace WorldTestSystem subSystem = new WorldTestSystem(); - bytes32 subsystemResourceSelector = ResourceSelector.from("namespace", "testSubSystem"); - world.registerSystem(subsystemResourceSelector, subSystem, false); + ResourceId subsystemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testSubSystem" + }); + world.registerSystem(subsystemId, subSystem, false); // Call the subsystem via the World (with access to the base route) - returnedAddress = abi.decode( - world.call(subsystemResourceSelector, abi.encodeCall(WorldTestSystem.msgSender, ())), - (address) - ); + returnedAddress = abi.decode(world.call(subsystemId, abi.encodeCall(WorldTestSystem.msgSender, ())), (address)); assertEq(returnedAddress, address(this)); // Call the subsystem via delegatecall from the system // (Note: just for testing purposes, in reality systems can call subsystems directly instead of via two indirections like here) bytes memory nestedReturndata = world.call( - resourceSelector, + systemId, abi.encodeCall( WorldTestSystem.delegateCallSubSystem, // Function in system ( @@ -748,14 +909,18 @@ contract WorldTest is Test, GasReporter { function testCallFromSelf() public { // Register a new system WorldTestSystem system = new WorldTestSystem(); - bytes32 resourceSelector = ResourceSelector.from("namespace", "testSystem"); - world.registerSystem(resourceSelector, system, true); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testSystem" + }); + world.registerSystem(systemId, system, true); address caller = address(1); // Call a system via callFrom with the own address vm.prank(caller); - bytes memory returnData = world.callFrom(caller, resourceSelector, abi.encodeCall(WorldTestSystem.msgSender, ())); + bytes memory returnData = world.callFrom(caller, systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); address returnedAddress = abi.decode(returnData, (address)); // Expect the system to have received the delegator's address @@ -765,8 +930,12 @@ contract WorldTest is Test, GasReporter { function testCallFromUnlimitedDelegation() public { // Register a new system WorldTestSystem system = new WorldTestSystem(); - bytes32 resourceSelector = ResourceSelector.from("namespace", "testSystem"); - world.registerSystem(resourceSelector, system, true); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testSystem" + }); + world.registerSystem(systemId, system, true); // Register an unlimited delegation address delegator = address(1); @@ -779,11 +948,7 @@ contract WorldTest is Test, GasReporter { // Call a system from the delegatee on behalf of the delegator vm.prank(delegatee); startGasReport("call a system via an unlimited delegation"); - bytes memory returnData = world.callFrom( - delegator, - resourceSelector, - abi.encodeCall(WorldTestSystem.msgSender, ()) - ); + bytes memory returnData = world.callFrom(delegator, systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); endGasReport(); address returnedAddress = abi.decode(returnData, (address)); @@ -794,8 +959,12 @@ contract WorldTest is Test, GasReporter { function testCallFromFailDelegationNotFound() public { // Register a new system WorldTestSystem system = new WorldTestSystem(); - bytes32 resourceSelector = ResourceSelector.from("namespace", "testSystem"); - world.registerSystem(resourceSelector, system, true); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testSystem" + }); + world.registerSystem(systemId, system, true); // Expect a revert when attempting to perform a call on behalf of an address that doesn't have a delegation vm.expectRevert( @@ -806,14 +975,18 @@ contract WorldTest is Test, GasReporter { ) ); vm.prank(address(1)); - world.callFrom(address(2), resourceSelector, abi.encodeCall(WorldTestSystem.msgSender, ())); + world.callFrom(address(2), systemId, abi.encodeCall(WorldTestSystem.msgSender, ())); } function testCallFromLimitedDelegation() public { // Register a new system WorldTestSystem system = new WorldTestSystem(); - bytes32 resourceSelector = ResourceSelector.from("namespace", "testSystem"); - world.registerSystem(resourceSelector, system, true); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testSystem" + }); + world.registerSystem(systemId, system, true); // Register a limited delegation address delegator = address(1); @@ -825,7 +998,7 @@ contract WorldTest is Test, GasReporter { function testRegisterStoreHook() public { FieldLayout fieldLayout = Bool.getFieldLayout(); Schema valueSchema = Bool.getValueSchema(); - bytes32 tableId = ResourceSelector.from("", "testTable"); + ResourceId tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: "", name: "testTable" }); // Register a new table world.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](1)); @@ -898,7 +1071,7 @@ contract WorldTest is Test, GasReporter { function testUnregisterStoreHook() public { FieldLayout fieldLayout = Bool.getFieldLayout(); Schema valueSchema = Bool.getValueSchema(); - bytes32 tableId = ResourceSelector.from("", "testTable"); + ResourceId tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: "", name: "testTable" }); // Register a new table world.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](1)); @@ -977,11 +1150,15 @@ contract WorldTest is Test, GasReporter { } function testRegisterSystemHook() public { - bytes32 systemId = ResourceSelector.from("namespace", "testTable"); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testSystem" + }); // Register a new system WorldTestSystem system = new WorldTestSystem(); - world.registerSystem(systemId, system, false); + world.registerSystem(systemId, system, true); // Expect the registration to fail if the contract does not implement the system hook interface vm.expectRevert( @@ -1014,7 +1191,11 @@ contract WorldTest is Test, GasReporter { } function testUnregisterSystemHook() public { - bytes32 systemId = ResourceSelector.from("namespace", "testTable"); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testTable" + }); // Register a new system WorldTestSystem system = new WorldTestSystem(); @@ -1052,7 +1233,11 @@ contract WorldTest is Test, GasReporter { } function testWriteRootSystem() public { - bytes32 tableId = ResourceSelector.from("namespace", "testTable"); + ResourceId tableId = WorldResourceIdLib.encode({ + typeId: RESOURCE_TABLE, + namespace: "namespace", + name: "testTable" + }); // Register a new table world.registerTable( tableId, @@ -1064,22 +1249,23 @@ contract WorldTest is Test, GasReporter { ); // Register a new system - bytes32 rootSystemId = ResourceSelector.from("", "testSystem"); + ResourceId rootSystemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "", name: "testSystem" }); WorldTestSystem system = new WorldTestSystem(); world.registerSystem(rootSystemId, system, false); // Call a system function that writes data to the World - world.call( - rootSystemId, - abi.encodeCall(WorldTestSystem.writeData, (bytes16("namespace"), bytes16("testTable"), true)) - ); + world.call(rootSystemId, abi.encodeCall(WorldTestSystem.writeData, ("namespace", "testTable", true))); // Expect the data to be written assertTrue(Bool.get(world, tableId)); } - function testWriteAutonomousSystem() public { - bytes32 tableId = ResourceSelector.from("namespace", "testTable"); + function testWriteNonRootSystem() public { + ResourceId tableId = WorldResourceIdLib.encode({ + typeId: RESOURCE_TABLE, + namespace: "namespace", + name: "testTable" + }); // Register a new table world.registerTable( tableId, @@ -1091,52 +1277,60 @@ contract WorldTest is Test, GasReporter { ); // Register a new system - bytes32 systemId = ResourceSelector.from("namespace", "testSystem"); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testSystem" + }); WorldTestSystem system = new WorldTestSystem(); world.registerSystem(systemId, system, false); // Call a system function that writes data to the World - world.call(systemId, abi.encodeCall(WorldTestSystem.writeData, (bytes16("namespace"), bytes16("testTable"), true))); + world.call(systemId, abi.encodeCall(WorldTestSystem.writeData, ("namespace", "testTable", true))); // Expect the data to be written assertTrue(Bool.get(world, tableId)); } function testDelegatecallRootSystem() public { - bytes32 resourceSelector = ResourceSelector.from("", "testSystem"); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "", name: "testSystem" }); // Register a new root system WorldTestSystem system = new WorldTestSystem(); - world.registerSystem(resourceSelector, system, false); + world.registerSystem(systemId, system, false); // Call the root sysyem vm.expectEmit(true, true, true, true); emit WorldTestSystemLog("delegatecall"); - world.call(resourceSelector, abi.encodeCall(WorldTestSystem.emitCallType, ())); + world.call(systemId, abi.encodeCall(WorldTestSystem.emitCallType, ())); } function testCallAutonomousSystem() public { - bytes32 resourceSelector = ResourceSelector.from("namespace", "testSystem"); + ResourceId systemId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "testSystem" + }); // Register a new non-root system WorldTestSystem system = new WorldTestSystem(); - world.registerSystem(resourceSelector, system, false); + world.registerSystem(systemId, system, false); // Call the sysyem vm.expectEmit(true, true, true, true); emit WorldTestSystemLog("call"); - world.call(resourceSelector, abi.encodeCall(WorldTestSystem.emitCallType, ())); + world.call(systemId, abi.encodeCall(WorldTestSystem.emitCallType, ())); } function testRegisterFunctionSelector() public { - bytes16 namespace = "testNamespace"; + bytes14 namespace = "testNamespace"; bytes16 name = "testSystem"; - bytes32 resourceSelector = ResourceSelector.from(namespace, name); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: name }); // Register a new system WorldTestSystem system = new WorldTestSystem(); - world.registerSystem(resourceSelector, system, true); + world.registerSystem(systemId, system, true); startGasReport("Register a function selector"); - bytes4 functionSelector = world.registerFunctionSelector(resourceSelector, "msgSender", "()"); + bytes4 functionSelector = world.registerFunctionSelector(systemId, "msgSender", "()"); endGasReport(); string memory expectedWorldFunctionSignature = "testNamespace_testSystem_msgSender()"; @@ -1150,7 +1344,7 @@ contract WorldTest is Test, GasReporter { assertEq(abi.decode(data, (address)), address(this), "wrong address returned"); // Register a function selector to the error function - functionSelector = world.registerFunctionSelector(resourceSelector, "err", "(string)"); + functionSelector = world.registerFunctionSelector(systemId, "err", "(string)"); // Expect errors to be passed through vm.expectRevert(abi.encodeWithSelector(WorldTestSystem.WorldTestSystemError.selector, "test error")); @@ -1158,27 +1352,27 @@ contract WorldTest is Test, GasReporter { } function testRegisterRootFunctionSelector() public { - bytes16 namespace = "testNamespace"; + bytes14 namespace = "testNamespace"; bytes16 name = "testSystem"; - bytes32 resourceSelector = ResourceSelector.from(namespace, name); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: name }); // Register a new system WorldTestSystem system = new WorldTestSystem(); - world.registerSystem(resourceSelector, system, true); + world.registerSystem(systemId, system, true); bytes4 worldFunc = bytes4(abi.encodeWithSignature("testSelector()")); bytes4 sysFunc = WorldTestSystem.msgSender.selector; // Expect an error when trying to register a root function selector from an account without access - _expectAccessDenied(address(0x01), "", ""); - world.registerRootFunctionSelector(resourceSelector, worldFunc, sysFunc); + _expectAccessDenied(address(0x01), "", "", RESOURCE_NAMESPACE); + world.registerRootFunctionSelector(systemId, worldFunc, sysFunc); // Expect the World to not be able to register a root function selector when calling the function externally - _expectAccessDenied(address(world), "", ""); - world.registerRootFunctionSelector(resourceSelector, "smth", "smth"); + _expectAccessDenied(address(world), "", "", RESOURCE_NAMESPACE); + world.registerRootFunctionSelector(systemId, "smth", "smth"); startGasReport("Register a root function selector"); - bytes4 functionSelector = world.registerRootFunctionSelector(resourceSelector, worldFunc, sysFunc); + bytes4 functionSelector = world.registerRootFunctionSelector(systemId, worldFunc, sysFunc); endGasReport(); assertEq(functionSelector, worldFunc, "wrong function selector returned"); @@ -1191,7 +1385,7 @@ contract WorldTest is Test, GasReporter { // Register a function selector to the error function functionSelector = world.registerRootFunctionSelector( - resourceSelector, + systemId, WorldTestSystem.err.selector, WorldTestSystem.err.selector ); @@ -1202,16 +1396,16 @@ contract WorldTest is Test, GasReporter { } function testRegisterFallbackSystem() public { - bytes16 namespace = "testNamespace"; + bytes14 namespace = "testNamespace"; bytes16 name = "testSystem"; - bytes32 resourceSelector = ResourceSelector.from(namespace, name); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: name }); // Register a new system WorldTestSystem system = new WorldTestSystem(); - world.registerSystem(resourceSelector, system, true); + world.registerSystem(systemId, system, true); startGasReport("Register a fallback system"); - bytes4 funcSelector1 = world.registerFunctionSelector(resourceSelector, "", ""); + bytes4 funcSelector1 = world.registerFunctionSelector(systemId, "", ""); endGasReport(); // Call the system's fallback function @@ -1223,7 +1417,7 @@ contract WorldTest is Test, GasReporter { bytes4 worldFunc = bytes4(abi.encodeWithSignature("testSelector()")); startGasReport("Register a root fallback system"); - bytes4 funcSelector2 = world.registerRootFunctionSelector(resourceSelector, worldFunc, 0); + bytes4 funcSelector2 = world.registerRootFunctionSelector(systemId, worldFunc, 0); endGasReport(); assertEq(funcSelector2, worldFunc, "wrong function selector returned"); @@ -1259,13 +1453,13 @@ contract WorldTest is Test, GasReporter { function testPayableSystem() public { // Register a root system with a payable function in the world WorldTestSystem system = new WorldTestSystem(); - bytes16 namespace = "noroot"; + bytes14 namespace = "noroot"; bytes16 name = "testSystem"; - bytes32 resourceSelector = ResourceSelector.from(namespace, name); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: name }); - world.registerSystem(resourceSelector, system, true); + world.registerSystem(systemId, system, true); world.registerRootFunctionSelector( - resourceSelector, + systemId, WorldTestSystem.receiveEther.selector, WorldTestSystem.receiveEther.selector ); @@ -1290,12 +1484,12 @@ contract WorldTest is Test, GasReporter { function testNonPayableSystem() public { // Register a non-root system with a non-payable function in the world WorldTestSystem system = new WorldTestSystem(); - bytes16 namespace = "noroot"; + bytes14 namespace = "noroot"; bytes16 name = "testSystem"; - bytes32 resourceSelector = ResourceSelector.from(namespace, name); - world.registerSystem(resourceSelector, system, true); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: name }); + world.registerSystem(systemId, system, true); world.registerRootFunctionSelector( - resourceSelector, + systemId, WorldTestSystem.msgSender.selector, WorldTestSystem.msgSender.selector ); @@ -1321,15 +1515,11 @@ contract WorldTest is Test, GasReporter { function testNonPayableFallbackSystem() public { // Register a root system with a non-payable function in the world WorldTestSystem system = new WorldTestSystem(); - bytes16 namespace = ROOT_NAMESPACE; + bytes14 namespace = ROOT_NAMESPACE; bytes16 name = "testSystem"; - bytes32 resourceSelector = ResourceSelector.from(namespace, name); - world.registerSystem(resourceSelector, system, true); - world.registerRootFunctionSelector( - resourceSelector, - bytes4(abi.encodeWithSignature("systemFallback()")), - bytes4("") - ); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: name }); + world.registerSystem(systemId, system, true); + world.registerRootFunctionSelector(systemId, bytes4(abi.encodeWithSignature("systemFallback()")), bytes4("")); // create new funded address and impersonate address alice = makeAddr("alice"); @@ -1351,15 +1541,11 @@ contract WorldTest is Test, GasReporter { function testPayableFallbackSystem() public { // Register a root system with a payable function in the world PayableFallbackSystem system = new PayableFallbackSystem(); - bytes16 namespace = ROOT_NAMESPACE; + bytes14 namespace = ROOT_NAMESPACE; bytes16 name = "testSystem"; - bytes32 resourceSelector = ResourceSelector.from(namespace, name); - world.registerSystem(resourceSelector, system, true); - world.registerRootFunctionSelector( - resourceSelector, - bytes4(abi.encodeWithSignature("systemFallback()")), - bytes4("") - ); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: name }); + world.registerSystem(systemId, system, true); + world.registerRootFunctionSelector(systemId, bytes4(abi.encodeWithSignature("systemFallback()")), bytes4("")); // create new funded address and impersonate address alice = makeAddr("alice"); @@ -1381,12 +1567,12 @@ contract WorldTest is Test, GasReporter { function testPayableRootSystem() public { // Register a root system with a payable function in the world WorldTestSystem system = new WorldTestSystem(); - bytes16 namespace = ROOT_NAMESPACE; + bytes14 namespace = ROOT_NAMESPACE; bytes16 name = "testSystem"; - bytes32 resourceSelector = ResourceSelector.from(namespace, name); - world.registerSystem(resourceSelector, system, true); + ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: name }); + world.registerSystem(systemId, system, true); world.registerRootFunctionSelector( - resourceSelector, + systemId, WorldTestSystem.receiveEther.selector, WorldTestSystem.receiveEther.selector ); diff --git a/packages/world/test/WorldBalance.t.sol b/packages/world/test/WorldBalance.t.sol index f7225afde6..4f3df02a0f 100644 --- a/packages/world/test/WorldBalance.t.sol +++ b/packages/world/test/WorldBalance.t.sol @@ -6,13 +6,14 @@ import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { World } from "../src/World.sol"; import { System } from "../src/System.sol"; import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; -import { ResourceSelector } from "../src/ResourceSelector.sol"; -import { ROOT_NAMESPACE } from "../src/constants.sol"; +import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../src/WorldResourceId.sol"; +import { ROOT_NAMESPACE, ROOT_NAMESPACE_ID } from "../src/constants.sol"; import { CoreModule } from "../src/modules/core/CoreModule.sol"; import { Balances } from "../src/modules/core/tables/Balances.sol"; import { IWorldErrors } from "../src/interfaces/IWorldErrors.sol"; +import { RESOURCE_SYSTEM, RESOURCE_NAMESPACE } from "../src/worldResourceTypes.sol"; -using ResourceSelector for bytes32; +using WorldResourceIdInstance for ResourceId; contract WorldBalanceTestSystem is System { function echoValue() public payable returns (uint256) { @@ -24,9 +25,12 @@ contract WorldBalanceTest is Test, GasReporter { IBaseWorld public world; WorldBalanceTestSystem public rootSystem = new WorldBalanceTestSystem(); WorldBalanceTestSystem public nonRootSystem = new WorldBalanceTestSystem(); - bytes16 public namespace = "namespace"; - bytes32 public rootSystemId = ResourceSelector.from(ROOT_NAMESPACE, "testSystem"); - bytes32 public nonRootSystemId = ResourceSelector.from(namespace, "testSystem"); + bytes14 public namespace = "namespace"; + ResourceId public namespaceId = WorldResourceIdLib.encodeNamespace(namespace); + ResourceId public rootSystemId = + WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: ROOT_NAMESPACE, name: "testSystem" }); + ResourceId public nonRootSystemId = + WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: namespace, name: "testSystem" }); address public caller = address(4242); function setUp() public { @@ -43,8 +47,8 @@ contract WorldBalanceTest is Test, GasReporter { uint256 value = 1 ether; // Expect the root and non root namespaces to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); // Call a function on the root system with value via call vm.deal(caller, value); @@ -53,7 +57,7 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(abi.decode(data, (uint256)), value); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Call a function on a non-root system with value via call vm.deal(caller, value); @@ -62,18 +66,18 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(abi.decode(data, (uint256)), value); // Expect the non root namespace to have the value as balance - assertEq(Balances.get(world, namespace), value); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), value); // Expect the root namespace to still have the same balance as before - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); } function testCallFromWithValue() public { uint256 value = 1 ether; // Expect the root and non root namespaces to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); // Call a function on the root system with value via callFrom vm.deal(caller, value); @@ -82,7 +86,7 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(abi.decode(data, (uint256)), value); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Call a function on a non-root system with value via callFrom vm.deal(caller, value); @@ -91,18 +95,18 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(abi.decode(data, (uint256)), value); // Expect the non root namespace to have the value as balance - assertEq(Balances.get(world, namespace), value); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), value); // Expect the root namespace to still have the same balance as before - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); } function testFallbackWithValue() public { uint256 value = 1 ether; // Expect the root and non root namespaces to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); // Call a function on the root system with value via the registered root function selector vm.deal(caller, value); @@ -112,7 +116,7 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(abi.decode(data, (uint256)), value); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Call a function on a non-root system with value vm.deal(caller, value); @@ -122,17 +126,17 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(abi.decode(data, (uint256)), value); // Expect the non root namespace to have the value as balance - assertEq(Balances.get(world, namespace), value); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), value); // Expect the root namespace to still have the same balance as before - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); } function testReceiveWithValue() public { uint256 value = 1 ether; // Expect the root to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); // Send value to the world without calldata vm.deal(caller, value); @@ -142,15 +146,15 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(data.length, 0); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); } function testTransferBalanceToNamespace() public { uint256 value = 1 ether; // Expect the root and non root namespaces to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); // Send balance to root namespace vm.deal(caller, value); @@ -160,24 +164,24 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(data.length, 0); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Transfer the balance to another namespace - world.transferBalanceToNamespace(ROOT_NAMESPACE, namespace, value); + world.transferBalanceToNamespace(ROOT_NAMESPACE_ID, namespaceId, value); // Expect the root namespace to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); // Expect the non root namespace to have the value as balance - assertEq(Balances.get(world, namespace), value); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), value); } function testTransferBalanceToNamespaceRevertInsufficientBalance() public { uint256 value = 1 ether; // Expect the root and non root namespaces to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); // Send balance to root namespace vm.deal(caller, value); @@ -187,25 +191,25 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(data.length, 0); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Expect revert when attempting to transfer more than the balance vm.expectRevert(abi.encodeWithSelector(IWorldErrors.InsufficientBalance.selector, value, value + 1)); - world.transferBalanceToNamespace(ROOT_NAMESPACE, namespace, value + 1); + world.transferBalanceToNamespace(ROOT_NAMESPACE_ID, namespaceId, value + 1); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Expect the non root namespace to have no balance - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); } function testTransferBalanceToNamespaceRevertAccessDenied() public { uint256 value = 1 ether; // Expect the root and non root namespaces to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); // Send balance to root namespace vm.deal(caller, value); @@ -215,32 +219,62 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(data.length, 0); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Expect revert when attempting to transfer from a namespace without access vm.prank(caller); + vm.expectRevert(abi.encodeWithSelector(IWorldErrors.AccessDenied.selector, ROOT_NAMESPACE_ID.toString(), caller)); + world.transferBalanceToNamespace(ROOT_NAMESPACE_ID, namespaceId, value); + + // Expect the root namespace to have the value as balance + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); + + // Expect the non root namespace to have no balance + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); + } + + function testTransferBalanceToNamespaceRevertInvalidResourceType() public { + uint256 value = 1 ether; + + // Expect the root namespace to have no balance + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); + + // Send balance to root namespace + vm.deal(caller, value); + vm.prank(caller); + (bool success, bytes memory data) = address(world).call{ value: value }(""); + assertTrue(success); + assertEq(data.length, 0); + + // Expect the root namespace to have the value as balance + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); + + // Expect revert when attempting to transfer to an invalid namespace + ResourceId invalidNamespace = WorldResourceIdLib.encode({ typeId: "xx", namespace: "something", name: "invalid" }); + vm.prank(caller); vm.expectRevert( abi.encodeWithSelector( - IWorldErrors.AccessDenied.selector, - ResourceSelector.from(ROOT_NAMESPACE).toString(), - caller + IWorldErrors.InvalidResourceType.selector, + RESOURCE_NAMESPACE, + invalidNamespace, + invalidNamespace.toString() ) ); - world.transferBalanceToNamespace(ROOT_NAMESPACE, namespace, value); + world.transferBalanceToNamespace(ROOT_NAMESPACE_ID, invalidNamespace, value); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Expect the non root namespace to have no balance - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(invalidNamespace)), 0); } function testTransferBalanceToAddress() public { uint256 value = 1 ether; // Expect the root and non root namespaces to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); // Send balance to root namespace vm.deal(caller, value); @@ -250,17 +284,17 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(data.length, 0); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Expect the receiver to not have any balance address receiver = address(1234); assertEq(receiver.balance, 0); // Transfer the balance to the receiver - world.transferBalanceToAddress(ROOT_NAMESPACE, receiver, value); + world.transferBalanceToAddress(ROOT_NAMESPACE_ID, receiver, value); // Expect the root namespace to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); // Expect the receiver to have value as balance assertEq(receiver.balance, value); @@ -270,8 +304,8 @@ contract WorldBalanceTest is Test, GasReporter { uint256 value = 1 ether; // Expect the root and non root namespaces to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); // Send balance to root namespace vm.deal(caller, value); @@ -281,7 +315,7 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(data.length, 0); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Expect the receiver to not have any balance address receiver = address(1234); @@ -289,10 +323,10 @@ contract WorldBalanceTest is Test, GasReporter { // Expect revert when attempting to transfer more than the balance vm.expectRevert(abi.encodeWithSelector(IWorldErrors.InsufficientBalance.selector, value, value + 1)); - world.transferBalanceToAddress(ROOT_NAMESPACE, receiver, value + 1); + world.transferBalanceToAddress(ROOT_NAMESPACE_ID, receiver, value + 1); // Expect the root namespace to have value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Expect the receiver to have no balance assertEq(receiver.balance, 0); @@ -302,8 +336,8 @@ contract WorldBalanceTest is Test, GasReporter { uint256 value = 1 ether; // Expect the root and non root namespaces to have no balance - assertEq(Balances.get(world, ROOT_NAMESPACE), 0); - assertEq(Balances.get(world, namespace), 0); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), 0); + assertEq(Balances.get(world, ResourceId.unwrap(namespaceId)), 0); // Send balance to root namespace vm.deal(caller, value); @@ -313,7 +347,7 @@ contract WorldBalanceTest is Test, GasReporter { assertEq(data.length, 0); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Expect the receiver to not have any balance address receiver = address(1234); @@ -324,14 +358,14 @@ contract WorldBalanceTest is Test, GasReporter { vm.expectRevert( abi.encodeWithSelector( IWorldErrors.AccessDenied.selector, - ResourceSelector.from(ROOT_NAMESPACE).toString(), + WorldResourceIdLib.encodeNamespace(ROOT_NAMESPACE).toString(), caller ) ); - world.transferBalanceToAddress(ROOT_NAMESPACE, receiver, value); + world.transferBalanceToAddress(ROOT_NAMESPACE_ID, receiver, value); // Expect the root namespace to have the value as balance - assertEq(Balances.get(world, ROOT_NAMESPACE), value); + assertEq(Balances.get(world, ResourceId.unwrap(ROOT_NAMESPACE_ID)), value); // Expect the receiver to have no balance assertEq(receiver.balance, 0); diff --git a/packages/world/test/WorldDynamicUpdate.t.sol b/packages/world/test/WorldDynamicUpdate.t.sol index e2bea13264..409495592a 100644 --- a/packages/world/test/WorldDynamicUpdate.t.sol +++ b/packages/world/test/WorldDynamicUpdate.t.sol @@ -16,10 +16,9 @@ import { SchemaEncodeHelper } from "@latticexyz/store/test/SchemaEncodeHelper.so import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { World } from "../src/World.sol"; -import { ResourceSelector } from "../src/ResourceSelector.sol"; +import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../src/WorldResourceId.sol"; +import { RESOURCE_TABLE } from "../src/worldResourceTypes.sol"; -import { NamespaceOwner } from "../src/tables/NamespaceOwner.sol"; -import { ResourceAccess } from "../src/tables/ResourceAccess.sol"; import { AddressArray } from "./tables/AddressArray.sol"; import { CoreModule } from "../src/modules/core/CoreModule.sol"; @@ -28,7 +27,7 @@ import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; import { IWorldErrors } from "../src/interfaces/IWorldErrors.sol"; contract UpdateInFieldTest is Test, GasReporter { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; event HookCalled(bytes data); event WorldTestSystemLog(string log); @@ -40,9 +39,9 @@ contract UpdateInFieldTest is Test, GasReporter { bytes32[] internal keyTuple; bytes32[] internal singletonKey; - bytes16 namespace; + bytes14 namespace; bytes16 name; - bytes32 internal tableId; + ResourceId internal tableId; address[] internal initData; bytes internal encodedData; @@ -61,7 +60,7 @@ contract UpdateInFieldTest is Test, GasReporter { namespace = "DynamicUpdTest"; name = "testTable"; - tableId = ResourceSelector.from(namespace, name); + tableId = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: name }); // Register a new table world.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](1)); @@ -77,7 +76,7 @@ contract UpdateInFieldTest is Test, GasReporter { } // Expect an error when trying to write from an address that doesn't have access - function _expectAccessDenied(address _caller, bytes32 _tableId) internal { + function _expectAccessDenied(address _caller, ResourceId _tableId) internal { vm.prank(_caller); vm.expectRevert(abi.encodeWithSelector(IWorldErrors.AccessDenied.selector, _tableId.toString(), _caller)); } diff --git a/packages/world/test/WorldResourceId.t.sol b/packages/world/test/WorldResourceId.t.sol new file mode 100644 index 0000000000..e249e75c9f --- /dev/null +++ b/packages/world/test/WorldResourceId.t.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +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 { RESOURCE_SYSTEM } from "../src/worldResourceTypes.sol"; + +contract WorldResourceIdTest is Test, GasReporter { + using ResourceIdInstance for ResourceId; + using WorldResourceIdInstance for ResourceId; + + function testEncode() public { + ResourceId resourceId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "name" + }); + + assertEq( + ResourceId.unwrap(resourceId), + bytes32(abi.encodePacked(RESOURCE_SYSTEM, bytes14("namespace"), bytes16("name"))) + ); + } + + function testGetNamespace() public { + ResourceId resourceId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "name" + }); + + startGasReport("encode namespace, name and type"); + bytes14 namespace = resourceId.getNamespace(); + endGasReport(); + + assertEq(namespace, "namespace"); + } + + function testGetNamespaceId() public { + ResourceId resourceId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "name" + }); + + startGasReport("get namespace ID from a resource ID"); + ResourceId namespaceId = resourceId.getNamespaceId(); + endGasReport(); + + assertEq(ResourceId.unwrap(namespaceId), ResourceId.unwrap(WorldResourceIdLib.encodeNamespace("namespace"))); + } + + function testGetType() public { + ResourceId resourceId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "name" + }); + + startGasReport("get type from a resource ID"); + bytes2 resourceType = resourceId.getType(); + endGasReport(); + + assertEq(resourceType, RESOURCE_SYSTEM); + } + + function testMatchResourceTypeEncoding() public { + ResourceId resourceId = WorldResourceIdLib.encode({ + typeId: RESOURCE_SYSTEM, + namespace: "namespace", + name: "name" + }); + bytes30 resourceIdWithoutType = bytes30(ResourceId.unwrap(resourceId) << (TYPE_BYTES * 8)); + assertEq( + ResourceId.unwrap(resourceId), + ResourceId.unwrap(ResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, name: resourceIdWithoutType })) + ); + } + + function testMatchingByteSizes() public { + assertEq(NAMESPACE_BYTES + NAME_BYTES + TYPE_BYTES, 32); + } + + function testFuzz(bytes14 namespace, bytes16 name, bytes2 resourceType) public { + bytes2 NOT_TYPE = bytes2("xx"); + vm.assume(resourceType != NOT_TYPE); + ResourceId resourceId = WorldResourceIdLib.encode({ typeId: resourceType, namespace: namespace, name: name }); + assertEq(resourceId.getNamespace(), namespace); + assertEq( + ResourceId.unwrap(resourceId.getNamespaceId()), + ResourceId.unwrap(WorldResourceIdLib.encodeNamespace(namespace)) + ); + assertEq(resourceId.getNamespaceId().getNamespace(), namespace); + assertEq(resourceId.getName(), name); + assertEq(resourceId.getType(), resourceType); + } +} diff --git a/packages/world/test/query.t.sol b/packages/world/test/query.t.sol index 27f8621b9a..fd2fa7873d 100644 --- a/packages/world/test/query.t.sol +++ b/packages/world/test/query.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import { Test } from "forge-std/Test.sol"; +import { Test, console } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; @@ -13,8 +13,9 @@ import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol" import { World } from "../src/World.sol"; import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; -import { ResourceSelector } from "../src/ResourceSelector.sol"; +import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../src/WorldResourceId.sol"; import { ROOT_NAMESPACE } from "../src/constants.sol"; +import { RESOURCE_TABLE } from "../src/worldResourceTypes.sol"; import { CoreModule } from "../src/modules/core/CoreModule.sol"; import { KeysInTableModule } from "../src/modules/keysintable/KeysInTableModule.sol"; @@ -22,12 +23,12 @@ import { KeysWithValueModule } from "../src/modules/keyswithvalue/KeysWithValueM import { query, QueryFragment, QueryType } from "../src/modules/keysintable/query.sol"; contract QueryTest is Test, GasReporter { - using ResourceSelector for bytes32; + using WorldResourceIdInstance for ResourceId; IBaseWorld private world; KeysInTableModule private keysInTableModule = new KeysInTableModule(); // Modules can be deployed once and installed multiple times KeysWithValueModule private keysWithValueModule = new KeysWithValueModule(); - bytes16 private namespace = ROOT_NAMESPACE; + bytes14 private namespace = ROOT_NAMESPACE; bytes16 private name1 = bytes16("source1"); bytes16 private name2 = bytes16("source2"); bytes16 private name3 = bytes16("source3"); @@ -35,9 +36,9 @@ contract QueryTest is Test, GasReporter { FieldLayout private tableFieldLayout; Schema private tableKeySchema; Schema private tableValueSchema; - bytes32 private table1 = ResourceSelector.from(namespace, name1); - bytes32 private table2 = ResourceSelector.from(namespace, name2); - bytes32 private table3 = ResourceSelector.from(namespace, name3); + ResourceId private table1 = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: name1 }); + ResourceId private table2 = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: name2 }); + ResourceId private table3 = WorldResourceIdLib.encode({ typeId: RESOURCE_TABLE, namespace: namespace, name: name3 }); uint256 private value = 1; bytes32[] private key1 = new bytes32[](1); diff --git a/packages/world/test/tables/AddressArray.sol b/packages/world/test/tables/AddressArray.sol index f702e371e4..2a0ca327d7 100644 --- a/packages/world/test/tables/AddressArray.sol +++ b/packages/world/test/tables/AddressArray.sol @@ -17,6 +17,8 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 @@ -57,22 +59,22 @@ library AddressArray { } /** Register the table with its config */ - function register(bytes32 _tableId) internal { + function register(ResourceId _tableId) internal { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config */ - function _register(bytes32 _tableId) internal { + function _register(ResourceId _tableId) internal { StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ - function register(IStore _store, bytes32 _tableId) internal { + function register(IStore _store, ResourceId _tableId) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ - function getValue(bytes32 _tableId, bytes32 key) internal view returns (address[] memory value) { + function getValue(ResourceId _tableId, bytes32 key) internal view returns (address[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -81,7 +83,7 @@ library AddressArray { } /** Get value */ - function _getValue(bytes32 _tableId, bytes32 key) internal view returns (address[] memory value) { + function _getValue(ResourceId _tableId, bytes32 key) internal view returns (address[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -90,7 +92,7 @@ library AddressArray { } /** Get value (using the specified store) */ - function getValue(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (address[] memory value) { + function getValue(IStore _store, ResourceId _tableId, bytes32 key) internal view returns (address[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -99,7 +101,7 @@ library AddressArray { } /** Get value */ - function get(bytes32 _tableId, bytes32 key) internal view returns (address[] memory value) { + function get(ResourceId _tableId, bytes32 key) internal view returns (address[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -108,7 +110,7 @@ library AddressArray { } /** Get value */ - function _get(bytes32 _tableId, bytes32 key) internal view returns (address[] memory value) { + function _get(ResourceId _tableId, bytes32 key) internal view returns (address[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -117,7 +119,7 @@ library AddressArray { } /** Get value (using the specified store) */ - function get(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (address[] memory value) { + function get(IStore _store, ResourceId _tableId, bytes32 key) internal view returns (address[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -126,7 +128,7 @@ library AddressArray { } /** Set value */ - function setValue(bytes32 _tableId, bytes32 key, address[] memory value) internal { + function setValue(ResourceId _tableId, bytes32 key, address[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -134,7 +136,7 @@ library AddressArray { } /** Set value */ - function _setValue(bytes32 _tableId, bytes32 key, address[] memory value) internal { + function _setValue(ResourceId _tableId, bytes32 key, address[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -142,7 +144,7 @@ library AddressArray { } /** Set value (using the specified store) */ - function setValue(IStore _store, bytes32 _tableId, bytes32 key, address[] memory value) internal { + function setValue(IStore _store, ResourceId _tableId, bytes32 key, address[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -150,7 +152,7 @@ library AddressArray { } /** Set value */ - function set(bytes32 _tableId, bytes32 key, address[] memory value) internal { + function set(ResourceId _tableId, bytes32 key, address[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -158,7 +160,7 @@ library AddressArray { } /** Set value */ - function _set(bytes32 _tableId, bytes32 key, address[] memory value) internal { + function _set(ResourceId _tableId, bytes32 key, address[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -166,7 +168,7 @@ library AddressArray { } /** Set value (using the specified store) */ - function set(IStore _store, bytes32 _tableId, bytes32 key, address[] memory value) internal { + function set(IStore _store, ResourceId _tableId, bytes32 key, address[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -174,7 +176,7 @@ library AddressArray { } /** Get the length of value */ - function lengthValue(bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function lengthValue(ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -185,7 +187,7 @@ library AddressArray { } /** Get the length of value */ - function _lengthValue(bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function _lengthValue(ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -196,7 +198,7 @@ library AddressArray { } /** Get the length of value (using the specified store) */ - function lengthValue(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function lengthValue(IStore _store, ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -207,7 +209,7 @@ library AddressArray { } /** Get the length of value */ - function length(bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function length(ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -218,7 +220,7 @@ library AddressArray { } /** Get the length of value */ - function _length(bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function _length(ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -229,7 +231,7 @@ library AddressArray { } /** Get the length of value (using the specified store) */ - function length(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (uint256) { + function length(IStore _store, ResourceId _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -243,7 +245,7 @@ library AddressArray { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function getItemValue(bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (address) { + function getItemValue(ResourceId _tableId, bytes32 key, uint256 _index) internal view returns (address) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -264,7 +266,7 @@ library AddressArray { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function _getItemValue(bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (address) { + function _getItemValue(ResourceId _tableId, bytes32 key, uint256 _index) internal view returns (address) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -285,7 +287,12 @@ library AddressArray { * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) */ - function getItemValue(IStore _store, bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (address) { + function getItemValue( + IStore _store, + ResourceId _tableId, + bytes32 key, + uint256 _index + ) internal view returns (address) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -299,7 +306,7 @@ library AddressArray { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function getItem(bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (address) { + function getItem(ResourceId _tableId, bytes32 key, uint256 _index) internal view returns (address) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -320,7 +327,7 @@ library AddressArray { * Get an item of value * (unchecked, returns invalid data if index overflows) */ - function _getItem(bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (address) { + function _getItem(ResourceId _tableId, bytes32 key, uint256 _index) internal view returns (address) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -341,7 +348,7 @@ library AddressArray { * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) */ - function getItem(IStore _store, bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (address) { + function getItem(IStore _store, ResourceId _tableId, bytes32 key, uint256 _index) internal view returns (address) { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -352,7 +359,7 @@ library AddressArray { } /** Push an element to value */ - function pushValue(bytes32 _tableId, bytes32 key, address _element) internal { + function pushValue(ResourceId _tableId, bytes32 key, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -360,7 +367,7 @@ library AddressArray { } /** Push an element to value */ - function _pushValue(bytes32 _tableId, bytes32 key, address _element) internal { + function _pushValue(ResourceId _tableId, bytes32 key, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -368,7 +375,7 @@ library AddressArray { } /** Push an element to value (using the specified store) */ - function pushValue(IStore _store, bytes32 _tableId, bytes32 key, address _element) internal { + function pushValue(IStore _store, ResourceId _tableId, bytes32 key, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -376,7 +383,7 @@ library AddressArray { } /** Push an element to value */ - function push(bytes32 _tableId, bytes32 key, address _element) internal { + function push(ResourceId _tableId, bytes32 key, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -384,7 +391,7 @@ library AddressArray { } /** Push an element to value */ - function _push(bytes32 _tableId, bytes32 key, address _element) internal { + function _push(ResourceId _tableId, bytes32 key, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -392,7 +399,7 @@ library AddressArray { } /** Push an element to value (using the specified store) */ - function push(IStore _store, bytes32 _tableId, bytes32 key, address _element) internal { + function push(IStore _store, ResourceId _tableId, bytes32 key, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -400,7 +407,7 @@ library AddressArray { } /** Pop an element from value */ - function popValue(bytes32 _tableId, bytes32 key) internal { + function popValue(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -408,7 +415,7 @@ library AddressArray { } /** Pop an element from value */ - function _popValue(bytes32 _tableId, bytes32 key) internal { + function _popValue(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -416,7 +423,7 @@ library AddressArray { } /** Pop an element from value (using the specified store) */ - function popValue(IStore _store, bytes32 _tableId, bytes32 key) internal { + function popValue(IStore _store, ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -424,7 +431,7 @@ library AddressArray { } /** Pop an element from value */ - function pop(bytes32 _tableId, bytes32 key) internal { + function pop(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -432,7 +439,7 @@ library AddressArray { } /** Pop an element from value */ - function _pop(bytes32 _tableId, bytes32 key) internal { + function _pop(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -440,7 +447,7 @@ library AddressArray { } /** Pop an element from value (using the specified store) */ - function pop(IStore _store, bytes32 _tableId, bytes32 key) internal { + function pop(IStore _store, ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -451,7 +458,7 @@ library AddressArray { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function updateValue(bytes32 _tableId, bytes32 key, uint256 _index, address _element) internal { + function updateValue(ResourceId _tableId, bytes32 key, uint256 _index, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -464,7 +471,7 @@ library AddressArray { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function _updateValue(bytes32 _tableId, bytes32 key, uint256 _index, address _element) internal { + function _updateValue(ResourceId _tableId, bytes32 key, uint256 _index, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -477,7 +484,7 @@ library AddressArray { * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function updateValue(IStore _store, bytes32 _tableId, bytes32 key, uint256 _index, address _element) internal { + function updateValue(IStore _store, ResourceId _tableId, bytes32 key, uint256 _index, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -490,7 +497,7 @@ library AddressArray { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function update(bytes32 _tableId, bytes32 key, uint256 _index, address _element) internal { + function update(ResourceId _tableId, bytes32 key, uint256 _index, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -503,7 +510,7 @@ library AddressArray { * Update an element of value at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function _update(bytes32 _tableId, bytes32 key, uint256 _index, address _element) internal { + function _update(ResourceId _tableId, bytes32 key, uint256 _index, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -516,7 +523,7 @@ library AddressArray { * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function update(IStore _store, bytes32 _tableId, bytes32 key, uint256 _index, address _element) internal { + function update(IStore _store, ResourceId _tableId, bytes32 key, uint256 _index, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -556,7 +563,7 @@ library AddressArray { } /* Delete all data for given keys */ - function deleteRecord(bytes32 _tableId, bytes32 key) internal { + function deleteRecord(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -564,7 +571,7 @@ library AddressArray { } /* Delete all data for given keys */ - function _deleteRecord(bytes32 _tableId, bytes32 key) internal { + function _deleteRecord(ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; @@ -572,7 +579,7 @@ library AddressArray { } /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 _tableId, bytes32 key) internal { + function deleteRecord(IStore _store, ResourceId _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; diff --git a/packages/world/test/tables/Bool.sol b/packages/world/test/tables/Bool.sol index f02424ce1c..3572977787 100644 --- a/packages/world/test/tables/Bool.sol +++ b/packages/world/test/tables/Bool.sol @@ -17,6 +17,8 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0001010001000000000000000000000000000000000000000000000000000000 @@ -55,22 +57,22 @@ library Bool { } /** Register the table with its config */ - function register(bytes32 _tableId) internal { + function register(ResourceId _tableId) internal { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config */ - function _register(bytes32 _tableId) internal { + function _register(ResourceId _tableId) internal { StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ - function register(IStore _store, bytes32 _tableId) internal { + function register(IStore _store, ResourceId _tableId) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ - function getValue(bytes32 _tableId) internal view returns (bool value) { + function getValue(ResourceId _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -78,7 +80,7 @@ library Bool { } /** Get value */ - function _getValue(bytes32 _tableId) internal view returns (bool value) { + function _getValue(ResourceId _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -86,7 +88,7 @@ library Bool { } /** Get value (using the specified store) */ - function getValue(IStore _store, bytes32 _tableId) internal view returns (bool value) { + function getValue(IStore _store, ResourceId _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -94,7 +96,7 @@ library Bool { } /** Get value */ - function get(bytes32 _tableId) internal view returns (bool value) { + function get(ResourceId _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -102,7 +104,7 @@ library Bool { } /** Get value */ - function _get(bytes32 _tableId) internal view returns (bool value) { + function _get(ResourceId _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -110,7 +112,7 @@ library Bool { } /** Get value (using the specified store) */ - function get(IStore _store, bytes32 _tableId) internal view returns (bool value) { + function get(IStore _store, ResourceId _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); @@ -118,42 +120,42 @@ library Bool { } /** Set value */ - function setValue(bytes32 _tableId, bool value) internal { + function setValue(ResourceId _tableId, bool value) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value */ - function _setValue(bytes32 _tableId, bool value) internal { + function _setValue(ResourceId _tableId, bool value) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ - function setValue(IStore _store, bytes32 _tableId, bool value) internal { + function setValue(IStore _store, ResourceId _tableId, bool value) internal { bytes32[] memory _keyTuple = new bytes32[](0); _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value */ - function set(bytes32 _tableId, bool value) internal { + function set(ResourceId _tableId, bool value) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value */ - function _set(bytes32 _tableId, bool value) internal { + function _set(ResourceId _tableId, bool value) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ - function set(IStore _store, bytes32 _tableId, bool value) internal { + function set(IStore _store, ResourceId _tableId, bool value) internal { bytes32[] memory _keyTuple = new bytes32[](0); _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); @@ -182,21 +184,21 @@ library Bool { } /* Delete all data for given keys */ - function deleteRecord(bytes32 _tableId) internal { + function deleteRecord(ResourceId _tableId) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys */ - function _deleteRecord(bytes32 _tableId) internal { + function _deleteRecord(ResourceId _tableId) internal { bytes32[] memory _keyTuple = new bytes32[](0); StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 _tableId) internal { + function deleteRecord(IStore _store, ResourceId _tableId) internal { bytes32[] memory _keyTuple = new bytes32[](0); _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); diff --git a/packages/world/ts/library/config/resolveWorldConfig.ts b/packages/world/ts/library/config/resolveWorldConfig.ts index f924e4ff04..e00fbcbe17 100644 --- a/packages/world/ts/library/config/resolveWorldConfig.ts +++ b/packages/world/ts/library/config/resolveWorldConfig.ts @@ -1,4 +1,4 @@ -import { getDuplicates, STORE_SELECTOR_MAX_LENGTH, UnrecognizedSystemErrorFactory } from "@latticexyz/config"; +import { getDuplicates, STORE_NAME_MAX_LENGTH, UnrecognizedSystemErrorFactory } from "@latticexyz/config"; import { MUDError } from "@latticexyz/common/errors"; import { StoreConfig } from "@latticexyz/store"; import { SystemConfig, WorldConfig } from "./types"; @@ -64,7 +64,7 @@ export function resolveWorldConfig(config: StoreConfig & WorldConfig, existingCo * Default value for accessListSystems is [] */ export function resolveSystemConfig(systemName: string, config?: SystemConfig, existingContracts?: string[]) { - const name = config?.name ?? systemName.slice(0, STORE_SELECTOR_MAX_LENGTH); + const name = (config?.name ?? systemName).slice(0, STORE_NAME_MAX_LENGTH); const registerFunctionSelectors = config?.registerFunctionSelectors ?? true; const openAccess = config?.openAccess ?? true; const accessListAddresses: string[] = []; diff --git a/packages/world/ts/library/config/worldConfig.ts b/packages/world/ts/library/config/worldConfig.ts index 2009c29983..ecd579ac7f 100644 --- a/packages/world/ts/library/config/worldConfig.ts +++ b/packages/world/ts/library/config/worldConfig.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { DynamicResolutionType, zEthereumAddress, zObjectName, zSelector } from "@latticexyz/config"; +import { DynamicResolutionType, zEthereumAddress, zName, zObjectName } from "@latticexyz/config"; import { SYSTEM_DEFAULTS, WORLD_DEFAULTS } from "./defaults"; const zSystemName = zObjectName; @@ -9,7 +9,7 @@ const zSystemAccessList = z.array(zSystemName.or(zEthereumAddress)).default(SYST // The system config is a combination of a name config and access config const zSystemConfig = z.intersection( z.object({ - name: zSelector.optional(), + name: zName.optional(), registerFunctionSelectors: z.boolean().default(SYSTEM_DEFAULTS.registerFunctionSelector), }), z.discriminatedUnion("openAccess", [ diff --git a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol index 997749a23d..f444e2aebd 100644 --- a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Counter"))); -bytes32 constant CounterTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Counter"))) +); +ResourceId constant CounterTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0004010004000000000000000000000000000000000000000000000000000000 diff --git a/templates/react/packages/contracts/src/codegen/tables/Counter.sol b/templates/react/packages/contracts/src/codegen/tables/Counter.sol index 997749a23d..f444e2aebd 100644 --- a/templates/react/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/react/packages/contracts/src/codegen/tables/Counter.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Counter"))); -bytes32 constant CounterTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Counter"))) +); +ResourceId constant CounterTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0004010004000000000000000000000000000000000000000000000000000000 diff --git a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol index b747e01351..d9ea2bc66b 100644 --- a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol +++ b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Position"))); -bytes32 constant PositionTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Position"))) +); +ResourceId constant PositionTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x000c030004040400000000000000000000000000000000000000000000000000 diff --git a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol index 997749a23d..f444e2aebd 100644 --- a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol @@ -17,9 +17,13 @@ import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; -bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Counter"))); -bytes32 constant CounterTableId = _tableId; +ResourceId constant _tableId = ResourceId.wrap( + bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Counter"))) +); +ResourceId constant CounterTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0004010004000000000000000000000000000000000000000000000000000000 diff --git a/test-data/world-logs.json b/test-data/world-logs.json index 01c17d0650..9ff96aa813 100644 --- a/test-data/world-logs.json +++ b/test-data/world-logs.json @@ -3,12 +3,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000022000000000a0000000000002c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000016d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000600060030220202000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000006003025f5f5fc4c4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000077461626c654964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000b6669656c644c61796f757400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096b6579536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76616c7565536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012616269456e636f6465644b65794e616d657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014616269456e636f6465644669656c644e616d6573000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000022000000000a0000000000002c00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000174626d756473746f72650000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000600060030220202000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000006003025f5f5fc4c4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000077461626c654964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000b6669656c644c61796f757400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096b6579536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76616c7565536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012616269456e636f6465644b65794e616d657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014616269456e636f6465644669656c644e616d6573000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x0", "transactionLogIndex": "0x0", @@ -17,13 +17,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000016d756473746f7265000000000000000053746f7265486f6f6b7300000000000000000000000000000000000000000000000000000000000000000000000000600000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000174626d756473746f72650000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x1", "transactionLogIndex": "0x1", @@ -33,12 +33,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e616d6573706163654f776e6572000000000000000000000000000000000000000000000000000000000000000000600014010014000000000000000000000000000000000000000000000000000000001001004f0000000000000000000000000000000000000000000000000000000014010061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e616d657370616365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000056f776e6572000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a0000000000001400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000174626d756473746f726500000000000053746f7265486f6f6b7300000000000000000000000000000000000000000000000000000000000000000000000000600000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x2", "transactionLogIndex": "0x2", @@ -47,13 +47,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000042616c616e636573000000000000000000000000000000000000000000000000000000000000000000000000000000600020010020000000000000000000000000000000000000000000000000000000001001004f000000000000000000000000000000000000000000000000000000002001001f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e616d6573706163650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000762616c616e636500000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000174626d756473746f726500000000000053746f7265486f6f6b7300000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x3", "transactionLogIndex": "0x3", @@ -63,12 +63,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000100000000000001a00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e7374616c6c65644d6f64756c657300000000000000000000000000000000000000000000000000000000000000600014010014000000000000000000000000000000000000000000000000000000003002004f5f0000000000000000000000000000000000000000000000000000001401006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000a6d6f64756c654e616d6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d617267756d656e74734861736800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d6d6f64756c654164647265737300000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a0000000000001400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000174626d756473746f72650000000000005265736f75726365496473000000000000000000000000000000000000000000000000000000000000000000000000600001010001000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000010100600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a7265736f7572636549640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000066578697374730000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x4", "transactionLogIndex": "0x4", @@ -77,13 +77,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000100000000000001a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000044656c65676174696f6e730000000000000000000000000000000000000000000000000000000000000000000000006000200100200000000000000000000000000000000000000000000000000000000028020061610000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000964656c656761746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964656c6567617465650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001364656c65676174696f6e436f6e74726f6c496400000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000174626d756473746f72650000000000005265736f75726365496473000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x5", "transactionLogIndex": "0x5", @@ -93,12 +93,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000100000000000001a000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000600001010001000000000000000000000000000000000000000000000000000000003402005f610000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000663616c6c6572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000066163636573730000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001746200000000000000000000000000004e616d6573706163654f776e6572000000000000000000000000000000000000000000000000000000000000000000600014010014000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000140100610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b6e616d657370616365496400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000056f776e6572000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x6", "transactionLogIndex": "0x6", @@ -107,13 +107,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000600015020014010000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000001502006160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f72000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000673797374656d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7075626c69634163636573730000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001746200000000000000000000000000004e616d6573706163654f776e6572000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x7", "transactionLogIndex": "0x7", @@ -123,12 +123,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000240200200400000000000000000000000000000000000000000000000000000004010043000000000000000000000000000000000000000000000000000000002402005f43000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001066756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001673797374656d46756e6374696f6e53656c6563746f7200000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000042616c616e636573000000000000000000000000000000000000000000000000000000000000000000000000000000600020010020000000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000002001001f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b6e616d6573706163654964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000762616c616e636500000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x8", "transactionLogIndex": "0x8", @@ -137,13 +137,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d486f6f6b73000000000000000000000000000000000000000000000000000000000000000000000000600000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000042616c616e636573000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x9", "transactionLogIndex": "0x9", @@ -153,12 +153,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d52656769737472790000000000000000000000000000000000000000000000000000000000000000006000200100200000000000000000000000000000000000000000000000000000000014010061000000000000000000000000000000000000000000000000000000002001005f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000673797374656d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000100000000000001a00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000174620000000000000000000000000000496e7374616c6c65644d6f64756c657300000000000000000000000000000000000000000000000000000000000000600014010014000000000000000000000000000000000000000000000000000000003002004f5f0000000000000000000000000000000000000000000000000000001401006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000a6d6f64756c654e616d6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d617267756d656e74734861736800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d6d6f64756c654164647265737300000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0xa", "transactionLogIndex": "0xa", @@ -167,13 +167,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000600001010001000000000000000000000000000000000000000000000000000000002001005f0000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c7265736f75726365547970650000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000174620000000000000000000000000000496e7374616c6c65644d6f64756c657300000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0xb", "transactionLogIndex": "0xb", @@ -182,13 +182,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000004e616d6573706163654f776e65720000" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000100000000000001a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000044656c65676174696f6e730000000000000000000000000000000000000000000000000000000000000000000000006000200100200000000000000000000000000000000000000000000000000000000028020061610000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000964656c656761746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964656c6567617465650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001364656c65676174696f6e436f6e74726f6c496400000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0xc", "transactionLogIndex": "0xc", @@ -198,12 +198,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263654163636573730000" + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000044656c65676174696f6e73000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0xd", "transactionLogIndex": "0xd", @@ -212,13 +212,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263655479706500000000" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000100000000000001a000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001746200000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000600001010001000000000000000000000000000000000000000000000000000000003402005f610000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000a7265736f75726365496400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000663616c6c6572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000066163636573730000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0xe", "transactionLogIndex": "0xe", @@ -228,12 +228,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263655479706500000000" + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000636f72652e730000000000000000000000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001746200000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0xf", "transactionLogIndex": "0xf", @@ -243,12 +243,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000053797374656d73000000000000000000" + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000636f72652e73000000000000000000000000000000000000000000000000000000000000000000000000000000000015cafac3dd18ac6c6e92c921884f9e4176737c052c0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000600015020014010000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000001502006160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000873797374656d49640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000673797374656d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7075626c69634163636573730000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x10", "transactionLogIndex": "0x10", @@ -258,12 +258,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x0000000000000000000000000000000053797374656d52656769737472790000" + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000636f72652e7300000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x11", "transactionLogIndex": "0x11", @@ -272,13 +272,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263654163636573730000" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000240200200400000000000000000000000000000000000000000000000000000004010043000000000000000000000000000000000000000000000000000000002402005f43000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001066756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000873797374656d4964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001673797374656d46756e6374696f6e53656c6563746f7200000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x12", "transactionLogIndex": "0x12", @@ -287,13 +287,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000140554c3a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000040554c3a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x13", "transactionLogIndex": "0x13", @@ -303,12 +303,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000018d53b20800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008d53b208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000053797374656d486f6f6b73000000000000000000000000000000000000000000000000000000000000000000000000600000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000873797374656d4964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x14", "transactionLogIndex": "0x14", @@ -317,13 +317,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000125f6221000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000025f62210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000053797374656d486f6f6b73000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x15", "transactionLogIndex": "0x15", @@ -333,12 +333,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000012bfaa27400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000002bfaa274000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000053797374656d52656769737472790000000000000000000000000000000000000000000000000000000000000000006000200100200000000000000000000000000000000000000000000000000000000014010061000000000000000000000000000000000000000000000000000000002001005f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000673797374656d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000873797374656d4964000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x16", "transactionLogIndex": "0x16", @@ -347,13 +347,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000121293ca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000021293ca0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000017462000000000000000000000000000053797374656d5265676973747279000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x17", "transactionLogIndex": "0x17", @@ -362,13 +362,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000013ea8492200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003ea84922000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000016e7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x18", "transactionLogIndex": "0x18", @@ -377,13 +377,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x746200000000000000000000000000004e616d6573706163654f776e65720000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000018da798da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008da798da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000016e730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x19", "transactionLogIndex": "0x19", @@ -392,13 +392,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x746200000000000000000000000000005265736f757263654163636573730000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010ba51f4900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000000ba51f49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000026e73000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x1a", "transactionLogIndex": "0x1a", @@ -407,13 +407,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001530f4b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000530f4b60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000173790000000000000000000000000000636f72652e730000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x1b", "transactionLogIndex": "0x1b", @@ -423,12 +423,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000053797374656d73000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010560912900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000005609129000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000173790000000000000000000000000000636f72652e73000000000000000000000000000000000000000000000000000000000000000000000000000000000015cafac3dd18ac6c6e92c921884f9e4176737c052c0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x1c", "transactionLogIndex": "0x1c", @@ -437,13 +437,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x7462000000000000000000000000000053797374656d52656769737472790000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001a886545e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000a886545e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c000000000000000000000000000000000000000000000000000000000000002073790000000000000000000000000000636f72652e7300000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x1d", "transactionLogIndex": "0x1d", @@ -452,13 +452,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x746200000000000000000000000000005265736f757263654163636573730000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001d5f8337f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000d5f8337f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000026e73000000000000000000000000000000000000000000000000000000000000000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x1e", "transactionLogIndex": "0x1e", @@ -468,12 +468,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001a92813ad00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000a92813ad000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000140554c3a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e730000000000000000000040554c3a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x1f", "transactionLogIndex": "0x1f", @@ -483,12 +483,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000013350b6a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003350b6a9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000018d53b20800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e73000000000000000000008d53b208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x20", "transactionLogIndex": "0x20", @@ -498,12 +498,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000013c03a51c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003c03a51c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001ef5d6bbb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e7300000000000000000000ef5d6bbb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x21", "transactionLogIndex": "0x21", @@ -513,12 +513,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001b7a3c75600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000b7a3c756000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001c9c85a6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e7300000000000000000000c9c85a60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x22", "transactionLogIndex": "0x22", @@ -528,12 +528,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000011d2257ba00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000001d2257ba000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000145afd19900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e730000000000000000000045afd199000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x23", "transactionLogIndex": "0x23", @@ -542,135 +542,300 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x00000000000000000000000000000000496e7374616c6c65644d6f64756c6573" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000002636f72652e6d0000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000014e7f1725e7734ce288f8367e1bb143e90bb3f0512000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000018da798da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e73000000000000000000008da798da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", "transactionIndex": "0x0", "logIndex": "0x24", "transactionLogIndex": "0x24", "removed": false }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010ba51f4900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e73000000000000000000000ba51f49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x25", + "transactionLogIndex": "0x25", + "removed": false + }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001530f4b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e7300000000000000000000530f4b60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x26", + "transactionLogIndex": "0x26", + "removed": false + }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010560912900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e730000000000000000000005609129000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x27", + "transactionLogIndex": "0x27", + "removed": false + }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001b29e408900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e7300000000000000000000b29e4089000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x28", + "transactionLogIndex": "0x28", + "removed": false + }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001d5f8337f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e7300000000000000000000d5f8337f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x29", + "transactionLogIndex": "0x29", + "removed": false + }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001a92813ad00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e7300000000000000000000a92813ad000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x2a", + "transactionLogIndex": "0x2a", + "removed": false + }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000013350b6a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e73000000000000000000003350b6a9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x2b", + "transactionLogIndex": "0x2b", + "removed": false + }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000013c03a51c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e73000000000000000000003c03a51c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x2c", + "transactionLogIndex": "0x2c", + "removed": false + }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001b7a3c75600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e7300000000000000000000b7a3c756000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x2d", + "transactionLogIndex": "0x2d", + "removed": false + }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000011d2257ba00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000636f72652e73000000000000000000001d2257ba000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x2e", + "transactionLogIndex": "0x2e", + "removed": false + }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263655479706500000000" + "0x74620000000000000000000000000000496e7374616c6c65644d6f64756c6573" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265720000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000002636f72652e6d0000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000014e7f1725e7734ce288f8367e1bb143e90bb3f0512000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x63c9c3f365b40de92c07c06e86f096433bfb2e968c3caec07df00fa2cd1a46d1", + "transactionHash": "0x7e2f055f66d3576d1f74a5b4d50612da661bc8a0aadeb4a7bab1d68ebcec2987", + "transactionIndex": "0x0", + "logIndex": "0x2f", + "transactionLogIndex": "0x2f", + "removed": false + }, + { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "topics": [ + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x74626d756473746f72650000000000005461626c657300000000000000000000" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001746200000000000000000000000000004e756d626572000000000000000000000000000000000000000000000000000000000000000000000000000000000060000401000400000000000000000000000000000000000000000000000000000000040100030000000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", + "blockNumber": "0x4", + "transactionHash": "0xfee34092d2be35f9cb4747048fba17f73969fdd2bea418fdabfd123e9fccfdd3", "transactionIndex": "0x1", - "logIndex": "0x25", + "logIndex": "0x30", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d626572000000000000000000000000000000000000000000000000000000000000000000000000000000000060000401000400000000000000000000000000000000000000000000000000000000040100030000000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001746200000000000000000000000000004e756d6265720000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x63c9c3f365b40de92c07c06e86f096433bfb2e968c3caec07df00fa2cd1a46d1", + "transactionHash": "0xfee34092d2be35f9cb4747048fba17f73969fdd2bea418fdabfd123e9fccfdd3", "transactionIndex": "0x1", - "logIndex": "0x26", + "logIndex": "0x31", "transactionLogIndex": "0x1", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263655479706500000000" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000566563746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000000a0000000000001a00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000174620000000000000000000000000000566563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000006000080200040400000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000802002323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b6579000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017900000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xe1f1a922f753965be316f50e3c51c91c436aff6091710ba37cd2c2b932625a6d", + "transactionHash": "0xfdbe3cacafcfe2f5841a693f23a8cf6971ba5fd688185820eb3801cbee3a9929", "transactionIndex": "0x2", - "logIndex": "0x27", + "logIndex": "0x32", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000000a0000000000001a00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000566563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000006000080200040400000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000802002323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b6579000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017900000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000174620000000000000000000000000000566563746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xe1f1a922f753965be316f50e3c51c91c436aff6091710ba37cd2c2b932625a6d", + "transactionHash": "0xfdbe3cacafcfe2f5841a693f23a8cf6971ba5fd688185820eb3801cbee3a9929", "transactionIndex": "0x2", - "logIndex": "0x28", + "logIndex": "0x33", "transactionLogIndex": "0x1", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263655479706500000000" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737400000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000040000000000000e000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001746200000000000000000000000000004e756d6265724c697374000000000000000000000000000000000000000000000000000000000000000000000000006000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x2a33d478b71e83b3075ae06f08da8260132fc8c0f8bb4e316b7c8c36b37a1fb8", + "transactionHash": "0x27e29a882fdeb2c02feeb5003780c26c767d29d19bf24a76e3b79849468fdc78", "transactionIndex": "0x3", - "logIndex": "0x29", + "logIndex": "0x34", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000040000000000000e000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c697374000000000000000000000000000000000000000000000000000000000000000000000000006000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001746200000000000000000000000000004e756d6265724c69737400000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x2a33d478b71e83b3075ae06f08da8260132fc8c0f8bb4e316b7c8c36b37a1fb8", + "transactionHash": "0x27e29a882fdeb2c02feeb5003780c26c767d29d19bf24a76e3b79849468fdc78", "transactionIndex": "0x3", - "logIndex": "0x2a", + "logIndex": "0x35", "transactionLogIndex": "0x1", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263655479706500000000" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x74626d756473746f72650000000000005461626c657300000000000000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004d756c7469000000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000001c0000000000002c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001746200000000000000000000000000004d756c74690000000000000000000000000000000000000000000000000000000000000000000000000000000000006000210200200100000000000000000000000000000000000000000000000000000034040003601f2e000000000000000000000000000000000000000000000000002102003f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000036e756d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x7f5154e28a5640217c214a2007641ccb776e5b9609101919e28aead1d8eb6352", + "transactionHash": "0x470b581c9a1cac85fda4feb069e47f881b6c6444c68ffe52385ff85f8e67f0b7", "transactionIndex": "0x4", - "logIndex": "0x2b", + "logIndex": "0x36", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x6d756473746f726500000000000000005461626c657300000000000000000000" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000001c0000000000002c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004d756c74690000000000000000000000000000000000000000000000000000000000000000000000000000000000006000210200200100000000000000000000000000000000000000000000000000000034040003601f2e000000000000000000000000000000000000000000000000002102003f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000036e756d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001746200000000000000000000000000004d756c7469000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x7f5154e28a5640217c214a2007641ccb776e5b9609101919e28aead1d8eb6352", + "transactionHash": "0x470b581c9a1cac85fda4feb069e47f881b6c6444c68ffe52385ff85f8e67f0b7", "transactionIndex": "0x4", - "logIndex": "0x2c", + "logIndex": "0x37", "transactionLogIndex": "0x1", "removed": false }, @@ -678,14 +843,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263655479706500000000" + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000173790000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x9522e814b8b7aa55524257cfb693c2fdcb6fe1afd7aae7f0daf68c426afcbac9", + "transactionHash": "0xc7a43a7856187b487496b0246a8417e332ed34a586ce98b0bf80111dcf5387a3", "transactionIndex": "0x5", - "logIndex": "0x2d", + "logIndex": "0x38", "transactionLogIndex": "0x0", "removed": false }, @@ -693,14 +858,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000053797374656d73000000000000000000" + "0x7462000000000000000000000000000053797374656d73000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000155fc8d32690cc91d4c39d9d3abcbd16989f8757070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000173790000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000155fc8d32690cc91d4c39d9d3abcbd16989f8757070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x9522e814b8b7aa55524257cfb693c2fdcb6fe1afd7aae7f0daf68c426afcbac9", + "transactionHash": "0xc7a43a7856187b487496b0246a8417e332ed34a586ce98b0bf80111dcf5387a3", "transactionIndex": "0x5", - "logIndex": "0x2e", + "logIndex": "0x39", "transactionLogIndex": "0x1", "removed": false }, @@ -708,14 +873,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x0000000000000000000000000000000053797374656d52656769737472790000" + "0x7462000000000000000000000000000053797374656d52656769737472790000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f875707000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000437573746f6d4572726f727353797374", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f875707000000000000000000000000000000000000000000000000000000000000002073790000000000000000000000000000437573746f6d4572726f727353797374", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x9522e814b8b7aa55524257cfb693c2fdcb6fe1afd7aae7f0daf68c426afcbac9", + "transactionHash": "0xc7a43a7856187b487496b0246a8417e332ed34a586ce98b0bf80111dcf5387a3", "transactionIndex": "0x5", - "logIndex": "0x2f", + "logIndex": "0x3a", "transactionLogIndex": "0x2", "removed": false }, @@ -723,14 +888,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263654163636573730000" + "0x746200000000000000000000000000005265736f757263654163636573730000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570700000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000026e730000000000000000000000000000000000000000000000000000000000000000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570700000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x9522e814b8b7aa55524257cfb693c2fdcb6fe1afd7aae7f0daf68c426afcbac9", + "transactionHash": "0xc7a43a7856187b487496b0246a8417e332ed34a586ce98b0bf80111dcf5387a3", "transactionIndex": "0x5", - "logIndex": "0x30", + "logIndex": "0x3b", "transactionLogIndex": "0x3", "removed": false }, @@ -738,14 +903,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263655479706500000000" + "0x74626d756473746f72650000000000005265736f757263654964730000000000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001737900000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x21d2bdc995fad3ad12bc649405f9c25522526bf04a2ba379fd5cb4056e9368f3", + "transactionHash": "0xe43ef0b86a52b4da0f61cdc2ea334e5b7fa66f7588983f640e5deb328f669d51", "transactionIndex": "0x6", - "logIndex": "0x31", + "logIndex": "0x3c", "transactionLogIndex": "0x0", "removed": false }, @@ -753,14 +918,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000053797374656d73000000000000000000" + "0x7462000000000000000000000000000053797374656d73000000000000000000" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000150165878a594ca255338adfa4d48449f69242eb8f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001737900000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000150165878a594ca255338adfa4d48449f69242eb8f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x21d2bdc995fad3ad12bc649405f9c25522526bf04a2ba379fd5cb4056e9368f3", + "transactionHash": "0xe43ef0b86a52b4da0f61cdc2ea334e5b7fa66f7588983f640e5deb328f669d51", "transactionIndex": "0x6", - "logIndex": "0x32", + "logIndex": "0x3d", "transactionLogIndex": "0x1", "removed": false }, @@ -768,14 +933,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x0000000000000000000000000000000053797374656d52656769737472790000" + "0x7462000000000000000000000000000053797374656d52656769737472790000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000004e756d6265724c69737453797374656d", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f0000000000000000000000000000000000000000000000000000000000000020737900000000000000000000000000004e756d6265724c69737453797374656d", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x21d2bdc995fad3ad12bc649405f9c25522526bf04a2ba379fd5cb4056e9368f3", + "transactionHash": "0xe43ef0b86a52b4da0f61cdc2ea334e5b7fa66f7588983f640e5deb328f669d51", "transactionIndex": "0x6", - "logIndex": "0x33", + "logIndex": "0x3e", "transactionLogIndex": "0x2", "removed": false }, @@ -783,14 +948,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", - "0x000000000000000000000000000000005265736f757263654163636573730000" + "0x746200000000000000000000000000005265736f757263654163636573730000" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000026e730000000000000000000000000000000000000000000000000000000000000000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x21d2bdc995fad3ad12bc649405f9c25522526bf04a2ba379fd5cb4056e9368f3", + "transactionHash": "0xe43ef0b86a52b4da0f61cdc2ea334e5b7fa66f7588983f640e5deb328f669d51", "transactionIndex": "0x6", - "logIndex": "0x34", + "logIndex": "0x3f", "transactionLogIndex": "0x3", "removed": false }, @@ -798,14 +963,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000015f644e3c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000437573746f6d4572726f7273537973745f644e3c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000015f644e3c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002473790000000000000000000000000000437573746f6d4572726f7273537973745f644e3c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xa7b13684919b9c2f639041255d439afd3468db01f44f2699e159704399a11d5c", + "transactionHash": "0x8af9c1dc64c54b515e45eada457deeefb8c41f28a5dcd383b08e1974aba9deeb", "transactionIndex": "0x7", - "logIndex": "0x35", + "logIndex": "0x40", "transactionLogIndex": "0x0", "removed": false }, @@ -813,14 +978,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001a4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656da4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001a4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024737900000000000000000000000000004e756d6265724c69737453797374656da4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xd06d889514df379529e4231e85b2d241559dc810b765152c17047ae767b51cf0", + "transactionHash": "0x594595958fab259d43d21eff2b843d5f4a8b72eaba5bfc7d7ac57a64429baa46", "transactionIndex": "0x8", - "logIndex": "0x36", + "logIndex": "0x41", "transactionLogIndex": "0x0", "removed": false }, @@ -828,14 +993,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001f7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656df7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001f7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024737900000000000000000000000000004e756d6265724c69737453797374656df7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0x08304f1f19f128d652cf1f5b599e1c8b87e5b8164e3046e7041aabc886b7227f", + "transactionHash": "0x1ad0a4cb99bb91696c2fdc950ef8f725a033126b014ef9f8dc33fe5e60651a58", "transactionIndex": "0x9", - "logIndex": "0x37", + "logIndex": "0x42", "transactionLogIndex": "0x0", "removed": false }, @@ -843,14 +1008,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656d306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024737900000000000000000000000000004e756d6265724c69737453797374656d306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xab1ec3ac7ebed007e57666d5fbb7c5ba174c9695ea87d9cd5025f1323d5cd573", + "transactionHash": "0x74242eea32fbe3313d212eb94d4b0e9a1b41d4a3ca73b8e43409652d0d1033b4", "transactionIndex": "0xa", - "logIndex": "0x38", + "logIndex": "0x43", "transactionLogIndex": "0x0", "removed": false }, @@ -858,14 +1023,14 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", - "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" + "0x7462000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001b8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656db8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001b8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024737900000000000000000000000000004e756d6265724c69737453797374656db8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7704cb23795595159707f7ec7ef212f8a1727f88b980d34b605e994bb9f9e403", "blockNumber": "0x4", - "transactionHash": "0xef2202fbaac567d90f4790707035892d554dc226c0d481ffe667f1818774ad7b", + "transactionHash": "0xb7ae5d81eac3cada387ee8aa84b200810a20239fc9d28c8d88b1928b52df89fe", "transactionIndex": "0xb", - "logIndex": "0x39", + "logIndex": "0x44", "transactionLogIndex": "0x0", "removed": false }, @@ -873,12 +1038,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0x5599f2052ade9808af7738adc73853c23894a2f1e944c827f7f6b8e948c4e885", - "0x000000000000000000000000000000004e756d6265724c697374000000000000" + "0x746200000000000000000000000000004e756d6265724c697374000000000000" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000040000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000001a400000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf77983f832702b99ab5712e6c94615f2125f82e1b279f966c49fd8c8d8bd03f1", + "blockHash": "0x59ae5d5807af461e28ea34b5c32a06c5deb94686c0039bc439cd2c5d4f000cc2", "blockNumber": "0x5", - "transactionHash": "0xe373575d25699927fbfcd0fb9eb2b48ebaed83b87d3ca1e0a30478ac2ae2be4f", + "transactionHash": "0x36889a5ee3c55bfaac027f3581de07e578bada31ae0ac3b015ce6eb8977ef084", "transactionIndex": "0x0", "logIndex": "0x0", "transactionLogIndex": "0x0", @@ -888,12 +1053,12 @@ "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ "0x5599f2052ade9808af7738adc73853c23894a2f1e944c827f7f6b8e948c4e885", - "0x000000000000000000000000000000004e756d6265724c697374000000000000" + "0x746200000000000000000000000000004e756d6265724c697374000000000000" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000800000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000004500000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf77983f832702b99ab5712e6c94615f2125f82e1b279f966c49fd8c8d8bd03f1", + "blockHash": "0x59ae5d5807af461e28ea34b5c32a06c5deb94686c0039bc439cd2c5d4f000cc2", "blockNumber": "0x5", - "transactionHash": "0xfec9e0db2f68f31109c2f8fb678f398807407b88deb1b9644f1638e0012fac7c", + "transactionHash": "0x5feacc4cdda19482f80e612fb3e7d8e3d5c9260b14a2da727f882a2f3d7dd07c", "transactionIndex": "0x1", "logIndex": "0x1", "transactionLogIndex": "0x0",