From bfcb293d1931edde7f8a3e077f6f555a26fd1d2f Mon Sep 17 00:00:00 2001 From: alvarius Date: Thu, 21 Sep 2023 17:17:23 +0100 Subject: [PATCH] feat(store,world): replace `ephemeral` tables with `offchain` tables (#1558) Co-authored-by: Kevin Ingersoll Co-authored-by: dk1a --- .changeset/small-chicken-repair.md | 20 +++ docs/pages/store/advanced-features.mdx | 20 +-- docs/pages/world/internals.mdx | 2 +- .../contracts/src/codegen/tables/Multi.sol | 56 +++---- .../contracts/src/codegen/tables/Number.sol | 50 +++--- .../src/codegen/tables/NumberList.sol | 44 +++--- .../contracts/src/codegen/tables/Vector.sol | 50 +++--- .../minimal/packages/contracts/mud.config.ts | 2 +- .../src/codegen/tables/CounterTable.sol | 44 +++--- .../src/codegen/tables/Inventory.sol | 56 +++---- .../src/codegen/tables/MessageTable.sol | 71 +++++++-- .../src/systems/ChatNamespacedSystem.sol | 2 +- .../contracts/src/systems/ChatSystem.sol | 2 +- .../contracts/test/ChatNamespaced.t.sol | 4 +- packages/block-logs-stream/README.md | 1 - packages/cli/contracts/src/codegen/index.sol | 2 +- .../src/codegen/tables/Dynamics1.sol | 50 +++--- .../src/codegen/tables/Dynamics2.sol | 50 +++--- .../tables/{Ephemeral.sol => Offchain.sol} | 90 +++++++++-- .../src/codegen/tables/Singleton.sol | 44 +++--- .../contracts/src/codegen/tables/Statics.sol | 80 +++++----- packages/cli/contracts/test/Tablegen.t.sol | 8 +- packages/cli/scripts/generate-test-tables.ts | 4 +- .../utils/tables/getRegisterTableCallData.ts | 2 +- packages/cli/src/utils/tables/types.ts | 2 +- .../src/codegen/render-solidity/common.ts | 16 +- .../src/codegen/render-solidity/types.ts | 1 + packages/dev-tools/src/events/EventIcon.tsx | 2 - packages/dev-tools/src/events/LogsTable.tsx | 2 +- packages/store-sync/src/common.ts | 2 +- .../src/postgres/postgresStorage.ts | 2 +- .../src/recs/configToRecsComponents.ts | 2 +- packages/store-sync/src/recs/recsStorage.ts | 2 +- .../store-sync/src/sqlite/sqliteStorage.ts | 2 +- packages/store/gas-report.json | 86 +++++------ packages/store/src/IStore.sol | 22 +-- packages/store/src/StoreCore.sol | 97 ++++++------ packages/store/src/StoreSwitch.sol | 23 --- .../store/src/codegen/tables/Callbacks.sol | 50 +++--- packages/store/src/codegen/tables/Hooks.sol | 50 +++--- .../store/src/codegen/tables/KeyEncoding.sol | 70 ++++----- packages/store/src/codegen/tables/Mixed.sol | 50 +++--- .../store/src/codegen/tables/ResourceIds.sol | 50 +++--- .../store/src/codegen/tables/StoreHooks.sol | 50 +++--- packages/store/src/codegen/tables/Tables.sol | 50 +++--- packages/store/src/codegen/tables/Vector2.sol | 50 +++--- packages/store/test/StoreMock.sol | 12 -- packages/store/ts/codegen/ephemeral.ts | 51 ------ packages/store/ts/codegen/field.ts | 145 +++++++++--------- packages/store/ts/codegen/record.ts | 62 +++++--- packages/store/ts/codegen/renderTable.ts | 31 +--- packages/store/ts/codegen/tableOptions.ts | 11 +- packages/store/ts/codegen/types.ts | 8 +- packages/store/ts/config/defaults.ts | 2 +- packages/store/ts/config/storeConfig.ts | 8 +- packages/store/ts/storeEvents.ts | 1 - packages/world/gas-report.json | 84 +++++----- packages/world/mud.config.ts | 2 - .../world/src/modules/core/CoreModule.sol | 6 +- .../world/src/modules/core/CoreSystem.sol | 2 - .../implementations/EphemeralRecordSystem.sol | 33 ---- .../src/modules/core/tables/Balances.sol | 50 +++--- .../modules/core/tables/FunctionSelectors.sol | 50 +++--- .../src/modules/core/tables/SystemHooks.sol | 50 +++--- .../modules/core/tables/SystemRegistry.sol | 50 +++--- .../world/src/modules/core/tables/Systems.sol | 50 +++--- .../keysintable/tables/KeysInTable.sol | 50 +++--- .../keysintable/tables/UsedKeysIndex.sol | 56 +++---- .../keyswithvalue/tables/KeysWithValue.sol | 50 +++--- .../tables/CallboundDelegations.sol | 70 ++++----- .../tables/TimeboundDelegations.sol | 56 +++---- .../uniqueentity/tables/UniqueEntity.sol | 44 +++--- packages/world/src/tables/Delegations.sol | 56 +++---- .../world/src/tables/InstalledModules.sol | 56 +++---- packages/world/src/tables/NamespaceOwner.sol | 50 +++--- packages/world/src/tables/ResourceAccess.sol | 56 +++---- packages/world/test/tables/AddressArray.sol | 50 +++--- packages/world/test/tables/Bool.sol | 44 +++--- .../contracts/src/codegen/tables/Counter.sol | 44 +++--- .../contracts/src/codegen/tables/Counter.sol | 44 +++--- .../contracts/src/codegen/tables/Position.sol | 50 +++--- .../contracts/src/codegen/tables/Counter.sol | 44 +++--- 82 files changed, 1474 insertions(+), 1489 deletions(-) create mode 100644 .changeset/small-chicken-repair.md rename packages/cli/contracts/src/codegen/tables/{Ephemeral.sol => Offchain.sol} (58%) delete mode 100644 packages/store/ts/codegen/ephemeral.ts delete mode 100644 packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol diff --git a/.changeset/small-chicken-repair.md b/.changeset/small-chicken-repair.md new file mode 100644 index 0000000000..f41b8e9190 --- /dev/null +++ b/.changeset/small-chicken-repair.md @@ -0,0 +1,20 @@ +--- +"@latticexyz/block-logs-stream": patch +"@latticexyz/cli": patch +"@latticexyz/common": major +"@latticexyz/dev-tools": patch +"@latticexyz/store-sync": patch +"@latticexyz/store": major +"create-mud": minor +--- + +What used to be known as `ephemeral` table is now called `offchain` table. +The previous `ephemeral` tables only supported an `emitEphemeral` method, which emitted a `StoreSetEphemeralRecord` event. + +Now `offchain` tables support all regular table methods, except partial operations on dynamic fields (`push`, `pop`, `update`). +Unlike regular tables they don't store data on-chain but emit the same events as regular tables (`StoreSetRecord`, `StoreSpliceStaticData`, `StoreDeleteRecord`), so their data can be indexed by offchain indexers/clients. + +```diff +- EphemeralTable.emitEphemeral(value); ++ OffchainTable.set(value); +``` diff --git a/docs/pages/store/advanced-features.mdx b/docs/pages/store/advanced-features.mdx index c04efbdaa7..484c2d0020 100644 --- a/docs/pages/store/advanced-features.mdx +++ b/docs/pages/store/advanced-features.mdx @@ -34,9 +34,9 @@ uint256 value = CounterSingleton.get(); Additional documentation on Table library generation can be found in the [`tablegen`](/store/config#store-config--tablegen-tool) section. -### Ephemeral tables +### Offchain tables -Tables with the `ephemeral` property do not write to on-chain storage. +Tables with the `offchainOnly` property do not write to on-chain storage. Instead, they simply emit events when records are set. They are useful for sending data to connected clients without the gas costs associated with a storage write. @@ -52,26 +52,12 @@ export default mudConfig({ amount: "uint32", receiver: "bytes32", }, - ephemeral: true, + offchainOnly: true, }, }, }); ``` -This will slightly change the generated code for the table. The `emitEphemeral` function is the main entrypoint: - -```solidity -import { TradeExecuted, TradeExecutedData } from "./codegen/Tables.sol"; - -// Emitting an ephemeral record -TradeExecuted.emitEphemeral("0x1234", TradeExecutedData({ - amount: 10, - receiver: "0x5678", -})); -``` - -`get`, `set`, and `delete` functions are not generated for ephemeral tables. - ### Storage hooks It is possible to register hooks on tables, allowing additional logic to be executed when records or fields are updated. Use cases include: creating indices on another table (like the `ownerOf` mapping of the ERC-721 spec as an example), emitting events on a different contract, or simply additional access-control and checks by reverting in the hook. diff --git a/docs/pages/world/internals.mdx b/docs/pages/world/internals.mdx index 2205f590d8..4b501e2c19 100644 --- a/docs/pages/world/internals.mdx +++ b/docs/pages/world/internals.mdx @@ -22,7 +22,7 @@ Except `NamespaceOwner` is initialized in World's constructor, because it's need Internal systems are in `core` module's [implementations](https://github.com/latticexyz/mud/tree/main/packages/world/src/modules/core/implementations) folder, because they're installed by `CoreModule`. - `AccessManagementSystem` - grants/revokes access to/from resources -- `EphemeralRecordSystem` - has `emitEphemeralRecord` for ephemeral tables +- `BalanceTransferSystem` - handles balance transfers between namespaces and from namespaces to addresses - `ModuleInstallationSystem` - installation of (non-root) modules in the World - `StoreRegistrationSystem` - _its methods should not be used with the World framework_. Surfaces the APIs necessary to register Tables on-chain, but lacks namespaces used by World for better permission checks - `WorldRegistrationSystem` - surfaces the APIs necessary to register Systems, Tables, and Namespaces on-chain diff --git a/e2e/packages/contracts/src/codegen/tables/Multi.sol b/e2e/packages/contracts/src/codegen/tables/Multi.sol index b3674887f3..56f69dba19 100644 --- a/e2e/packages/contracts/src/codegen/tables/Multi.sol +++ b/e2e/packages/contracts/src/codegen/tables/Multi.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Multi"))) @@ -362,63 +362,63 @@ library Multi { (_table.num, _table.value) = decodeStatic(_staticData); } - /** Tightly pack static data using this table's schema */ - function encodeStatic(int256 num, bool value) internal pure returns (bytes memory) { - return abi.encodePacked(num, value); - } - - /** Tightly pack full data using this table's field layout */ - function encode(int256 num, bool value) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(num, value); - - PackedCounter _encodedLengths; - bytes memory _dynamicData; - - return (_staticData, _encodedLengths, _dynamicData); - } - - /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(uint32 a, bool b, uint256 c, int120 d) internal pure returns (bytes32[] memory) { + /** Delete all data for given keys */ + function deleteRecord(uint32 a, bool b, uint256 c, int120 d) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(a)); _keyTuple[1] = _boolToBytes32(b); _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - return _keyTuple; + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ - function deleteRecord(uint32 a, bool b, uint256 c, int120 d) internal { + /** Delete all data for given keys */ + function _deleteRecord(uint32 a, bool b, uint256 c, int120 d) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(a)); _keyTuple[1] = _boolToBytes32(b); _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ - function _deleteRecord(uint32 a, bool b, uint256 c, int120 d) internal { + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, uint32 a, bool b, uint256 c, int120 d) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(a)); _keyTuple[1] = _boolToBytes32(b); _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, uint32 a, bool b, uint256 c, int120 d) internal { + /** Tightly pack static data using this table's schema */ + function encodeStatic(int256 num, bool value) internal pure returns (bytes memory) { + return abi.encodePacked(num, value); + } + + /** Tightly pack full data using this table's field layout */ + function encode(int256 num, bool value) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(num, value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** Encode keys as a bytes32 array using this table's field layout */ + function encodeKeyTuple(uint32 a, bool b, uint256 c, int120 d) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(a)); _keyTuple[1] = _boolToBytes32(b); _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + return _keyTuple; } } diff --git a/e2e/packages/contracts/src/codegen/tables/Number.sol b/e2e/packages/contracts/src/codegen/tables/Number.sol index db8e380f8b..b17b841277 100644 --- a/e2e/packages/contracts/src/codegen/tables/Number.sol +++ b/e2e/packages/contracts/src/codegen/tables/Number.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Number"))) @@ -180,6 +180,30 @@ library Number { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Delete all data for given keys */ + function deleteRecord(uint32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(uint32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, uint32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(uint32 value) internal pure returns (bytes memory) { return abi.encodePacked(value); @@ -202,28 +226,4 @@ library Number { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(uint32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(uint256(key)); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(uint32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(uint256(key)); - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, uint32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(uint256(key)); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/e2e/packages/contracts/src/codegen/tables/NumberList.sol b/e2e/packages/contracts/src/codegen/tables/NumberList.sol index 17d4e49daa..1510e27581 100644 --- a/e2e/packages/contracts/src/codegen/tables/NumberList.sol +++ b/e2e/packages/contracts/src/codegen/tables/NumberList.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("NumberList"))) @@ -474,6 +474,27 @@ library NumberList { } } + /** Delete all data for given keys */ + function deleteRecord() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord() 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) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack dynamic data using this table's schema */ function encodeLengths(uint32[] memory value) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits @@ -502,25 +523,4 @@ library NumberList { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord() internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord() 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) internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/e2e/packages/contracts/src/codegen/tables/Vector.sol b/e2e/packages/contracts/src/codegen/tables/Vector.sol index 8fca7ea7bb..cb2ef6792b 100644 --- a/e2e/packages/contracts/src/codegen/tables/Vector.sol +++ b/e2e/packages/contracts/src/codegen/tables/Vector.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Vector"))) @@ -302,6 +302,30 @@ library Vector { (_table.x, _table.y) = decodeStatic(_staticData); } + /** Delete all data for given keys */ + function deleteRecord(uint32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(uint32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, uint32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(int32 x, int32 y) internal pure returns (bytes memory) { return abi.encodePacked(x, y); @@ -324,28 +348,4 @@ library Vector { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(uint32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(uint256(key)); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(uint32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(uint256(key)); - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, uint32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(uint256(key)); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/examples/minimal/packages/contracts/mud.config.ts b/examples/minimal/packages/contracts/mud.config.ts index 58cf475496..dfeeaffb52 100644 --- a/examples/minimal/packages/contracts/mud.config.ts +++ b/examples/minimal/packages/contracts/mud.config.ts @@ -26,7 +26,7 @@ export default mudConfig({ valueSchema: { value: "string", }, - ephemeral: true, + offchainOnly: true, }, Inventory: { keySchema: { diff --git a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol index fccaf9550e..963e2f4452 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("CounterTable"))) @@ -166,6 +166,27 @@ library CounterTable { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Delete all data for given keys */ + function deleteRecord() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord() 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) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(uint32 value) internal pure returns (bytes memory) { return abi.encodePacked(value); @@ -187,25 +208,4 @@ library CounterTable { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord() internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord() 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) internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol index 046b2889d6..d90f9a1343 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Inventory"))) @@ -213,58 +213,58 @@ library Inventory { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((amount)), _fieldLayout); } - /** Tightly pack static data using this table's schema */ - function encodeStatic(uint32 amount) internal pure returns (bytes memory) { - return abi.encodePacked(amount); - } - - /** Tightly pack full data using this table's field layout */ - function encode(uint32 amount) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(amount); - - PackedCounter _encodedLengths; - bytes memory _dynamicData; - - return (_staticData, _encodedLengths, _dynamicData); - } - - /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(address owner, uint32 item, uint32 itemVariant) internal pure returns (bytes32[] memory) { + /** Delete all data for given keys */ + function deleteRecord(address owner, uint32 item, uint32 itemVariant) internal { bytes32[] memory _keyTuple = new bytes32[](3); _keyTuple[0] = bytes32(uint256(uint160(owner))); _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - return _keyTuple; + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ - function deleteRecord(address owner, uint32 item, uint32 itemVariant) internal { + /** Delete all data for given keys */ + function _deleteRecord(address owner, uint32 item, uint32 itemVariant) internal { bytes32[] memory _keyTuple = new bytes32[](3); _keyTuple[0] = bytes32(uint256(uint160(owner))); _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ - function _deleteRecord(address owner, uint32 item, uint32 itemVariant) internal { + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, address owner, uint32 item, uint32 itemVariant) internal { bytes32[] memory _keyTuple = new bytes32[](3); _keyTuple[0] = bytes32(uint256(uint160(owner))); _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, address owner, uint32 item, uint32 itemVariant) internal { + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint32 amount) internal pure returns (bytes memory) { + return abi.encodePacked(amount); + } + + /** Tightly pack full data using this table's field layout */ + function encode(uint32 amount) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(amount); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** Encode keys as a bytes32 array using this table's field layout */ + function encodeKeyTuple(address owner, uint32 item, uint32 itemVariant) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](3); _keyTuple[0] = bytes32(uint256(uint160(owner))); _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + return _keyTuple; } } diff --git a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol index 872bdf5b51..b23dd832b9 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol @@ -18,10 +18,10 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( - bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("MessageTable"))) + bytes32(abi.encodePacked(RESOURCE_OFFCHAIN_TABLE, bytes14(""), bytes16("MessageTable"))) ); ResourceId constant MessageTableTableId = _tableId; @@ -76,37 +76,86 @@ library MessageTable { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } - /** Emit the ephemeral event using individual values */ - function emitEphemeral(string memory value) internal { + /** Set the full data using individual values */ + function set(string memory value) internal { bytes memory _staticData; PackedCounter _encodedLengths = encodeLengths(value); bytes memory _dynamicData = encodeDynamic(value); bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } - /** Emit the ephemeral event using individual values */ - function _emitEphemeral(string memory value) internal { + /** Set the full data using individual values */ + function _set(string memory value) internal { bytes memory _staticData; PackedCounter _encodedLengths = encodeLengths(value); bytes memory _dynamicData = encodeDynamic(value); bytes32[] memory _keyTuple = new bytes32[](0); - StoreCore.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } - /** Emit the ephemeral event using individual values (using the specified store) */ - function emitEphemeral(IStore _store, string memory value) internal { + /** Set the full data using individual values (using the specified store) */ + function set(IStore _store, string memory value) internal { bytes memory _staticData; PackedCounter _encodedLengths = encodeLengths(value); bytes memory _dynamicData = encodeDynamic(value); bytes32[] memory _keyTuple = new bytes32[](0); - _store.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + + /** + * Decode the tightly packed blob of static data using this table's field layout + * Undefined behaviour for invalid blobs + */ + function decodeDynamic( + PackedCounter _encodedLengths, + bytes memory _blob + ) internal pure returns (string memory value) { + uint256 _start; + uint256 _end; + unchecked { + _end = _encodedLengths.atIndex(0); + } + value = (string(SliceLib.getSubslice(_blob, _start, _end).toBytes())); + } + + /** + * Decode the tightly packed blob using this table's field layout. + * Undefined behaviour for invalid blobs. + */ + function decode( + bytes memory, + PackedCounter _encodedLengths, + bytes memory _dynamicData + ) internal pure returns (string memory value) { + (value) = decodeDynamic(_encodedLengths, _dynamicData); + } + + /** Delete all data for given keys */ + function deleteRecord() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord() 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) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /** Tightly pack dynamic data using this table's schema */ diff --git a/examples/minimal/packages/contracts/src/systems/ChatNamespacedSystem.sol b/examples/minimal/packages/contracts/src/systems/ChatNamespacedSystem.sol index 88a5958cbe..3d43d16f07 100644 --- a/examples/minimal/packages/contracts/src/systems/ChatNamespacedSystem.sol +++ b/examples/minimal/packages/contracts/src/systems/ChatNamespacedSystem.sol @@ -6,6 +6,6 @@ import { MessageTable } from "../codegen/index.sol"; // This system is supposed to have a different namespace, but otherwise be identical to ChatSystem contract ChatNamespacedSystem is System { function sendMessage(string memory message) public { - MessageTable.emitEphemeral(message); + MessageTable.set(message); } } diff --git a/examples/minimal/packages/contracts/src/systems/ChatSystem.sol b/examples/minimal/packages/contracts/src/systems/ChatSystem.sol index 6091eb92a9..e359ef4002 100644 --- a/examples/minimal/packages/contracts/src/systems/ChatSystem.sol +++ b/examples/minimal/packages/contracts/src/systems/ChatSystem.sol @@ -5,6 +5,6 @@ import { MessageTable } from "../codegen/index.sol"; contract ChatSystem is System { function sendMessage(string memory message) public { - MessageTable.emitEphemeral(message); + MessageTable.set(message); } } diff --git a/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol b/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol index 10a4675e22..122f2392f2 100644 --- a/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol +++ b/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol @@ -11,11 +11,11 @@ import { MessageTable, MessageTableTableId } from "../src/codegen/index.sol"; import { IChatNamespacedSystem } from "../src/interfaces/IChatNamespacedSystem.sol"; contract ChatNamespacedTest is MudTest { - function testEmitEphemeral() public { + function testOffchain() public { bytes32[] memory keyTuple; string memory value = "test"; vm.expectEmit(true, true, true, true); - emit StoreCore.StoreEphemeralRecord( + emit StoreCore.StoreSetRecord( MessageTableTableId, keyTuple, new bytes(0), diff --git a/packages/block-logs-stream/README.md b/packages/block-logs-stream/README.md index 14691644a6..5dae0a43a9 100644 --- a/packages/block-logs-stream/README.md +++ b/packages/block-logs-stream/README.md @@ -29,7 +29,6 @@ latestBlockNumber$ "event StoreDeleteRecord(bytes32 tableId, bytes32[] keyTuple)", "event StoreSetField(bytes32 tableId, bytes32[] keyTuple, uint8 schemaIndex, bytes data)", "event StoreSetRecord(bytes32 tableId, bytes32[] keyTuple, bytes data)", - "event StoreEphemeralRecord(bytes32 tableId, bytes32[] keyTuple, bytes data)", ]), }), mergeMap(({ logs }) => from(groupLogsByBlockNumber(logs))) diff --git a/packages/cli/contracts/src/codegen/index.sol b/packages/cli/contracts/src/codegen/index.sol index de034e0789..49830113c3 100644 --- a/packages/cli/contracts/src/codegen/index.sol +++ b/packages/cli/contracts/src/codegen/index.sol @@ -7,4 +7,4 @@ import { Statics, StaticsData, StaticsTableId } from "./tables/Statics.sol"; import { Dynamics1, Dynamics1Data, Dynamics1TableId } from "./tables/Dynamics1.sol"; import { Dynamics2, Dynamics2Data, Dynamics2TableId } from "./tables/Dynamics2.sol"; import { Singleton, SingletonTableId } from "./tables/Singleton.sol"; -import { Ephemeral, EphemeralTableId } from "./tables/Ephemeral.sol"; +import { Offchain, OffchainTableId } from "./tables/Offchain.sol"; diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol index 76852f049e..3675d141c5 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Dynamics1"))) @@ -1416,6 +1416,30 @@ library Dynamics1 { ); } + /** Delete all data for given keys */ + function deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack dynamic data using this table's schema */ function encodeLengths( bytes32[1] memory staticB32, @@ -1476,30 +1500,6 @@ library Dynamics1 { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } function toStaticArray_bytes32_1(bytes32[] memory _value) pure returns (bytes32[1] memory _result) { diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol index 5001ff4efb..e233e4e5f3 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Dynamics2"))) @@ -878,6 +878,30 @@ library Dynamics2 { (_table.u64, _table.str, _table.b) = decodeDynamic(_encodedLengths, _dynamicData); } + /** Delete all data for given keys */ + function deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack dynamic data using this table's schema */ function encodeLengths( uint64[] memory u64, @@ -915,28 +939,4 @@ library Dynamics2 { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol b/packages/cli/contracts/src/codegen/tables/Offchain.sol similarity index 58% rename from packages/cli/contracts/src/codegen/tables/Ephemeral.sol rename to packages/cli/contracts/src/codegen/tables/Offchain.sol index b2edf7c856..90d628f248 100644 --- a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol +++ b/packages/cli/contracts/src/codegen/tables/Offchain.sol @@ -18,18 +18,18 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( - bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Ephemeral"))) + bytes32(abi.encodePacked(RESOURCE_OFFCHAIN_TABLE, bytes14(""), bytes16("Offchain"))) ); -ResourceId constant EphemeralTableId = _tableId; +ResourceId constant OffchainTableId = _tableId; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0020010020000000000000000000000000000000000000000000000000000000 ); -library Ephemeral { +library Offchain { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { return _fieldLayout; @@ -78,8 +78,32 @@ library Ephemeral { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } - /** Emit the ephemeral event using individual values */ - function emitEphemeral(bytes32 key, uint256 value) internal { + /** Set value */ + function setValue(bytes32 key, uint256 value) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + + /** Set value */ + function _setValue(bytes32 key, uint256 value) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + + /** Set value (using the specified store) */ + function setValue(IStore _store, bytes32 key, uint256 value) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + + /** Set the full data using individual values */ + function set(bytes32 key, uint256 value) internal { bytes memory _staticData = encodeStatic(value); PackedCounter _encodedLengths; @@ -88,11 +112,11 @@ library Ephemeral { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } - /** Emit the ephemeral event using individual values */ - function _emitEphemeral(bytes32 key, uint256 value) internal { + /** Set the full data using individual values */ + function _set(bytes32 key, uint256 value) internal { bytes memory _staticData = encodeStatic(value); PackedCounter _encodedLengths; @@ -101,11 +125,11 @@ library Ephemeral { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreCore.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } - /** Emit the ephemeral event using individual values (using the specified store) */ - function emitEphemeral(IStore _store, bytes32 key, uint256 value) internal { + /** Set the full data using individual values (using the specified store) */ + function set(IStore _store, bytes32 key, uint256 value) internal { bytes memory _staticData = encodeStatic(value); PackedCounter _encodedLengths; @@ -114,7 +138,47 @@ library Ephemeral { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + + /** + * 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 (uint256 value) { + value = (uint256(Bytes.slice32(_blob, 0))); + } + + /** + * Decode the tightly packed blob using this table's field layout. + * Undefined behaviour for invalid blobs. + */ + function decode(bytes memory _staticData, PackedCounter, bytes memory) internal pure returns (uint256 value) { + (value) = decodeStatic(_staticData); + } + + /** Delete all data for given keys */ + function deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /** Tightly pack static data using this table's schema */ diff --git a/packages/cli/contracts/src/codegen/tables/Singleton.sol b/packages/cli/contracts/src/codegen/tables/Singleton.sol index 45d77b5356..f55dc19ff7 100644 --- a/packages/cli/contracts/src/codegen/tables/Singleton.sol +++ b/packages/cli/contracts/src/codegen/tables/Singleton.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Singleton"))) @@ -848,6 +848,27 @@ library Singleton { (v2, v3, v4) = decodeDynamic(_encodedLengths, _dynamicData); } + /** Delete all data for given keys */ + function deleteRecord() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord() 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) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(int256 v1) internal pure returns (bytes memory) { return abi.encodePacked(v1); @@ -900,27 +921,6 @@ library Singleton { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord() internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord() 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) internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } function toStaticArray_uint32_2(uint32[] memory _value) pure returns (uint32[2] memory _result) { diff --git a/packages/cli/contracts/src/codegen/tables/Statics.sol b/packages/cli/contracts/src/codegen/tables/Statics.sol index 961208a783..dfb0cde25b 100644 --- a/packages/cli/contracts/src/codegen/tables/Statics.sol +++ b/packages/cli/contracts/src/codegen/tables/Statics.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; // Import user types import { Enum2, Enum1 } from "./../common.sol"; @@ -870,6 +870,45 @@ library Statics { (_table.v1, _table.v2, _table.v3, _table.v4, _table.v5, _table.v6) = decodeStatic(_staticData); } + /** Delete all data for given keys */ + function deleteRecord(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal { + bytes32[] memory _keyTuple = new bytes32[](6); + _keyTuple[0] = bytes32(uint256(k1)); + _keyTuple[1] = bytes32(uint256(int256(k2))); + _keyTuple[2] = bytes32(k3); + _keyTuple[3] = bytes32(uint256(uint160(k4))); + _keyTuple[4] = _boolToBytes32(k5); + _keyTuple[5] = bytes32(uint256(uint8(k6))); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal { + bytes32[] memory _keyTuple = new bytes32[](6); + _keyTuple[0] = bytes32(uint256(k1)); + _keyTuple[1] = bytes32(uint256(int256(k2))); + _keyTuple[2] = bytes32(k3); + _keyTuple[3] = bytes32(uint256(uint160(k4))); + _keyTuple[4] = _boolToBytes32(k5); + _keyTuple[5] = bytes32(uint256(uint8(k6))); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal { + bytes32[] memory _keyTuple = new bytes32[](6); + _keyTuple[0] = bytes32(uint256(k1)); + _keyTuple[1] = bytes32(uint256(int256(k2))); + _keyTuple[2] = bytes32(k3); + _keyTuple[3] = bytes32(uint256(uint160(k4))); + _keyTuple[4] = _boolToBytes32(k5); + _keyTuple[5] = bytes32(uint256(uint8(k6))); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic( uint256 v1, @@ -918,45 +957,6 @@ library Statics { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal { - bytes32[] memory _keyTuple = new bytes32[](6); - _keyTuple[0] = bytes32(uint256(k1)); - _keyTuple[1] = bytes32(uint256(int256(k2))); - _keyTuple[2] = bytes32(k3); - _keyTuple[3] = bytes32(uint256(uint160(k4))); - _keyTuple[4] = _boolToBytes32(k5); - _keyTuple[5] = bytes32(uint256(uint8(k6))); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal { - bytes32[] memory _keyTuple = new bytes32[](6); - _keyTuple[0] = bytes32(uint256(k1)); - _keyTuple[1] = bytes32(uint256(int256(k2))); - _keyTuple[2] = bytes32(k3); - _keyTuple[3] = bytes32(uint256(uint160(k4))); - _keyTuple[4] = _boolToBytes32(k5); - _keyTuple[5] = bytes32(uint256(uint8(k6))); - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal { - bytes32[] memory _keyTuple = new bytes32[](6); - _keyTuple[0] = bytes32(uint256(k1)); - _keyTuple[1] = bytes32(uint256(int256(k2))); - _keyTuple[2] = bytes32(k3); - _keyTuple[3] = bytes32(uint256(uint160(k4))); - _keyTuple[4] = _boolToBytes32(k5); - _keyTuple[5] = bytes32(uint256(uint8(k6))); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } function _toBool(uint8 value) pure returns (bool result) { diff --git a/packages/cli/contracts/test/Tablegen.t.sol b/packages/cli/contracts/test/Tablegen.t.sol index d5a5cbc77b..8a71d7fb9e 100644 --- a/packages/cli/contracts/test/Tablegen.t.sol +++ b/packages/cli/contracts/test/Tablegen.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0; import "forge-std/Test.sol"; import { StoreMock } from "@latticexyz/store/test/StoreMock.sol"; -import { Statics, StaticsData, Dynamics1, Dynamics1Data, Dynamics2, Dynamics2Data, Singleton, Ephemeral } from "../src/codegen/index.sol"; +import { Statics, StaticsData, Dynamics1, Dynamics1Data, Dynamics2, Dynamics2Data, Singleton, Offchain } from "../src/codegen/index.sol"; import { Enum1, Enum2 } from "../src/codegen/common.sol"; @@ -143,9 +143,9 @@ contract TablegenTest is Test, StoreMock { assertEq(Singleton.getItemV4(1), 0); } - function testEphemeral() public { - Ephemeral.register(); + function testOffchain() public { + Offchain.register(); - Ephemeral.emitEphemeral("key", 123); + Offchain.set("key", 123); } } diff --git a/packages/cli/scripts/generate-test-tables.ts b/packages/cli/scripts/generate-test-tables.ts index 74ecec0817..79d9430437 100644 --- a/packages/cli/scripts/generate-test-tables.ts +++ b/packages/cli/scripts/generate-test-tables.ts @@ -55,9 +55,9 @@ try { }, dataStruct: false, }, - Ephemeral: { + Offchain: { valueSchema: "uint256", - ephemeral: true, + offchainOnly: true, }, }, diff --git a/packages/cli/src/utils/tables/getRegisterTableCallData.ts b/packages/cli/src/utils/tables/getRegisterTableCallData.ts index 8db6cc0c43..218e89e05d 100644 --- a/packages/cli/src/utils/tables/getRegisterTableCallData.ts +++ b/packages/cli/src/utils/tables/getRegisterTableCallData.ts @@ -30,7 +30,7 @@ export function getRegisterTableCallData(table: Table, storeConfig: StoreConfig) func: "registerTable", args: [ // TODO: add support for table namespaces (https://github.com/latticexyz/mud/issues/994) - resourceIdToHex({ type: table.ephemeral ? "offchainTable" : "table", namespace: storeConfig.namespace, name }), + resourceIdToHex({ type: table.offchainOnly ? "offchainTable" : "table", namespace: storeConfig.namespace, name }), fieldLayoutToHex(fieldLayout), encodeSchema(keyTypes), encodeSchema(schemaTypes), diff --git a/packages/cli/src/utils/tables/types.ts b/packages/cli/src/utils/tables/types.ts index 2fbe66339e..21dcd8438c 100644 --- a/packages/cli/src/utils/tables/types.ts +++ b/packages/cli/src/utils/tables/types.ts @@ -4,7 +4,7 @@ export type Table = { directory: string; tableIdArgument: boolean; storeArgument: boolean; - ephemeral: boolean; + offchainOnly: boolean; name?: string | undefined; dataStruct?: boolean | undefined; }; diff --git a/packages/common/src/codegen/render-solidity/common.ts b/packages/common/src/codegen/render-solidity/common.ts index c88829706e..f956f7b658 100644 --- a/packages/common/src/codegen/render-solidity/common.ts +++ b/packages/common/src/codegen/render-solidity/common.ts @@ -162,15 +162,25 @@ export function renderWithFieldSuffix( return result; } -export function renderTableId(staticResourceData: StaticResourceData): { +export function renderTableId({ namespace, name, offchainOnly, tableIdName }: StaticResourceData): { hardcodedTableId: string; tableIdDefinition: string; } { - const hardcodedTableId = `ResourceId.wrap(bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("${staticResourceData.namespace}"), bytes16("${staticResourceData.name}"))))`; + const hardcodedTableId = ` + ResourceId.wrap( + bytes32( + abi.encodePacked( + ${offchainOnly ? "RESOURCE_OFFCHAIN_TABLE" : "RESOURCE_TABLE"}, + bytes14("${namespace}"), + bytes16("${name}") + ) + ) + ) + `; const tableIdDefinition = ` ResourceId constant _tableId = ${hardcodedTableId}; - ResourceId constant ${staticResourceData.tableIdName} = _tableId; + ResourceId constant ${tableIdName} = _tableId; `; return { hardcodedTableId, diff --git a/packages/common/src/codegen/render-solidity/types.ts b/packages/common/src/codegen/render-solidity/types.ts index cb65df5e02..833065e207 100644 --- a/packages/common/src/codegen/render-solidity/types.ts +++ b/packages/common/src/codegen/render-solidity/types.ts @@ -16,6 +16,7 @@ export interface StaticResourceData { tableIdName: string; namespace: string; name: string; + offchainOnly: boolean; } export interface RenderType { diff --git a/packages/dev-tools/src/events/EventIcon.tsx b/packages/dev-tools/src/events/EventIcon.tsx index 8b40c01690..2efbcb0d23 100644 --- a/packages/dev-tools/src/events/EventIcon.tsx +++ b/packages/dev-tools/src/events/EventIcon.tsx @@ -14,8 +14,6 @@ export function EventIcon({ type }: Props) { return +; case "StoreDeleteRecord": return -; - case "StoreEphemeralRecord": - return ~; default: return assertExhaustive(type, `Unexpected event type: ${type}`); } diff --git a/packages/dev-tools/src/events/LogsTable.tsx b/packages/dev-tools/src/events/LogsTable.tsx index 5c720f1a62..b24495a4ef 100644 --- a/packages/dev-tools/src/events/LogsTable.tsx +++ b/packages/dev-tools/src/events/LogsTable.tsx @@ -44,7 +44,7 @@ export function LogsTable({ logs }: Props) { {/* TODO: decode these values if we can */} - {log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord" + {log.eventName === "StoreSetRecord" ? JSON.stringify({ staticData: log.args.staticData, encodedLengths: log.args.encodedLengths, diff --git a/packages/store-sync/src/common.ts b/packages/store-sync/src/common.ts index c45687cca8..41caa5d2f9 100644 --- a/packages/store-sync/src/common.ts +++ b/packages/store-sync/src/common.ts @@ -78,7 +78,7 @@ export type StorageAdapter = (block: StorageAdapterBlock) => 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 = resourceIdToHex({ - type: schemasTable.ephemeral ? "offchainTable" : "table", + type: schemasTable.offchainOnly ? "offchainTable" : "table", namespace: storeConfig.namespace, name: schemasTable.name, }); diff --git a/packages/store-sync/src/postgres/postgresStorage.ts b/packages/store-sync/src/postgres/postgresStorage.ts index 4246c037cc..5b714d096c 100644 --- a/packages/store-sync/src/postgres/postgresStorage.ts +++ b/packages/store-sync/src/postgres/postgresStorage.ts @@ -96,7 +96,7 @@ export async function postgresStorage debug(log.eventName, log); - if (log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord") { + if (log.eventName === "StoreSetRecord") { const value = decodeValueArgs(table.valueSchema, log.args); debug("upserting record", { namespace: table.namespace, diff --git a/packages/store-sync/src/recs/configToRecsComponents.ts b/packages/store-sync/src/recs/configToRecsComponents.ts index de52d113b8..0e83de5a8b 100644 --- a/packages/store-sync/src/recs/configToRecsComponents.ts +++ b/packages/store-sync/src/recs/configToRecsComponents.ts @@ -28,7 +28,7 @@ export function configToRecsComponents( { // TODO: support table namespaces https://github.com/latticexyz/mud/issues/994 id: resourceIdToHex({ - type: table.ephemeral ? "offchainTable" : "table", + type: table.offchainOnly ? "offchainTable" : "table", namespace: config.namespace, name: tableName, }), diff --git a/packages/store-sync/src/recs/recsStorage.ts b/packages/store-sync/src/recs/recsStorage.ts index ce351803f7..5275ec0a58 100644 --- a/packages/store-sync/src/recs/recsStorage.ts +++ b/packages/store-sync/src/recs/recsStorage.ts @@ -80,7 +80,7 @@ export function recsStorage({ const entity = hexKeyTupleToEntity(log.args.keyTuple); - if (log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord") { + if (log.eventName === "StoreSetRecord") { const value = decodeValueArgs(table.valueSchema, log.args); debug("setting component", { namespace: table.namespace, diff --git a/packages/store-sync/src/sqlite/sqliteStorage.ts b/packages/store-sync/src/sqlite/sqliteStorage.ts index 180048279e..c0e78bcdc9 100644 --- a/packages/store-sync/src/sqlite/sqliteStorage.ts +++ b/packages/store-sync/src/sqlite/sqliteStorage.ts @@ -96,7 +96,7 @@ export async function sqliteStorage({ const uniqueKey = concatHex(log.args.keyTuple as Hex[]); const key = decodeKey(table.keySchema, log.args.keyTuple); - if (log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord") { + if (log.eventName === "StoreSetRecord") { const value = decodeValueArgs(table.valueSchema, log.args); debug("upserting record", { namespace: table.namespace, diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 6f8ba5f968..3c65f6ecb2 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": 720082 + "gasUsed": 720118 }, { "file": "test/Mixed.t.sol", @@ -363,13 +363,13 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Mixed table", - "gasUsed": 581907 + "gasUsed": 581944 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 103942 + "gasUsed": 103976 }, { "file": "test/Mixed.t.sol", @@ -621,25 +621,25 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 19440 + "gasUsed": 19449 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 13450 + "gasUsed": 13457 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 17208 + "gasUsed": 17217 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 13219 + "gasUsed": 13225 }, { "file": "test/StoreCoreGas.t.sol", @@ -675,7 +675,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 6700 + "gasUsed": 6735 }, { "file": "test/StoreCoreGas.t.sol", @@ -693,67 +693,67 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 58696 + "gasUsed": 58766 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 71265 + "gasUsed": 71311 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 20746 + "gasUsed": 20788 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 16736 + "gasUsed": 16784 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 58696 + "gasUsed": 58766 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 164386 + "gasUsed": 164432 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 24513 + "gasUsed": 24552 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 17721 + "gasUsed": 17769 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 10264 + "gasUsed": 10260 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 32940 + "gasUsed": 32930 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 642028 + "gasUsed": 642065 }, { "file": "test/StoreCoreGas.t.sol", @@ -777,7 +777,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 101840 + "gasUsed": 101874 }, { "file": "test/StoreCoreGas.t.sol", @@ -819,7 +819,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 31601 + "gasUsed": 31604 }, { "file": "test/StoreCoreGas.t.sol", @@ -831,7 +831,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 30241 + "gasUsed": 30245 }, { "file": "test/StoreCoreGas.t.sol", @@ -843,7 +843,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 53966 + "gasUsed": 53959 }, { "file": "test/StoreCoreGas.t.sol", @@ -855,7 +855,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 32192 + "gasUsed": 32182 }, { "file": "test/StoreCoreGas.t.sol", @@ -867,7 +867,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 32145 + "gasUsed": 32179 }, { "file": "test/StoreCoreGas.t.sol", @@ -879,7 +879,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 54650 + "gasUsed": 54684 }, { "file": "test/StoreCoreGas.t.sol", @@ -891,13 +891,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 9608 + "gasUsed": 9604 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 10045 + "gasUsed": 10043 }, { "file": "test/StoreHook.t.sol", @@ -939,7 +939,7 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 57052 + "gasUsed": 57051 }, { "file": "test/tables/Callbacks.t.sol", @@ -951,19 +951,19 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 33337 + "gasUsed": 33332 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 59054 + "gasUsed": 59057 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 59054 + "gasUsed": 59057 }, { "file": "test/tables/StoreHooks.t.sol", @@ -975,37 +975,37 @@ "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 13431 + "gasUsed": 13430 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 10739 + "gasUsed": 10743 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 11453 + "gasUsed": 11447 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 30668 + "gasUsed": 30659 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 7128 + "gasUsed": 7163 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 31215 + "gasUsed": 31201 }, { "file": "test/tables/StoreHooks.t.sol", @@ -1023,7 +1023,7 @@ "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 15996 + "gasUsed": 16031 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", @@ -1047,13 +1047,13 @@ "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 19168 + "gasUsed": 19178 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 21111 + "gasUsed": 21114 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -1107,13 +1107,13 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 443350 + "gasUsed": 443387 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 33069 + "gasUsed": 33103 }, { "file": "test/Vector2.t.sol", diff --git a/packages/store/src/IStore.sol b/packages/store/src/IStore.sol index f73f4f4c46..cae2ec6f36 100644 --- a/packages/store/src/IStore.sol +++ b/packages/store/src/IStore.sol @@ -179,26 +179,6 @@ interface IStoreWrite { function deleteRecord(ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) external; } -interface IStoreEphemeral { - event StoreEphemeralRecord( - ResourceId indexed tableId, - bytes32[] keyTuple, - bytes staticData, - bytes32 encodedLengths, - bytes dynamicData - ); - - // Emit the ephemeral event without modifying storage - function emitEphemeralRecord( - ResourceId tableId, - bytes32[] calldata keyTuple, - bytes calldata staticData, - PackedCounter encodedLengths, - bytes calldata dynamicData, - FieldLayout fieldLayout - ) external; -} - /** * The IStoreData interface includes methods for reading and writing table values. * These methods are frequently invoked during runtime, so it is essential to prioritize @@ -230,4 +210,4 @@ interface IStoreRegistration { function unregisterStoreHook(ResourceId tableId, IStoreHook hookAddress) external; } -interface IStore is IStoreData, IStoreRegistration, IStoreEphemeral, IStoreErrors {} +interface IStore is IStoreData, IStoreRegistration, IStoreErrors {} diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index d4683aaa10..f5baaa3546 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -50,13 +50,6 @@ library StoreCore { bytes32 encodedLengths ); event StoreDeleteRecord(ResourceId indexed tableId, bytes32[] keyTuple); - event StoreEphemeralRecord( - ResourceId indexed tableId, - bytes32[] keyTuple, - bytes staticData, - bytes32 encodedLengths, - bytes dynamicData - ); /** * Intialize the store address to use in StoreSwitch. @@ -187,6 +180,11 @@ library StoreCore { * Register hooks to be called when a record or field is set or deleted */ function registerStoreHook(ResourceId tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) internal { + // Hooks are only supported for tables, not for offchain tables + if (tableId.getType() != RESOURCE_TABLE) { + revert IStoreErrors.StoreCore_InvalidResourceType(RESOURCE_TABLE, tableId, string(abi.encodePacked(tableId))); + } + StoreHooks.push(ResourceId.unwrap(tableId), Hook.unwrap(HookLib.encode(address(hookAddress), enabledHooksBitmap))); } @@ -223,6 +221,11 @@ library StoreCore { // Emit event to notify indexers emit StoreSetRecord(tableId, keyTuple, staticData, encodedLengths.unwrap(), dynamicData); + // Early return if the table is an offchain table + if (tableId.getType() != RESOURCE_TABLE) { + return; + } + // Call onBeforeSetRecord hooks (before actually modifying the state, so observers have access to the previous state if needed) bytes21[] memory hooks = StoreHooks._get(ResourceId.unwrap(tableId)); for (uint256 i; i < hooks.length; i++) { @@ -302,6 +305,20 @@ library StoreCore { ) internal { uint256 location = StoreCoreInternal._getStaticDataLocation(tableId, keyTuple); + // Emit event to notify offchain indexers + emit StoreCore.StoreSpliceStaticData({ + tableId: tableId, + keyTuple: keyTuple, + start: start, + deleteCount: deleteCount, + data: data + }); + + // Early return if the table is an offchain table + if (tableId.getType() != RESOURCE_TABLE) { + return; + } + // Call onBeforeSpliceStaticData hooks (before actually modifying the state, so observers have access to the previous state if needed) bytes21[] memory hooks = StoreHooks._get(ResourceId.unwrap(tableId)); for (uint256 i; i < hooks.length; i++) { @@ -333,15 +350,6 @@ library StoreCore { }); } } - - // Emit event to notify offchain indexers - emit StoreCore.StoreSpliceStaticData({ - tableId: tableId, - keyTuple: keyTuple, - start: start, - deleteCount: deleteCount, - data: data - }); } function spliceDynamicData( @@ -424,6 +432,11 @@ library StoreCore { // Emit event to notify indexers emit StoreDeleteRecord(tableId, keyTuple); + // Early return if the table is an offchain table + if (tableId.getType() != RESOURCE_TABLE) { + return; + } + // Call onBeforeDeleteRecord hooks (before actually modifying the state, so observers have access to the previous state if needed) bytes21[] memory hooks = StoreHooks._get(ResourceId.unwrap(tableId)); for (uint256 i; i < hooks.length; i++) { @@ -510,30 +523,6 @@ library StoreCore { StoreCoreInternal._setDynamicFieldItem(tableId, keyTuple, fieldLayout, fieldIndex, startByteIndex, dataToSet); } - /************************************************************************ - * - * EPHEMERAL SET DATA - * - ************************************************************************/ - - /** - * Emit the ephemeral event without modifying storage for the full data of the given table ID and key tuple - */ - function emitEphemeralRecord( - ResourceId tableId, - bytes32[] memory keyTuple, - bytes memory staticData, - PackedCounter encodedLengths, - bytes memory dynamicData, - FieldLayout fieldLayout - ) internal { - // Verify static data length + dynamic data length matches the given data - StoreCoreInternal._validateDataLength(fieldLayout, staticData, encodedLengths, dynamicData); - - // Emit event to notify indexers - emit StoreEphemeralRecord(tableId, keyTuple, staticData, encodedLengths.unwrap(), dynamicData); - } - /************************************************************************ * * GET DATA @@ -674,6 +663,8 @@ library StoreCore { } library StoreCoreInternal { + using ResourceIdInstance for ResourceId; + bytes32 internal constant SLOT = keccak256("mud.store"); bytes32 internal constant DYNMAIC_DATA_SLOT = keccak256("mud.store.dynamicData"); bytes32 internal constant DYNAMIC_DATA_LENGTH_SLOT = keccak256("mud.store.dynamicDataLength"); @@ -693,6 +684,12 @@ library StoreCoreInternal { bytes memory data, PackedCounter previousEncodedLengths ) internal { + // Splicing dynamic data is not supported for offchain tables, because it + // requires reading the previous encoded lengths from storage + if (tableId.getType() != RESOURCE_TABLE) { + revert IStoreErrors.StoreCore_InvalidResourceType(RESOURCE_TABLE, tableId, string(abi.encodePacked(tableId))); + } + uint256 previousFieldLength = previousEncodedLengths.atIndex(dynamicFieldIndex); uint256 updatedFieldLength = previousFieldLength - deleteCount + data.length; @@ -714,6 +711,16 @@ library StoreCoreInternal { // Update the encoded length PackedCounter updatedEncodedLengths = previousEncodedLengths.setAtIndex(dynamicFieldIndex, updatedFieldLength); + // Emit event to notify offchain indexers + emit StoreCore.StoreSpliceDynamicData({ + tableId: tableId, + keyTuple: keyTuple, + start: uint48(start), + deleteCount: deleteCount, + data: data, + encodedLengths: updatedEncodedLengths.unwrap() + }); + // Call onBeforeSpliceDynamicData hooks (before actually modifying the state, so observers have access to the previous state if needed) bytes21[] memory hooks = StoreHooks._get(ResourceId.unwrap(tableId)); for (uint256 i; i < hooks.length; i++) { @@ -758,16 +765,6 @@ library StoreCoreInternal { }); } } - - // Emit event to notify offchain indexers - emit StoreCore.StoreSpliceDynamicData({ - tableId: tableId, - keyTuple: keyTuple, - start: uint48(start), - deleteCount: deleteCount, - data: data, - encodedLengths: updatedEncodedLengths.unwrap() - }); } function _pushToDynamicField( diff --git a/packages/store/src/StoreSwitch.sol b/packages/store/src/StoreSwitch.sol index caa043ebfe..ba483f2dea 100644 --- a/packages/store/src/StoreSwitch.sol +++ b/packages/store/src/StoreSwitch.sol @@ -234,29 +234,6 @@ library StoreSwitch { } } - function emitEphemeralRecord( - ResourceId tableId, - bytes32[] memory keyTuple, - bytes memory staticData, - PackedCounter encodedLengths, - bytes memory dynamicData, - FieldLayout fieldLayout - ) internal { - address _storeAddress = getStoreAddress(); - if (_storeAddress == address(this)) { - StoreCore.emitEphemeralRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); - } else { - IStore(_storeAddress).emitEphemeralRecord( - tableId, - keyTuple, - staticData, - encodedLengths, - dynamicData, - fieldLayout - ); - } - } - function getRecord( ResourceId tableId, bytes32[] memory keyTuple, diff --git a/packages/store/src/codegen/tables/Callbacks.sol b/packages/store/src/codegen/tables/Callbacks.sol index e7c1e00837..4dcbce5052 100644 --- a/packages/store/src/codegen/tables/Callbacks.sol +++ b/packages/store/src/codegen/tables/Callbacks.sol @@ -18,7 +18,7 @@ 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "../../storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("Callbacks"))) @@ -532,6 +532,30 @@ library Callbacks { } } + /** Delete all data for given keys */ + function deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack dynamic data using this table's schema */ function encodeLengths(bytes24[] memory value) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits @@ -561,28 +585,4 @@ library Callbacks { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/store/src/codegen/tables/Hooks.sol b/packages/store/src/codegen/tables/Hooks.sol index ed26828797..34f6c804cf 100644 --- a/packages/store/src/codegen/tables/Hooks.sol +++ b/packages/store/src/codegen/tables/Hooks.sol @@ -18,7 +18,7 @@ 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "../../storeResourceTypes.sol"; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 @@ -532,6 +532,30 @@ library Hooks { } } + /** Delete all data for given keys */ + function deleteRecord(ResourceId _tableId, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(ResourceId _tableId, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, ResourceId _tableId, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack dynamic data using this table's schema */ function encodeLengths(bytes21[] memory value) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits @@ -561,28 +585,4 @@ library Hooks { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(ResourceId _tableId, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(ResourceId _tableId, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, ResourceId _tableId, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/store/src/codegen/tables/KeyEncoding.sol b/packages/store/src/codegen/tables/KeyEncoding.sol index 4f5afd260d..6a198c2d27 100644 --- a/packages/store/src/codegen/tables/KeyEncoding.sol +++ b/packages/store/src/codegen/tables/KeyEncoding.sol @@ -18,7 +18,7 @@ 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "../../storeResourceTypes.sol"; // Import user types import { ExampleEnum } from "./../common.sol"; @@ -315,30 +315,8 @@ library KeyEncoding { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } - /** Tightly pack static data using this table's schema */ - function encodeStatic(bool value) internal pure returns (bytes memory) { - return abi.encodePacked(value); - } - - /** Tightly pack full data using this table's field layout */ - function encode(bool value) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(value); - - PackedCounter _encodedLengths; - bytes memory _dynamicData; - - return (_staticData, _encodedLengths, _dynamicData); - } - - /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple( - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - ExampleEnum k6 - ) internal pure returns (bytes32[] memory) { + /** Delete all data for given keys */ + function deleteRecord(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, ExampleEnum k6) internal { bytes32[] memory _keyTuple = new bytes32[](6); _keyTuple[0] = bytes32(uint256(k1)); _keyTuple[1] = bytes32(uint256(int256(k2))); @@ -347,11 +325,11 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - return _keyTuple; + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ - function deleteRecord(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, ExampleEnum k6) internal { + /** Delete all data for given keys */ + function _deleteRecord(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, ExampleEnum k6) internal { bytes32[] memory _keyTuple = new bytes32[](6); _keyTuple[0] = bytes32(uint256(k1)); _keyTuple[1] = bytes32(uint256(int256(k2))); @@ -360,11 +338,11 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ - function _deleteRecord(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, ExampleEnum k6) internal { + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, ExampleEnum k6) internal { bytes32[] memory _keyTuple = new bytes32[](6); _keyTuple[0] = bytes32(uint256(k1)); _keyTuple[1] = bytes32(uint256(int256(k2))); @@ -373,11 +351,33 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, ExampleEnum k6) internal { + /** Tightly pack static data using this table's schema */ + function encodeStatic(bool value) internal pure returns (bytes memory) { + return abi.encodePacked(value); + } + + /** Tightly pack full data using this table's field layout */ + function encode(bool value) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** Encode keys as a bytes32 array using this table's field layout */ + function encodeKeyTuple( + uint256 k1, + int32 k2, + bytes16 k3, + address k4, + bool k5, + ExampleEnum k6 + ) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](6); _keyTuple[0] = bytes32(uint256(k1)); _keyTuple[1] = bytes32(uint256(int256(k2))); @@ -386,7 +386,7 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + return _keyTuple; } } diff --git a/packages/store/src/codegen/tables/Mixed.sol b/packages/store/src/codegen/tables/Mixed.sol index 995a84f49c..48c8678ba9 100644 --- a/packages/store/src/codegen/tables/Mixed.sol +++ b/packages/store/src/codegen/tables/Mixed.sol @@ -18,7 +18,7 @@ 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "../../storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("Mixed"))) @@ -772,6 +772,30 @@ library Mixed { (_table.a32, _table.s) = decodeDynamic(_encodedLengths, _dynamicData); } + /** Delete all data for given keys */ + function deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(uint32 u32, uint128 u128) internal pure returns (bytes memory) { return abi.encodePacked(u32, u128); @@ -812,28 +836,4 @@ library Mixed { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/store/src/codegen/tables/ResourceIds.sol b/packages/store/src/codegen/tables/ResourceIds.sol index 229d236416..273a4c6fb0 100644 --- a/packages/store/src/codegen/tables/ResourceIds.sol +++ b/packages/store/src/codegen/tables/ResourceIds.sol @@ -18,7 +18,7 @@ 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "../../storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("ResourceIds"))) @@ -180,6 +180,30 @@ library ResourceIds { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); } + /** 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); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(bool exists) internal pure returns (bytes memory) { return abi.encodePacked(exists); @@ -202,30 +226,6 @@ library ResourceIds { 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) { diff --git a/packages/store/src/codegen/tables/StoreHooks.sol b/packages/store/src/codegen/tables/StoreHooks.sol index bba07c02cd..b900ad3640 100644 --- a/packages/store/src/codegen/tables/StoreHooks.sol +++ b/packages/store/src/codegen/tables/StoreHooks.sol @@ -18,7 +18,7 @@ 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "../../storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("StoreHooks"))) @@ -532,6 +532,30 @@ library StoreHooks { } } + /** Delete all data for given keys */ + function deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack dynamic data using this table's schema */ function encodeLengths(bytes21[] memory value) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits @@ -561,28 +585,4 @@ library StoreHooks { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/store/src/codegen/tables/Tables.sol b/packages/store/src/codegen/tables/Tables.sol index 3e4c7b0724..04d49cd786 100644 --- a/packages/store/src/codegen/tables/Tables.sol +++ b/packages/store/src/codegen/tables/Tables.sol @@ -18,7 +18,7 @@ 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "../../storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("Tables"))) @@ -888,6 +888,30 @@ library Tables { (_table.abiEncodedKeyNames, _table.abiEncodedFieldNames) = decodeDynamic(_encodedLengths, _dynamicData); } + /** Delete all data for given keys */ + function deleteRecord(bytes32 tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic( bytes32 fieldLayout, @@ -939,28 +963,4 @@ library Tables { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 tableId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = tableId; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 tableId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = tableId; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 tableId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = tableId; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/store/src/codegen/tables/Vector2.sol b/packages/store/src/codegen/tables/Vector2.sol index cb95a745ea..71f23b8be2 100644 --- a/packages/store/src/codegen/tables/Vector2.sol +++ b/packages/store/src/codegen/tables/Vector2.sol @@ -18,7 +18,7 @@ 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "../../storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14("mudstore"), bytes16("Vector2"))) @@ -302,6 +302,30 @@ library Vector2 { (_table.x, _table.y) = decodeStatic(_staticData); } + /** Delete all data for given keys */ + function deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(uint32 x, uint32 y) internal pure returns (bytes memory) { return abi.encodePacked(x, y); @@ -324,28 +348,4 @@ library Vector2 { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/store/test/StoreMock.sol b/packages/store/test/StoreMock.sol index 14eb95c89b..fab796a8f1 100644 --- a/packages/store/test/StoreMock.sol +++ b/packages/store/test/StoreMock.sol @@ -103,18 +103,6 @@ contract StoreMock is IStore, StoreRead { StoreCore.deleteRecord(tableId, keyTuple, fieldLayout); } - // Emit the ephemeral event without modifying storage - function emitEphemeralRecord( - ResourceId tableId, - bytes32[] calldata keyTuple, - bytes calldata staticData, - PackedCounter encodedLengths, - bytes calldata dynamicData, - FieldLayout fieldLayout - ) public { - StoreCore.emitEphemeralRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); - } - function registerTable( ResourceId tableId, FieldLayout fieldLayout, diff --git a/packages/store/ts/codegen/ephemeral.ts b/packages/store/ts/codegen/ephemeral.ts deleted file mode 100644 index df57892d8a..0000000000 --- a/packages/store/ts/codegen/ephemeral.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { renderArguments, renderCommonData, renderWithStore } from "@latticexyz/common/codegen"; -import { RenderTableOptions } from "./types"; -import { renderRecordData } from "./record"; - -export function renderEphemeralMethods(options: RenderTableOptions) { - const { structName, storeArgument } = options; - const { _tableId, _typedTableId, _keyArgs, _typedKeyArgs, _keyTupleDefinition } = renderCommonData(options); - - let result = renderWithStore( - storeArgument, - (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` - /** Emit the ephemeral event using individual values${_commentSuffix} */ - function ${_methodNamePrefix}emitEphemeral(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - renderArguments(options.fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`)), - ])}) internal { - ${renderRecordData(options)} - - ${_keyTupleDefinition} - - ${_store}.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); - } - ` - ); - - if (structName !== undefined) { - result += renderWithStore( - storeArgument, - (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` - /** Emit the ephemeral event using the data struct${_commentSuffix} */ - function ${_methodNamePrefix}emitEphemeral(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - `${structName} memory _table`, - ])}) internal { - emitEphemeral(${renderArguments([ - _untypedStore, - _tableId, - _keyArgs, - renderArguments(options.fields.map(({ name }) => `_table.${name}`)), - ])}); - } - ` - ); - } - - return result; -} diff --git a/packages/store/ts/codegen/field.ts b/packages/store/ts/codegen/field.ts index c65307e2f7..6fad585ca1 100644 --- a/packages/store/ts/codegen/field.ts +++ b/packages/store/ts/codegen/field.ts @@ -14,40 +14,45 @@ export function renderFieldMethods(options: RenderTableOptions) { let result = ""; for (const [schemaIndex, field] of options.fields.entries()) { - // For dynamic fields, compute the field index relative to the end of the static fields + if (!options.withDynamicFieldMethods && field.isDynamic) { + continue; + } + // For dynamic fields, compute the field index relative to the end of the static fields const _typedFieldName = `${field.typeWithLocation} ${field.name}`; - result += renderWithFieldSuffix(options.withSuffixlessFieldMethods, field.name, (_methodNameSuffix) => - renderWithStore( - storeArgument, - (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` - /** Get ${field.name}${_commentSuffix} */ - function ${_methodNamePrefix}get${_methodNameSuffix}(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - ])}) internal view returns (${_typedFieldName}) { - ${_keyTupleDefinition} - ${ - field.isDynamic - ? `bytes memory _blob = ${_store}.getDynamicField( - _tableId, - _keyTuple, - ${schemaIndex - options.staticFields.length} - );` - : `bytes32 _blob = ${_store}.getStaticField( - _tableId, - _keyTuple, - ${schemaIndex}, - _fieldLayout - );` + if (options.withGetters) { + result += renderWithFieldSuffix(options.withSuffixlessFieldMethods, field.name, (_methodNameSuffix) => + renderWithStore( + storeArgument, + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` + /** Get ${field.name}${_commentSuffix} */ + function ${_methodNamePrefix}get${_methodNameSuffix}(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + ])}) internal view returns (${_typedFieldName}) { + ${_keyTupleDefinition} + ${ + field.isDynamic + ? `bytes memory _blob = ${_store}.getDynamicField( + _tableId, + _keyTuple, + ${schemaIndex - options.staticFields.length} + );` + : `bytes32 _blob = ${_store}.getStaticField( + _tableId, + _keyTuple, + ${schemaIndex}, + _fieldLayout + );` + } + return ${renderDecodeFieldSingle(field)}; } - return ${renderDecodeFieldSingle(field)}; - } ` - ) - ); + ) + ); + } result += renderWithFieldSuffix(options.withSuffixlessFieldMethods, field.name, (_methodNameSuffix) => renderWithStore( @@ -70,40 +75,41 @@ export function renderFieldMethods(options: RenderTableOptions) { if (field.isDynamic) { const portionData = fieldPortionData(field); - result += renderWithFieldSuffix(options.withSuffixlessFieldMethods, field.name, (_methodNameSuffix) => - renderWithStore( - storeArgument, - (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` - /** Get the length of ${field.name}${_commentSuffix} */ - function ${_methodNamePrefix}length${_methodNameSuffix}(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - ])}) internal view returns (uint256) { - ${_keyTupleDefinition} - uint256 _byteLength = ${_store}.getFieldLength(_tableId, _keyTuple, ${schemaIndex}, _fieldLayout); - unchecked { - return _byteLength / ${portionData.elementLength}; + if (options.withGetters) { + result += renderWithFieldSuffix(options.withSuffixlessFieldMethods, field.name, (_methodNameSuffix) => + renderWithStore( + storeArgument, + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` + /** Get the length of ${field.name}${_commentSuffix} */ + function ${_methodNamePrefix}length${_methodNameSuffix}(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + ])}) internal view returns (uint256) { + ${_keyTupleDefinition} + uint256 _byteLength = ${_store}.getFieldLength(_tableId, _keyTuple, ${schemaIndex}, _fieldLayout); + unchecked { + return _byteLength / ${portionData.elementLength}; + } } - } ` - ) - ); + ) + ); - result += renderWithFieldSuffix(options.withSuffixlessFieldMethods, field.name, (_methodNameSuffix) => - renderWithStore( - storeArgument, - (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` - /** - * Get an item of ${field.name}${_commentSuffix} - * (unchecked, returns invalid data if index overflows) - */ - function ${_methodNamePrefix}getItem${_methodNameSuffix}(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - "uint256 _index", - ])}) internal view returns (${portionData.typeWithLocation}) { + result += renderWithFieldSuffix(options.withSuffixlessFieldMethods, field.name, (_methodNameSuffix) => + renderWithStore( + storeArgument, + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` + /** + * Get an item of ${field.name}${_commentSuffix} + * (unchecked, returns invalid data if index overflows) + */ + function ${_methodNamePrefix}getItem${_methodNameSuffix}(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + "uint256 _index", + ])}) internal view returns (${portionData.typeWithLocation}) { ${_keyTupleDefinition} unchecked { bytes memory _blob = ${_store}.getFieldSlice( @@ -113,20 +119,21 @@ export function renderFieldMethods(options: RenderTableOptions) { _fieldLayout, _index * ${portionData.elementLength}, (_index + 1) * ${portionData.elementLength} - ); - return ${portionData.decoded}; + ); + return ${portionData.decoded}; + } } - } - ` - ) - ); + ` + ) + ); + } result += renderWithFieldSuffix(options.withSuffixlessFieldMethods, field.name, (_methodNameSuffix) => renderWithStore( storeArgument, (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` - /** Push ${portionData.title} to ${field.name}${_commentSuffix} */ - function ${_methodNamePrefix}push${_methodNameSuffix}(${renderArguments([ + /** Push ${portionData.title} to ${field.name}${_commentSuffix} */ + function ${_methodNamePrefix}push${_methodNameSuffix}(${renderArguments([ _typedStore, _typedTableId, _typedKeyArgs, @@ -135,7 +142,7 @@ export function renderFieldMethods(options: RenderTableOptions) { ${_keyTupleDefinition} ${_store}.pushToField(_tableId, _keyTuple, ${schemaIndex}, ${portionData.encoded}, _fieldLayout); } - ` + ` ) ); diff --git a/packages/store/ts/codegen/record.ts b/packages/store/ts/codegen/record.ts index 7f1636ce62..bca8884879 100644 --- a/packages/store/ts/codegen/record.ts +++ b/packages/store/ts/codegen/record.ts @@ -12,26 +12,30 @@ export function renderRecordMethods(options: RenderTableOptions) { const { structName, storeArgument } = options; const { _tableId, _typedTableId, _keyArgs, _typedKeyArgs, _keyTupleDefinition } = renderCommonData(options); - let result = renderWithStore( - storeArgument, - (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` - /** Get the full data${_commentSuffix} */ - function ${_methodNamePrefix}get(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - ])}) internal view returns (${renderDecodedRecord(options)}) { - ${_keyTupleDefinition} + let result = ""; - ( - bytes memory _staticData, - PackedCounter _encodedLengths, - bytes memory _dynamicData - ) = ${_store}.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_staticData, _encodedLengths, _dynamicData); - } - ` - ); + if (options.withGetters) { + result += renderWithStore( + storeArgument, + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` + /** Get the full data${_commentSuffix} */ + function ${_methodNamePrefix}get(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + ])}) internal view returns (${renderDecodedRecord(options)}) { + ${_keyTupleDefinition} + + ( + bytes memory _staticData, + PackedCounter _encodedLengths, + bytes memory _dynamicData + ) = ${_store}.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_staticData, _encodedLengths, _dynamicData); + } + ` + ); + } result += renderWithStore( storeArgument, @@ -104,6 +108,26 @@ export function renderRecordData(options: RenderTableOptions) { return result; } +export function renderDeleteRecordMethods(options: RenderTableOptions) { + const { storeArgument } = options; + const { _typedTableId, _typedKeyArgs, _keyTupleDefinition } = renderCommonData(options); + + return renderWithStore( + storeArgument, + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` + /** Delete all data for given keys${_commentSuffix} */ + function ${_methodNamePrefix}deleteRecord(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + ])}) internal { + ${_keyTupleDefinition} + ${_store}.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + ` + ); +} + // Renders the `decode` function that parses a bytes blob into the table data function renderDecodeFunctions({ structName, fields, staticFields, dynamicFields }: RenderTableOptions) { // either set struct properties, or just variables diff --git a/packages/store/ts/codegen/renderTable.ts b/packages/store/ts/codegen/renderTable.ts index 0e97775183..e941e5c017 100644 --- a/packages/store/ts/codegen/renderTable.ts +++ b/packages/store/ts/codegen/renderTable.ts @@ -10,9 +10,8 @@ import { renderedSolidityHeader, RenderStaticField, } from "@latticexyz/common/codegen"; -import { renderEphemeralMethods } from "./ephemeral"; import { renderEncodeFieldSingle, renderFieldMethods } from "./field"; -import { renderRecordData, renderRecordMethods } from "./record"; +import { renderDeleteRecordMethods, renderRecordData, renderRecordMethods } from "./record"; import { renderFieldLayout } from "./renderFieldLayout"; import { RenderTableOptions } from "./types"; @@ -26,15 +25,12 @@ export function renderTable(options: RenderTableOptions) { fields, staticFields, dynamicFields, - withFieldMethods, withRecordMethods, - withEphemeralMethods, storeArgument, keyTuple, } = options; const { _typedTableId, _typedKeyArgs, _keyTupleDefinition } = renderCommonData(options); - const shouldRenderDelete = !withEphemeralMethods; return ` ${renderedSolidityHeader} @@ -54,7 +50,7 @@ export function renderTable(options: RenderTableOptions) { 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"; + import { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "${storeImportPath}storeResourceTypes.sol"; ${ imports.length > 0 @@ -123,11 +119,11 @@ export function renderTable(options: RenderTableOptions) { ` )} - ${withFieldMethods ? renderFieldMethods(options) : ""} + ${renderFieldMethods(options)} ${withRecordMethods ? renderRecordMethods(options) : ""} - ${withEphemeralMethods ? renderEphemeralMethods(options) : ""} + ${renderDeleteRecordMethods(options)} ${renderEncodeStatic(staticFields)} @@ -149,25 +145,6 @@ export function renderTable(options: RenderTableOptions) { ${_keyTupleDefinition} return _keyTuple; } - - ${ - shouldRenderDelete - ? renderWithStore( - storeArgument, - (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` - /* Delete all data for given keys${_commentSuffix} */ - function ${_methodNamePrefix}deleteRecord(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - ])}) internal { - ${_keyTupleDefinition} - ${_store}.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - ` - ) - : "" - } } ${renderTypeHelpers(options)} diff --git a/packages/store/ts/codegen/tableOptions.ts b/packages/store/ts/codegen/tableOptions.ts index fe66118099..c1f19d91ce 100644 --- a/packages/store/ts/codegen/tableOptions.ts +++ b/packages/store/ts/codegen/tableOptions.ts @@ -26,8 +26,8 @@ export function getTableOptions(config: StoreConfig): TableOptions[] { // struct adds methods to get/set all values at once const withStruct = tableData.dataStruct; - // operate on all fields at once; for only 1 field keep them only if struct is also kept - const withRecordMethods = withStruct || Object.keys(tableData.valueSchema).length > 1; + // operate on all fields at once; always render for offchain tables; for only 1 field keep them if struct is also kept + const withRecordMethods = withStruct || tableData.offchainOnly || Object.keys(tableData.valueSchema).length > 1; // field methods can include simply get/set if there's only 1 field and no record methods const withSuffixlessFieldMethods = !withRecordMethods && Object.keys(tableData.valueSchema).length === 1; // list of any symbols that need to be imported @@ -79,6 +79,7 @@ export function getTableOptions(config: StoreConfig): TableOptions[] { tableIdName: tableName + "TableId", namespace: config.namespace, name: tableData.name, + offchainOnly: tableData.offchainOnly, }; } })(); @@ -96,9 +97,9 @@ export function getTableOptions(config: StoreConfig): TableOptions[] { fields, staticFields, dynamicFields, - withFieldMethods: !tableData.ephemeral, - withRecordMethods: withRecordMethods && !tableData.ephemeral, - withEphemeralMethods: tableData.ephemeral, + withGetters: !tableData.offchainOnly, + withRecordMethods, + withDynamicFieldMethods: !tableData.offchainOnly, withSuffixlessFieldMethods, storeArgument: tableData.storeArgument, }, diff --git a/packages/store/ts/codegen/types.ts b/packages/store/ts/codegen/types.ts index ff01d2e2de..96ea355f53 100644 --- a/packages/store/ts/codegen/types.ts +++ b/packages/store/ts/codegen/types.ts @@ -22,12 +22,12 @@ export interface RenderTableOptions { fields: RenderField[]; staticFields: RenderStaticField[]; dynamicFields: RenderDynamicField[]; - /** Whether to render methods for individual fields (get/set, and more for dynamic elements) */ - withFieldMethods: boolean; + /** Whether to render getter functions */ + withGetters: boolean; + /** Whether to render dynamic field methods (push, pop, update) */ + withDynamicFieldMethods: boolean; /** Whether to render get/set methods for the whole record */ withRecordMethods: boolean; - /** Whether to render emitEphemeral methods */ - withEphemeralMethods: boolean; /** Whether to additionally render field methods without a field name suffix */ withSuffixlessFieldMethods: boolean; /** Whether to render additional methods that accept a manual `IStore` argument */ diff --git a/packages/store/ts/config/defaults.ts b/packages/store/ts/config/defaults.ts index 0393830547..be7dfd58e7 100644 --- a/packages/store/ts/config/defaults.ts +++ b/packages/store/ts/config/defaults.ts @@ -15,5 +15,5 @@ export const TABLE_DEFAULTS = { keySchema: { key: "bytes32" }, tableIdArgument: false, storeArgument: true, - ephemeral: false, + offchainOnly: false, } as const; diff --git a/packages/store/ts/config/storeConfig.ts b/packages/store/ts/config/storeConfig.ts index 36a951b862..dd0627424a 100644 --- a/packages/store/ts/config/storeConfig.ts +++ b/packages/store/ts/config/storeConfig.ts @@ -86,8 +86,8 @@ export interface TableConfig< storeArgument?: boolean; /** Include a data struct and methods for it. Default is false for 1-column tables; true for multi-column tables. */ dataStruct?: boolean; - /** Generate only `emitEphemeral` which emits an event without writing to storage. Default is false. */ - ephemeral?: boolean; + /** Offchain tables don't write to onchain storage, but only emit events for offchain clients. Default is false. */ + offchainOnly?: boolean; /** * Table's key names mapped to their types. * Default is `{ key: "bytes32" }` @@ -119,7 +119,7 @@ export interface ExpandTableConfig, TableN // dataStruct isn't expanded, because its value is conditional on the number of value schema fields dataStruct: boolean; keySchema: typeof TABLE_DEFAULTS.keySchema; - ephemeral: typeof TABLE_DEFAULTS.ephemeral; + offchainOnly: typeof TABLE_DEFAULTS.offchainOnly; } > { valueSchema: ExpandSchemaConfig; @@ -134,7 +134,7 @@ const zFullTableConfig = z dataStruct: z.boolean().optional(), keySchema: zKeySchema, valueSchema: zSchemaConfig, - ephemeral: z.boolean().default(TABLE_DEFAULTS.ephemeral), + offchainOnly: z.boolean().default(TABLE_DEFAULTS.offchainOnly), }) .transform((arg) => { // default dataStruct value depends on value schema's length diff --git a/packages/store/ts/storeEvents.ts b/packages/store/ts/storeEvents.ts index 5f1d1a23a9..67de4dd645 100644 --- a/packages/store/ts/storeEvents.ts +++ b/packages/store/ts/storeEvents.ts @@ -2,6 +2,5 @@ export const storeEvents = [ "event StoreSetRecord(bytes32 indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData)", "event StoreSpliceStaticData(bytes32 indexed tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data)", "event StoreSpliceDynamicData(bytes32 indexed tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data, bytes32 encodedLengths)", - "event StoreEphemeralRecord(bytes32 indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData)", "event StoreDeleteRecord(bytes32 indexed tableId, bytes32[] keyTuple)", ] as const; diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 1a53c2c895..46c6292db7 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -39,67 +39,67 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1414600 + "gasUsed": 1414806 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1414600 + "gasUsed": 1414806 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 158308 + "gasUsed": 158382 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1414600 + "gasUsed": 1414806 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1414600 + "gasUsed": 1414806 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 22290 + "gasUsed": 22324 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 160543 + "gasUsed": 160664 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1414600 + "gasUsed": 1414806 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 21012 + "gasUsed": 21046 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 85675 + "gasUsed": 85764 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 664896 + "gasUsed": 665200 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,49 +117,49 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 664896 + "gasUsed": 665200 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 135679 + "gasUsed": 135760 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 664896 + "gasUsed": 665200 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 106088 + "gasUsed": 106140 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 35339 + "gasUsed": 35415 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 664896 + "gasUsed": 665200 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 148411 + "gasUsed": 148511 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 113170 + "gasUsed": 113270 }, { "file": "test/query.t.sol", @@ -231,49 +231,49 @@ "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 114520 + "gasUsed": 114571 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 34023 + "gasUsed": 34058 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 108972 + "gasUsed": 109041 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 27100 + "gasUsed": 27106 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 689839 + "gasUsed": 690323 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 52112 + "gasUsed": 52137 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 680105 + "gasUsed": 680596 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 52112 + "gasUsed": 52137 }, { "file": "test/World.t.sol", @@ -285,7 +285,7 @@ "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 50584 + "gasUsed": 50615 }, { "file": "test/World.t.sol", @@ -297,7 +297,7 @@ "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 9120 + "gasUsed": 9155 }, { "file": "test/World.t.sol", @@ -309,79 +309,79 @@ "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 59355 + "gasUsed": 59404 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 52902 + "gasUsed": 52929 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 79949 + "gasUsed": 79998 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 123062 + "gasUsed": 123238 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 74815 + "gasUsed": 74842 }, { "file": "test/World.t.sol", "test": "testRegisterSystem", "name": "register a system", - "gasUsed": 165531 + "gasUsed": 165710 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 651531 + "gasUsed": 651789 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 37403 + "gasUsed": 37413 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 35397 + "gasUsed": 35407 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 24633 + "gasUsed": 24643 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 13779 + "gasUsed": 13789 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 25244 + "gasUsed": 25248 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 14449 + "gasUsed": 14453 }, { "file": "test/WorldResourceId.t.sol", diff --git a/packages/world/mud.config.ts b/packages/world/mud.config.ts index 1a77d8309b..9a3fe83257 100644 --- a/packages/world/mud.config.ts +++ b/packages/world/mud.config.ts @@ -191,7 +191,5 @@ export default mudConfig({ // TODO: add support for inheritance to worldgen // (see: https://github.com/latticexyz/mud/issues/631) "StoreRegistrationSystem", - // Similar overlap occurs for IEphemeralRecordSystem. IWorldEphemeral is included instead. - "EphemeralRecordSystem", ], }); diff --git a/packages/world/src/modules/core/CoreModule.sol b/packages/world/src/modules/core/CoreModule.sol index bdbaca2226..9d5fc3a852 100644 --- a/packages/world/src/modules/core/CoreModule.sol +++ b/packages/world/src/modules/core/CoreModule.sol @@ -7,7 +7,6 @@ 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 { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol"; import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "../../WorldResourceId.sol"; @@ -29,7 +28,6 @@ import { Balances } from "./tables/Balances.sol"; import { AccessManagementSystem } from "./implementations/AccessManagementSystem.sol"; import { BalanceTransferSystem } from "./implementations/BalanceTransferSystem.sol"; -import { EphemeralRecordSystem } from "./implementations/EphemeralRecordSystem.sol"; import { ModuleInstallationSystem } from "./implementations/ModuleInstallationSystem.sol"; import { StoreRegistrationSystem } from "./implementations/StoreRegistrationSystem.sol"; import { WorldRegistrationSystem } from "./implementations/WorldRegistrationSystem.sol"; @@ -104,7 +102,7 @@ contract CoreModule is Module { * Register function selectors for all CoreSystem functions in the World */ function _registerFunctionSelectors() internal { - bytes4[17] memory functionSelectors = [ + bytes4[16] memory functionSelectors = [ // --- AccessManagementSystem --- AccessManagementSystem.grantAccess.selector, AccessManagementSystem.revokeAccess.selector, @@ -112,8 +110,6 @@ contract CoreModule is Module { // --- BalanceTransferSystem --- BalanceTransferSystem.transferBalanceToNamespace.selector, BalanceTransferSystem.transferBalanceToAddress.selector, - // --- EphemeralRecordSystem --- - IStoreEphemeral.emitEphemeralRecord.selector, // --- ModuleInstallationSystem --- ModuleInstallationSystem.installModule.selector, // --- StoreRegistrationSystem --- diff --git a/packages/world/src/modules/core/CoreSystem.sol b/packages/world/src/modules/core/CoreSystem.sol index 1a3b5c0c1c..5372acc73d 100644 --- a/packages/world/src/modules/core/CoreSystem.sol +++ b/packages/world/src/modules/core/CoreSystem.sol @@ -5,7 +5,6 @@ import { IWorldErrors } from "../../interfaces/IWorldErrors.sol"; import { AccessManagementSystem } from "./implementations/AccessManagementSystem.sol"; import { BalanceTransferSystem } from "./implementations/BalanceTransferSystem.sol"; -import { EphemeralRecordSystem } from "./implementations/EphemeralRecordSystem.sol"; import { ModuleInstallationSystem } from "./implementations/ModuleInstallationSystem.sol"; import { StoreRegistrationSystem } from "./implementations/StoreRegistrationSystem.sol"; import { WorldRegistrationSystem } from "./implementations/WorldRegistrationSystem.sol"; @@ -18,7 +17,6 @@ contract CoreSystem is IWorldErrors, AccessManagementSystem, BalanceTransferSystem, - EphemeralRecordSystem, ModuleInstallationSystem, StoreRegistrationSystem, WorldRegistrationSystem diff --git a/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol b/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol deleted file mode 100644 index e5726d495f..0000000000 --- a/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; - -import { IStoreEphemeral } from "@latticexyz/store/src/IStore.sol"; -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 { ResourceId, WorldResourceIdInstance } from "../../../WorldResourceId.sol"; -import { AccessControl } from "../../../AccessControl.sol"; - -contract EphemeralRecordSystem is IStoreEphemeral, System { - 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 table ID) - */ - function emitEphemeralRecord( - ResourceId tableId, - bytes32[] calldata keyTuple, - bytes calldata staticData, - PackedCounter encodedLengths, - bytes calldata dynamicData, - FieldLayout fieldLayout - ) public virtual { - // Require access to the namespace or name - AccessControl.requireAccess(tableId, msg.sender); - - // Set the record - StoreCore.emitEphemeralRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); - } -} diff --git a/packages/world/src/modules/core/tables/Balances.sol b/packages/world/src/modules/core/tables/Balances.sol index abdb7903f5..b1a6f276be 100644 --- a/packages/world/src/modules/core/tables/Balances.sol +++ b/packages/world/src/modules/core/tables/Balances.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Balances"))) @@ -180,6 +180,30 @@ library Balances { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); } + /** Delete all data for given keys */ + function deleteRecord(bytes32 namespaceId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = namespaceId; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 namespaceId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = namespaceId; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 namespaceId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = namespaceId; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(uint256 balance) internal pure returns (bytes memory) { return abi.encodePacked(balance); @@ -202,28 +226,4 @@ library Balances { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 namespaceId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = namespaceId; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 namespaceId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = namespaceId; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 namespaceId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _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 19c200d122..7f520a92bb 100644 --- a/packages/world/src/modules/core/tables/FunctionSelectors.sol +++ b/packages/world/src/modules/core/tables/FunctionSelectors.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("FunctionSelector"))) @@ -288,6 +288,30 @@ library FunctionSelectors { (systemId, systemFunctionSelector) = decodeStatic(_staticData); } + /** Delete all data for given keys */ + function deleteRecord(bytes4 functionSelector) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(functionSelector); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes4 functionSelector) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(functionSelector); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes4 functionSelector) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(functionSelector); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(bytes32 systemId, bytes4 systemFunctionSelector) internal pure returns (bytes memory) { return abi.encodePacked(systemId, systemFunctionSelector); @@ -313,28 +337,4 @@ library FunctionSelectors { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes4 functionSelector) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(functionSelector); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes4 functionSelector) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(functionSelector); - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes4 functionSelector) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(functionSelector); - - _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 0201700a2d..b42a79d2eb 100644 --- a/packages/world/src/modules/core/tables/SystemHooks.sol +++ b/packages/world/src/modules/core/tables/SystemHooks.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("SystemHooks"))) @@ -532,6 +532,30 @@ library SystemHooks { } } + /** Delete all data for given keys */ + function deleteRecord(bytes32 systemId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = systemId; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 systemId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = systemId; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 systemId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = systemId; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack dynamic data using this table's schema */ function encodeLengths(bytes21[] memory value) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits @@ -561,28 +585,4 @@ library SystemHooks { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 systemId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = systemId; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 systemId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = systemId; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 systemId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _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 58064ea817..aaec11544d 100644 --- a/packages/world/src/modules/core/tables/SystemRegistry.sol +++ b/packages/world/src/modules/core/tables/SystemRegistry.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("SystemRegistry"))) @@ -180,6 +180,30 @@ library SystemRegistry { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((systemId)), _fieldLayout); } + /** Delete all data for given keys */ + function deleteRecord(address system) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(uint160(system))); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(address system) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(uint160(system))); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, address system) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(uint160(system))); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(bytes32 systemId) internal pure returns (bytes memory) { return abi.encodePacked(systemId); @@ -202,28 +226,4 @@ library SystemRegistry { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(address system) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(uint256(uint160(system))); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(address system) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(uint256(uint160(system))); - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, address system) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(uint256(uint160(system))); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/world/src/modules/core/tables/Systems.sol b/packages/world/src/modules/core/tables/Systems.sol index 2da7769044..10c7b49a40 100644 --- a/packages/world/src/modules/core/tables/Systems.sol +++ b/packages/world/src/modules/core/tables/Systems.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Systems"))) @@ -282,6 +282,30 @@ library Systems { (system, publicAccess) = decodeStatic(_staticData); } + /** Delete all data for given keys */ + function deleteRecord(bytes32 systemId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = systemId; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 systemId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = systemId; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 systemId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = systemId; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(address system, bool publicAccess) internal pure returns (bytes memory) { return abi.encodePacked(system, publicAccess); @@ -304,30 +328,6 @@ library Systems { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 systemId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = systemId; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 systemId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = systemId; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 systemId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = systemId; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } function _toBool(uint8 value) pure returns (bool result) { diff --git a/packages/world/src/modules/keysintable/tables/KeysInTable.sol b/packages/world/src/modules/keysintable/tables/KeysInTable.sol index b51ca0c922..7c86f97fed 100644 --- a/packages/world/src/modules/keysintable/tables/KeysInTable.sol +++ b/packages/world/src/modules/keysintable/tables/KeysInTable.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("KeysInTable"))) @@ -1406,6 +1406,30 @@ library KeysInTable { ); } + /** Delete all data for given keys */ + function deleteRecord(bytes32 sourceTable) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 sourceTable) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 sourceTable) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack dynamic data using this table's schema */ function encodeLengths( bytes32[] memory keys0, @@ -1466,28 +1490,4 @@ library KeysInTable { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 sourceTable) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = sourceTable; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 sourceTable) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = sourceTable; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 sourceTable) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = sourceTable; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol index d4c75eddb8..ade2c06653 100644 --- a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol +++ b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("UsedKeysIndex"))) @@ -302,31 +302,7 @@ library UsedKeysIndex { (has, index) = decodeStatic(_staticData); } - /** Tightly pack static data using this table's schema */ - function encodeStatic(bool has, uint40 index) internal pure returns (bytes memory) { - return abi.encodePacked(has, index); - } - - /** Tightly pack full data using this table's field layout */ - function encode(bool has, uint40 index) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(has, index); - - PackedCounter _encodedLengths; - bytes memory _dynamicData; - - return (_staticData, _encodedLengths, _dynamicData); - } - - /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(bytes32 sourceTable, bytes32 keysHash) internal pure returns (bytes32[] memory) { - bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = sourceTable; - _keyTuple[1] = keysHash; - - return _keyTuple; - } - - /* Delete all data for given keys */ + /** Delete all data for given keys */ function deleteRecord(bytes32 sourceTable, bytes32 keysHash) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = sourceTable; @@ -335,7 +311,7 @@ library UsedKeysIndex { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ + /** Delete all data for given keys */ function _deleteRecord(bytes32 sourceTable, bytes32 keysHash) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = sourceTable; @@ -344,7 +320,7 @@ library UsedKeysIndex { StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys (using the specified store) */ + /** Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes32 sourceTable, bytes32 keysHash) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = sourceTable; @@ -352,6 +328,30 @@ library UsedKeysIndex { _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + + /** Tightly pack static data using this table's schema */ + function encodeStatic(bool has, uint40 index) internal pure returns (bytes memory) { + return abi.encodePacked(has, index); + } + + /** Tightly pack full data using this table's field layout */ + function encode(bool has, uint40 index) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(has, index); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** Encode keys as a bytes32 array using this table's field layout */ + function encodeKeyTuple(bytes32 sourceTable, bytes32 keysHash) internal pure returns (bytes32[] memory) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = sourceTable; + _keyTuple[1] = keysHash; + + return _keyTuple; + } } function _toBool(uint8 value) pure returns (bool result) { diff --git a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol index 24fce461aa..0cc9ed2cf8 100644 --- a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol +++ b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 @@ -570,6 +570,30 @@ library KeysWithValue { } } + /** Delete all data for given keys */ + function deleteRecord(ResourceId _tableId, bytes32 valueHash) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = valueHash; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(ResourceId _tableId, bytes32 valueHash) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = valueHash; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, ResourceId _tableId, bytes32 valueHash) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = valueHash; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack dynamic data using this table's schema */ function encodeLengths(bytes32[] memory keysWithValue) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits @@ -599,28 +623,4 @@ library KeysWithValue { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(ResourceId _tableId, bytes32 valueHash) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = valueHash; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(ResourceId _tableId, bytes32 valueHash) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = valueHash; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, ResourceId _tableId, bytes32 valueHash) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = valueHash; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol index 93c6ef192d..5bb08ebe8a 100644 --- a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("CallboundDelegat"))) @@ -292,38 +292,7 @@ library CallboundDelegations { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); } - /** Tightly pack static data using this table's schema */ - function encodeStatic(uint256 availableCalls) internal pure returns (bytes memory) { - return abi.encodePacked(availableCalls); - } - - /** Tightly pack full data using this table's field layout */ - function encode(uint256 availableCalls) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(availableCalls); - - PackedCounter _encodedLengths; - bytes memory _dynamicData; - - return (_staticData, _encodedLengths, _dynamicData); - } - - /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple( - address delegator, - address delegatee, - 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] = systemId; - _keyTuple[3] = callDataHash; - - return _keyTuple; - } - - /* Delete all data for given keys */ + /** Delete all data for given keys */ function deleteRecord(address delegator, address delegatee, bytes32 systemId, bytes32 callDataHash) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); @@ -334,7 +303,7 @@ library CallboundDelegations { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ + /** Delete all data for given keys */ function _deleteRecord(address delegator, address delegatee, bytes32 systemId, bytes32 callDataHash) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); @@ -345,7 +314,7 @@ library CallboundDelegations { StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys (using the specified store) */ + /** Delete all data for given keys (using the specified store) */ function deleteRecord( IStore _store, address delegator, @@ -361,4 +330,35 @@ library CallboundDelegations { _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint256 availableCalls) internal pure returns (bytes memory) { + return abi.encodePacked(availableCalls); + } + + /** Tightly pack full data using this table's field layout */ + function encode(uint256 availableCalls) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(availableCalls); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** Encode keys as a bytes32 array using this table's field layout */ + function encodeKeyTuple( + address delegator, + address delegatee, + 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] = systemId; + _keyTuple[3] = callDataHash; + + return _keyTuple; + } } diff --git a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol index 7505e6a7c6..f973705ea6 100644 --- a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("TimeboundDelegat"))) @@ -198,31 +198,7 @@ library TimeboundDelegations { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((maxTimestamp)), _fieldLayout); } - /** Tightly pack static data using this table's schema */ - function encodeStatic(uint256 maxTimestamp) internal pure returns (bytes memory) { - return abi.encodePacked(maxTimestamp); - } - - /** Tightly pack full data using this table's field layout */ - function encode(uint256 maxTimestamp) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(maxTimestamp); - - PackedCounter _encodedLengths; - bytes memory _dynamicData; - - return (_staticData, _encodedLengths, _dynamicData); - } - - /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(address delegator, address delegatee) internal pure returns (bytes32[] memory) { - bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = bytes32(uint256(uint160(delegator))); - _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - - return _keyTuple; - } - - /* Delete all data for given keys */ + /** Delete all data for given keys */ function deleteRecord(address delegator, address delegatee) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = bytes32(uint256(uint160(delegator))); @@ -231,7 +207,7 @@ library TimeboundDelegations { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ + /** Delete all data for given keys */ function _deleteRecord(address delegator, address delegatee) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = bytes32(uint256(uint160(delegator))); @@ -240,7 +216,7 @@ library TimeboundDelegations { StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys (using the specified store) */ + /** Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, address delegator, address delegatee) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = bytes32(uint256(uint160(delegator))); @@ -248,4 +224,28 @@ library TimeboundDelegations { _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint256 maxTimestamp) internal pure returns (bytes memory) { + return abi.encodePacked(maxTimestamp); + } + + /** Tightly pack full data using this table's field layout */ + function encode(uint256 maxTimestamp) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(maxTimestamp); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** Encode keys as a bytes32 array using this table's field layout */ + function encodeKeyTuple(address delegator, address delegatee) internal pure returns (bytes32[] memory) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = bytes32(uint256(uint160(delegator))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + + return _keyTuple; + } } diff --git a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol index 2e2982e647..504f52e8b4 100644 --- a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol +++ b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0020010020000000000000000000000000000000000000000000000000000000 @@ -161,6 +161,27 @@ library UniqueEntity { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Delete all data for given keys */ + function deleteRecord(ResourceId _tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + 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, ResourceId _tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(uint256 value) internal pure returns (bytes memory) { return abi.encodePacked(value); @@ -182,25 +203,4 @@ library UniqueEntity { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(ResourceId _tableId) internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - 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, ResourceId _tableId) internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/world/src/tables/Delegations.sol b/packages/world/src/tables/Delegations.sol index f39cb50e68..d74442d458 100644 --- a/packages/world/src/tables/Delegations.sol +++ b/packages/world/src/tables/Delegations.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Delegations"))) @@ -213,31 +213,7 @@ library Delegations { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((delegationControlId)), _fieldLayout); } - /** Tightly pack static data using this table's schema */ - function encodeStatic(bytes32 delegationControlId) internal pure returns (bytes memory) { - return abi.encodePacked(delegationControlId); - } - - /** Tightly pack full data using this table's field layout */ - function encode(bytes32 delegationControlId) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(delegationControlId); - - PackedCounter _encodedLengths; - bytes memory _dynamicData; - - return (_staticData, _encodedLengths, _dynamicData); - } - - /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(address delegator, address delegatee) internal pure returns (bytes32[] memory) { - bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = bytes32(uint256(uint160(delegator))); - _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - - return _keyTuple; - } - - /* Delete all data for given keys */ + /** Delete all data for given keys */ function deleteRecord(address delegator, address delegatee) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = bytes32(uint256(uint160(delegator))); @@ -246,7 +222,7 @@ library Delegations { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ + /** Delete all data for given keys */ function _deleteRecord(address delegator, address delegatee) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = bytes32(uint256(uint160(delegator))); @@ -255,7 +231,7 @@ library Delegations { StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys (using the specified store) */ + /** Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, address delegator, address delegatee) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = bytes32(uint256(uint160(delegator))); @@ -263,4 +239,28 @@ library Delegations { _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + + /** Tightly pack static data using this table's schema */ + function encodeStatic(bytes32 delegationControlId) internal pure returns (bytes memory) { + return abi.encodePacked(delegationControlId); + } + + /** Tightly pack full data using this table's field layout */ + function encode(bytes32 delegationControlId) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(delegationControlId); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** Encode keys as a bytes32 array using this table's field layout */ + function encodeKeyTuple(address delegator, address delegatee) internal pure returns (bytes32[] memory) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = bytes32(uint256(uint160(delegator))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + + return _keyTuple; + } } diff --git a/packages/world/src/tables/InstalledModules.sol b/packages/world/src/tables/InstalledModules.sol index babc79ad42..378bbf8bb1 100644 --- a/packages/world/src/tables/InstalledModules.sol +++ b/packages/world/src/tables/InstalledModules.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("InstalledModules"))) @@ -198,31 +198,7 @@ library InstalledModules { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((moduleAddress)), _fieldLayout); } - /** Tightly pack static data using this table's schema */ - function encodeStatic(address moduleAddress) internal pure returns (bytes memory) { - return abi.encodePacked(moduleAddress); - } - - /** Tightly pack full data using this table's field layout */ - function encode(address moduleAddress) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(moduleAddress); - - PackedCounter _encodedLengths; - bytes memory _dynamicData; - - return (_staticData, _encodedLengths, _dynamicData); - } - - /** Encode keys as a bytes32 array using this table's field layout */ - function encodeKeyTuple(bytes16 moduleName, bytes32 argumentsHash) internal pure returns (bytes32[] memory) { - bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = bytes32(moduleName); - _keyTuple[1] = argumentsHash; - - return _keyTuple; - } - - /* Delete all data for given keys */ + /** Delete all data for given keys */ function deleteRecord(bytes16 moduleName, bytes32 argumentsHash) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = bytes32(moduleName); @@ -231,7 +207,7 @@ library InstalledModules { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ + /** Delete all data for given keys */ function _deleteRecord(bytes16 moduleName, bytes32 argumentsHash) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = bytes32(moduleName); @@ -240,7 +216,7 @@ library InstalledModules { StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys (using the specified store) */ + /** Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes16 moduleName, bytes32 argumentsHash) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = bytes32(moduleName); @@ -248,4 +224,28 @@ library InstalledModules { _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + + /** Tightly pack static data using this table's schema */ + function encodeStatic(address moduleAddress) internal pure returns (bytes memory) { + return abi.encodePacked(moduleAddress); + } + + /** Tightly pack full data using this table's field layout */ + function encode(address moduleAddress) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(moduleAddress); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** Encode keys as a bytes32 array using this table's field layout */ + function encodeKeyTuple(bytes16 moduleName, bytes32 argumentsHash) internal pure returns (bytes32[] memory) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = bytes32(moduleName); + _keyTuple[1] = argumentsHash; + + return _keyTuple; + } } diff --git a/packages/world/src/tables/NamespaceOwner.sol b/packages/world/src/tables/NamespaceOwner.sol index 6b9c4c6a99..50fc82b5aa 100644 --- a/packages/world/src/tables/NamespaceOwner.sol +++ b/packages/world/src/tables/NamespaceOwner.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("NamespaceOwner"))) @@ -180,6 +180,30 @@ library NamespaceOwner { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); } + /** Delete all data for given keys */ + function deleteRecord(bytes32 namespaceId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = namespaceId; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 namespaceId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = namespaceId; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 namespaceId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = namespaceId; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(address owner) internal pure returns (bytes memory) { return abi.encodePacked(owner); @@ -202,28 +226,4 @@ library NamespaceOwner { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 namespaceId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = namespaceId; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 namespaceId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = namespaceId; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 namespaceId) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _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 28613dbe6a..58b9ccceb5 100644 --- a/packages/world/src/tables/ResourceAccess.sol +++ b/packages/world/src/tables/ResourceAccess.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("ResourceAccess"))) @@ -194,31 +194,7 @@ library ResourceAccess { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); } - /** Tightly pack static data using this table's schema */ - function encodeStatic(bool access) internal pure returns (bytes memory) { - return abi.encodePacked(access); - } - - /** Tightly pack full data using this table's field layout */ - function encode(bool access) internal pure returns (bytes memory, PackedCounter, bytes memory) { - bytes memory _staticData = encodeStatic(access); - - 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, address caller) internal pure returns (bytes32[] memory) { - bytes32[] memory _keyTuple = new bytes32[](2); - _keyTuple[0] = resourceId; - _keyTuple[1] = bytes32(uint256(uint160(caller))); - - return _keyTuple; - } - - /* Delete all data for given keys */ + /** Delete all data for given keys */ function deleteRecord(bytes32 resourceId, address caller) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = resourceId; @@ -227,7 +203,7 @@ library ResourceAccess { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys */ + /** Delete all data for given keys */ function _deleteRecord(bytes32 resourceId, address caller) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = resourceId; @@ -236,7 +212,7 @@ library ResourceAccess { StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } - /* Delete all data for given keys (using the specified store) */ + /** Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes32 resourceId, address caller) internal { bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = resourceId; @@ -244,6 +220,30 @@ library ResourceAccess { _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + + /** Tightly pack static data using this table's schema */ + function encodeStatic(bool access) internal pure returns (bytes memory) { + return abi.encodePacked(access); + } + + /** Tightly pack full data using this table's field layout */ + function encode(bool access) internal pure returns (bytes memory, PackedCounter, bytes memory) { + bytes memory _staticData = encodeStatic(access); + + 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, address caller) internal pure returns (bytes32[] memory) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = resourceId; + _keyTuple[1] = bytes32(uint256(uint160(caller))); + + return _keyTuple; + } } function _toBool(uint8 value) pure returns (bool result) { diff --git a/packages/world/test/tables/AddressArray.sol b/packages/world/test/tables/AddressArray.sol index 2a0ca327d7..8f658a688e 100644 --- a/packages/world/test/tables/AddressArray.sol +++ b/packages/world/test/tables/AddressArray.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0000000100000000000000000000000000000000000000000000000000000000 @@ -532,6 +532,30 @@ library AddressArray { } } + /** Delete all data for given keys */ + function deleteRecord(ResourceId _tableId, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(ResourceId _tableId, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, ResourceId _tableId, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack dynamic data using this table's schema */ function encodeLengths(address[] memory value) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits @@ -561,28 +585,4 @@ library AddressArray { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(ResourceId _tableId, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(ResourceId _tableId, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, ResourceId _tableId, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/packages/world/test/tables/Bool.sol b/packages/world/test/tables/Bool.sol index 3572977787..976c3c4658 100644 --- a/packages/world/test/tables/Bool.sol +++ b/packages/world/test/tables/Bool.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; FieldLayout constant _fieldLayout = FieldLayout.wrap( 0x0001010001000000000000000000000000000000000000000000000000000000 @@ -161,6 +161,27 @@ library Bool { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Delete all data for given keys */ + function deleteRecord(ResourceId _tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + 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, ResourceId _tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(bool value) internal pure returns (bytes memory) { return abi.encodePacked(value); @@ -182,27 +203,6 @@ library Bool { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(ResourceId _tableId) internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - 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, ResourceId _tableId) internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } function _toBool(uint8 value) pure returns (bool result) { diff --git a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol index f444e2aebd..33aeb9dba3 100644 --- a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Counter"))) @@ -166,6 +166,27 @@ library Counter { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Delete all data for given keys */ + function deleteRecord() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord() 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) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(uint32 value) internal pure returns (bytes memory) { return abi.encodePacked(value); @@ -187,25 +208,4 @@ library Counter { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord() internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord() 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) internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/templates/react/packages/contracts/src/codegen/tables/Counter.sol b/templates/react/packages/contracts/src/codegen/tables/Counter.sol index f444e2aebd..33aeb9dba3 100644 --- a/templates/react/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/react/packages/contracts/src/codegen/tables/Counter.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Counter"))) @@ -166,6 +166,27 @@ library Counter { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Delete all data for given keys */ + function deleteRecord() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord() 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) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(uint32 value) internal pure returns (bytes memory) { return abi.encodePacked(value); @@ -187,25 +208,4 @@ library Counter { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord() internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord() 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) internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol index d9ea2bc66b..07ae7da4b2 100644 --- a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol +++ b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Position"))) @@ -358,6 +358,30 @@ library Position { (_table.x, _table.y, _table.z) = decodeStatic(_staticData); } + /** Delete all data for given keys */ + function deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys (using the specified store) */ + function deleteRecord(IStore _store, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(int32 x, int32 y, int32 z) internal pure returns (bytes memory) { return abi.encodePacked(x, y, z); @@ -380,28 +404,4 @@ library Position { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord(bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys (using the specified store) */ - function deleteRecord(IStore _store, bytes32 key) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } } diff --git a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol index f444e2aebd..33aeb9dba3 100644 --- a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol @@ -18,7 +18,7 @@ import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.s 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 { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; ResourceId constant _tableId = ResourceId.wrap( bytes32(abi.encodePacked(RESOURCE_TABLE, bytes14(""), bytes16("Counter"))) @@ -166,6 +166,27 @@ library Counter { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Delete all data for given keys */ + function deleteRecord() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** Delete all data for given keys */ + function _deleteRecord() 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) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /** Tightly pack static data using this table's schema */ function encodeStatic(uint32 value) internal pure returns (bytes memory) { return abi.encodePacked(value); @@ -187,25 +208,4 @@ library Counter { return _keyTuple; } - - /* Delete all data for given keys */ - function deleteRecord() internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /* Delete all data for given keys */ - function _deleteRecord() 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) internal { - bytes32[] memory _keyTuple = new bytes32[](0); - - _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } }