Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(store): enforce unique table names across types #2736

Merged
merged 14 commits into from
Apr 25, 2024
5 changes: 5 additions & 0 deletions .changeset/strong-lobsters-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@latticexyz/store": patch
holic marked this conversation as resolved.
Show resolved Hide resolved
---

Added a check to `registerTable` that prevents registering both an offchain and onchain table with the same namespace and name, making indexing with decoded tables easier.
holic marked this conversation as resolved.
Show resolved Hide resolved
20 changes: 20 additions & 0 deletions docs/pages/store/reference/misc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1850,6 +1850,26 @@ function getType(ResourceId resourceId) internal pure returns (bytes2);
| -------- | -------- | ------------------------------------- |
| `<none>` | `bytes2` | The extracted 2-byte type identifier. |

#### getResourceName

Get the name from a resource ID.

```solidity
function getResourceName(ResourceId resourceId) internal pure returns (bytes30);
```

**Parameters**

| Name | Type | Description |
| ------------ | ------------ | ---------------- |
| `resourceId` | `ResourceId` | The resource ID. |

**Returns**

| Name | Type | Description |
| -------- | --------- | --------------- |
| `<none>` | `bytes30` | A 30-byte name. |

## ResourceIdLib

[Git Source](https://github.com/latticexyz/mud/blob/main/packages/store/src/ResourceId.sol)
Expand Down
26 changes: 13 additions & 13 deletions packages/store/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@
"file": "test/KeyEncoding.t.sol",
"test": "testRegisterAndGetFieldLayout",
"name": "register KeyEncoding table",
"gasUsed": 717787
"gasUsed": 721008
},
{
"file": "test/Mixed.t.sol",
Expand Down Expand Up @@ -669,7 +669,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testAccessEmptyData",
"name": "access length of dynamic field of non-existing record",
"gasUsed": 1158
"gasUsed": 1159
},
{
"file": "test/StoreCoreGas.t.sol",
Expand Down Expand Up @@ -771,13 +771,13 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testRegisterAndGetFieldLayout",
"name": "StoreCore: register table",
"gasUsed": 647841
"gasUsed": 651056
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testRegisterAndGetFieldLayout",
"name": "StoreCore: get field layout (warm)",
"gasUsed": 508
"gasUsed": 509
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -795,13 +795,13 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetDynamicData",
"name": "set complex record with dynamic data (4 slots)",
"gasUsed": 101866
"gasUsed": 101867
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetDynamicData",
"name": "get complex record with dynamic data (4 slots)",
"gasUsed": 4235
"gasUsed": 4234
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -813,7 +813,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetDynamicData",
"name": "compare: Set complex record with dynamic data using abi.encode",
"gasUsed": 267534
"gasUsed": 267535
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -825,13 +825,13 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetDynamicDataLength",
"name": "set dynamic length of dynamic index 1",
"gasUsed": 967
"gasUsed": 968
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetDynamicDataLength",
"name": "reduce dynamic length of dynamic index 0",
"gasUsed": 957
"gasUsed": 958
},
{
"file": "test/StoreCoreGas.t.sol",
Expand Down Expand Up @@ -873,7 +873,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetField",
"name": "set dynamic field (1 slot, second dynamic field)",
"gasUsed": 32246
"gasUsed": 32247
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -891,13 +891,13 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetStaticData",
"name": "get static record (1 slot)",
"gasUsed": 1551
"gasUsed": 1552
},
{
"file": "test/StoreCoreGas.t.sol",
"test": "testSetAndGetStaticDataSpanningWords",
"name": "set static record (2 slots)",
"gasUsed": 54649
"gasUsed": 54650
},
{
"file": "test/StoreCoreGas.t.sol",
Expand Down Expand Up @@ -1113,7 +1113,7 @@
"file": "test/Vector2.t.sol",
"test": "testRegisterAndGetFieldLayout",
"name": "register Vector2 field layout",
"gasUsed": 443849
"gasUsed": 447063
},
{
"file": "test/Vector2.t.sol",
Expand Down
9 changes: 9 additions & 0 deletions packages/store/src/ResourceId.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,13 @@ library ResourceIdInstance {
function getType(ResourceId resourceId) internal pure returns (bytes2) {
return bytes2(ResourceId.unwrap(resourceId));
}

/**
* @notice Get the name from a resource ID.
* @param resourceId The resource ID.
* @return A 30-byte name.
*/
function getResourceName(ResourceId resourceId) internal pure returns (bytes30) {
return bytes30(ResourceId.unwrap(resourceId) << (TYPE_BITS));
}
}
10 changes: 6 additions & 4 deletions packages/store/src/StoreCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { IStoreHook } from "./IStoreHook.sol";
import { StoreSwitch } from "./StoreSwitch.sol";
import { Hook, HookLib } from "./Hook.sol";
import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SPLICE_STATIC_DATA, AFTER_SPLICE_STATIC_DATA, BEFORE_SPLICE_DYNAMIC_DATA, AFTER_SPLICE_DYNAMIC_DATA, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "./storeHookTypes.sol";
import { ResourceId } from "./ResourceId.sol";
import { ResourceId, ResourceIdLib } from "./ResourceId.sol";
import { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "./storeResourceTypes.sol";
import { IStoreEvents } from "./IStoreEvents.sol";

Expand Down Expand Up @@ -160,7 +160,7 @@ library StoreCore {
string[] memory keyNames,
string[] memory fieldNames
) internal {
// Verify the table ID is of type RESOURCE_TABLE
// Verify the table ID is of type RESOURCE_TABLE or RESOURCE_OFFCHAIN_TABLE
if (tableId.getType() != RESOURCE_TABLE && tableId.getType() != RESOURCE_OFFCHAIN_TABLE) {
revert IStoreErrors.Store_InvalidResourceType(RESOURCE_TABLE, tableId, string(abi.encodePacked(tableId)));
}
Expand Down Expand Up @@ -209,8 +209,10 @@ library StoreCore {
}
}

// Verify there is no resource with this ID yet
if (ResourceIds._getExists(tableId)) {
// Verify that there is no table or offchain table with the same name
ResourceId onchainTableId = ResourceIdLib.encode(RESOURCE_TABLE, tableId.getResourceName());
ResourceId offchainTableId = ResourceIdLib.encode(RESOURCE_OFFCHAIN_TABLE, tableId.getResourceName());
if (ResourceIds._getExists(onchainTableId) || ResourceIds._getExists(offchainTableId)) {
revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId)));
}
holic marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
24 changes: 12 additions & 12 deletions packages/world-modules/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"file": "test/CallWithSignatureModule.t.sol",
"test": "testInstallRoot",
"name": "install delegation module",
"gasUsed": 687912
"gasUsed": 691133
},
{
"file": "test/CallWithSignatureModule.t.sol",
Expand Down Expand Up @@ -87,13 +87,13 @@
"file": "test/KeysInTableModule.t.sol",
"test": "testInstallComposite",
"name": "install keys in table module",
"gasUsed": 1456815
"gasUsed": 1463317
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testInstallGas",
"name": "install keys in table module",
"gasUsed": 1456815
"gasUsed": 1463317
},
{
"file": "test/KeysInTableModule.t.sol",
Expand All @@ -105,13 +105,13 @@
"file": "test/KeysInTableModule.t.sol",
"test": "testInstallSingleton",
"name": "install keys in table module",
"gasUsed": 1456815
"gasUsed": 1463317
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testSetAndDeleteRecordHookCompositeGas",
"name": "install keys in table module",
"gasUsed": 1456815
"gasUsed": 1463317
},
{
"file": "test/KeysInTableModule.t.sol",
Expand All @@ -129,7 +129,7 @@
"file": "test/KeysInTableModule.t.sol",
"test": "testSetAndDeleteRecordHookGas",
"name": "install keys in table module",
"gasUsed": 1456815
"gasUsed": 1463317
},
{
"file": "test/KeysInTableModule.t.sol",
Expand All @@ -147,7 +147,7 @@
"file": "test/KeysWithValueModule.t.sol",
"test": "testGetKeysWithValueGas",
"name": "install keys with value module",
"gasUsed": 715762
"gasUsed": 719012
},
{
"file": "test/KeysWithValueModule.t.sol",
Expand All @@ -165,7 +165,7 @@
"file": "test/KeysWithValueModule.t.sol",
"test": "testInstall",
"name": "install keys with value module",
"gasUsed": 715762
"gasUsed": 719012
},
{
"file": "test/KeysWithValueModule.t.sol",
Expand All @@ -177,7 +177,7 @@
"file": "test/KeysWithValueModule.t.sol",
"test": "testSetAndDeleteRecordHook",
"name": "install keys with value module",
"gasUsed": 715762
"gasUsed": 719012
},
{
"file": "test/KeysWithValueModule.t.sol",
Expand All @@ -195,7 +195,7 @@
"file": "test/KeysWithValueModule.t.sol",
"test": "testSetField",
"name": "install keys with value module",
"gasUsed": 715762
"gasUsed": 719012
},
{
"file": "test/KeysWithValueModule.t.sol",
Expand Down Expand Up @@ -315,7 +315,7 @@
"file": "test/UniqueEntityModule.t.sol",
"test": "testInstall",
"name": "install unique entity module",
"gasUsed": 715495
"gasUsed": 718745
},
{
"file": "test/UniqueEntityModule.t.sol",
Expand All @@ -327,7 +327,7 @@
"file": "test/UniqueEntityModule.t.sol",
"test": "testInstallRoot",
"name": "installRoot unique entity module",
"gasUsed": 685964
"gasUsed": 689190
},
{
"file": "test/UniqueEntityModule.t.sol",
Expand Down
8 changes: 4 additions & 4 deletions packages/world/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"file": "test/Factories.t.sol",
"test": "testWorldFactoryGas",
"name": "deploy world via WorldFactory",
"gasUsed": 12805251
"gasUsed": 12847807
},
{
"file": "test/World.t.sol",
Expand Down Expand Up @@ -129,7 +129,7 @@
"file": "test/World.t.sol",
"test": "testRegisterTable",
"name": "Register a new table in the namespace",
"gasUsed": 569676
"gasUsed": 572927
},
{
"file": "test/World.t.sol",
Expand Down Expand Up @@ -249,7 +249,7 @@
"file": "test/WorldProxy.t.sol",
"test": "testRegisterTable",
"name": "Register a new table in the namespace",
"gasUsed": 574686
"gasUsed": 577937
},
{
"file": "test/WorldProxy.t.sol",
Expand Down Expand Up @@ -285,7 +285,7 @@
"file": "test/WorldProxyFactory.t.sol",
"test": "testWorldProxyFactoryGas",
"name": "deploy world via WorldProxyFactory",
"gasUsed": 9100791
"gasUsed": 9143347
},
{
"file": "test/WorldProxyFactory.t.sol",
Expand Down
Loading