From be434562766a73e19f1aec547c37e4006d57e1bb Mon Sep 17 00:00:00 2001 From: y77cao Date: Fri, 15 Sep 2023 17:19:16 -0400 Subject: [PATCH 01/17] add accidentally removed line --- e2e/packages/client-vanilla/src/mud/setupNetwork.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e/packages/client-vanilla/src/mud/setupNetwork.ts b/e2e/packages/client-vanilla/src/mud/setupNetwork.ts index d9d45cb1e6..662c2f059a 100644 --- a/e2e/packages/client-vanilla/src/mud/setupNetwork.ts +++ b/e2e/packages/client-vanilla/src/mud/setupNetwork.ts @@ -33,6 +33,7 @@ export async function setupNetwork() { address: networkConfig.worldAddress as Hex, publicClient, startBlock: BigInt(networkConfig.initialBlockNumber), + indexerUrl: networkConfig.indexerUrl ?? undefined, }); const worldContract = createContract({ From 331dbfdcbbda404de4b0fd4d439d636ae2033853 Mon Sep 17 00:00:00 2001 From: dk1a Date: Sat, 16 Sep 2023 15:23:15 +0300 Subject: [PATCH 02/17] feat(store,): add splice events (#1354) Co-authored-by: Kevin Ingersoll Co-authored-by: alvrs --- .changeset/cyan-hats-try.md | 30 + .changeset/fast-zebras-promise.md | 6 + .changeset/rotten-cats-lay.md | 9 + .changeset/shy-sheep-wait.md | 9 + .../client-vanilla/src/mud/setupNetwork.ts | 4 +- .../contracts/src/codegen/tables/Multi.sol | 26 +- .../contracts/src/codegen/tables/Number.sol | 12 +- .../src/codegen/tables/NumberList.sol | 19 +- .../contracts/src/codegen/tables/Vector.sol | 26 +- e2e/packages/contracts/worlds.json | 2 +- .../sync-test/data/encodeTestData.test.ts | 48 +- e2e/packages/sync-test/data/encodeTestData.ts | 23 +- .../sync-test/data/expectClientData.ts | 2 +- .../sync-test/data/setContractData.ts | 6 +- e2e/packages/sync-test/data/types.ts | 2 +- e2e/packages/sync-test/rpcSync.test.ts | 1 - .../sync-test/setup/startBrowserAndPage.ts | 2 +- e2e/packages/sync-test/vite.config.ts | 1 - .../client-phaser/src/mud/setupNetwork.ts | 4 +- .../packages/client-phaser/src/ui/App.tsx | 2 +- .../packages/client-react/src/index.tsx | 2 +- .../client-react/src/mud/setupNetwork.ts | 4 +- .../packages/client-vanilla/src/index.ts | 2 +- .../client-vanilla/src/mud/setupNetwork.ts | 4 +- .../src/codegen/tables/CounterTable.sol | 12 +- .../src/codegen/tables/Inventory.sol | 12 +- .../src/codegen/tables/MessageTable.sol | 31 +- .../contracts/test/ChatNamespaced.t.sol | 11 +- .../src/groupLogsByBlockNumber.ts | 2 +- .../src/codegen/tables/Dynamics1.sol | 44 +- .../src/codegen/tables/Dynamics2.sol | 35 +- .../src/codegen/tables/Ephemeral.sol | 26 +- .../src/codegen/tables/Singleton.sol | 51 +- .../contracts/src/codegen/tables/Statics.sol | 462 ++----- packages/cli/contracts/test/Tablegen.t.sol | 13 +- packages/cli/scripts/generate-test-tables.ts | 4 +- packages/common/src/index.ts | 2 + .../src/readHex.test.ts | 0 .../src/readHex.ts | 0 packages/common/src/spliceHex.ts | 6 + packages/common/src/type-utils/common.ts | 2 + packages/dev-tools/README.md | 2 +- packages/dev-tools/src/DevToolsContext.tsx | 15 +- .../dev-tools/src/actions/WriteSummary.tsx | 1 + packages/dev-tools/src/common.ts | 4 +- packages/dev-tools/src/events/EventIcon.tsx | 18 +- packages/dev-tools/src/events/EventsPage.tsx | 8 +- packages/dev-tools/src/events/LogsTable.tsx | 72 ++ .../src/events/StorageOperationsTable.tsx | 53 - .../dev-tools/src/summary/EventsSummary.tsx | 6 +- packages/protocol-parser/src/common.ts | 7 + packages/protocol-parser/src/decodeRecord.ts | 2 +- .../protocol-parser/src/decodeValueArgs.ts | 20 + .../protocol-parser/src/encodeLengths.test.ts | 10 + packages/protocol-parser/src/encodeLengths.ts | 12 + packages/protocol-parser/src/encodeValue.ts | 15 +- .../protocol-parser/src/encodeValueArgs.ts | 27 + .../protocol-parser/src/hexToPackedCounter.ts | 2 +- packages/protocol-parser/src/index.ts | 3 +- .../store-indexer/bin/postgres-indexer.ts | 10 +- packages/store-indexer/bin/sqlite-indexer.ts | 4 +- packages/store-indexer/package.json | 4 +- .../src/sqlite/createQueryAdapter.ts | 4 +- packages/store-sync/package.json | 4 +- .../store-sync/src/blockLogsToStorage.test.ts | 195 --- packages/store-sync/src/blockLogsToStorage.ts | 192 --- packages/store-sync/src/common.ts | 85 +- packages/store-sync/src/createStoreSync.ts | 73 +- packages/store-sync/src/index.ts | 1 - .../store-sync/src/isTableRegistrationLog.ts | 7 + packages/store-sync/src/logToTable.test.ts | 39 + packages/store-sync/src/logToTable.ts | 37 + .../store-sync/src/postgres/buildColumn.ts | 5 +- .../src/postgres/buildTable.test.ts | 768 +++++++++++- .../store-sync/src/postgres/buildTable.ts | 10 +- .../store-sync/src/postgres/cleanDatabase.ts | 10 +- .../store-sync/src/postgres/columnTypes.ts | 30 +- .../store-sync/src/postgres/getSchema.test.ts | 12 - packages/store-sync/src/postgres/getSchema.ts | 6 - .../store-sync/src/postgres/getTableKey.ts | 6 +- .../src/postgres/postgresStorage.test.ts | 121 +- .../src/postgres/postgresStorage.ts | 351 +++--- .../store-sync/src/postgres/setupTables.ts | 19 +- .../store-sync/src/postgres/syncToPostgres.ts | 9 +- packages/store-sync/src/recs/common.test-d.ts | 21 +- packages/store-sync/src/recs/common.ts | 4 + .../src/recs/configToRecsComponents.ts | 19 +- packages/store-sync/src/recs/decodeEntity.ts | 2 +- packages/store-sync/src/recs/encodeEntity.ts | 2 +- .../store-sync/src/recs/getTableEntity.ts | 2 +- .../store-sync/src/recs/recsStorage.test.ts | 30 +- packages/store-sync/src/recs/recsStorage.ts | 183 +-- packages/store-sync/src/recs/syncToRecs.ts | 4 +- packages/store-sync/src/schemaToDefaults.ts | 2 +- .../{buildSqliteColumn.ts => buildColumn.ts} | 5 +- .../store-sync/src/sqlite/buildTable.test.ts | 1086 +++++++++++++++++ .../{createSqliteTable.ts => buildTable.ts} | 22 +- packages/store-sync/src/sqlite/columnTypes.ts | 9 +- .../src/sqlite/createSqliteTable.test.ts | 446 ------- packages/store-sync/src/sqlite/getTables.ts | 4 +- packages/store-sync/src/sqlite/index.ts | 2 +- .../src/sqlite/sqliteStorage.test.ts | 122 +- .../store-sync/src/sqlite/sqliteStorage.ts | 346 +++--- .../store-sync/src/sqlite/syncToSqlite.ts | 8 +- packages/store/gas-report.json | 136 ++- packages/store/src/IStore.sol | 50 +- packages/store/src/IStoreErrors.sol | 3 +- packages/store/src/IStoreHook.sol | 13 +- packages/store/src/StoreCore.sol | 346 ++++-- packages/store/src/StoreRead.sol | 12 +- packages/store/src/StoreSwitch.sol | 29 +- .../store/src/codegen/tables/Callbacks.sol | 19 +- packages/store/src/codegen/tables/Hooks.sol | 19 +- .../store/src/codegen/tables/KeyEncoding.sol | 12 +- packages/store/src/codegen/tables/Mixed.sol | 39 +- .../store/src/codegen/tables/StoreHooks.sol | 19 +- packages/store/src/codegen/tables/Tables.sol | 61 +- packages/store/src/codegen/tables/Vector2.sol | 26 +- packages/store/test/EchoSubscriber.sol | 21 +- packages/store/test/Gas.t.sol | 32 + packages/store/test/MirrorSubscriber.sol | 17 +- packages/store/test/PackedCounter.t.sol | 5 + packages/store/test/RevertSubscriber.sol | 21 +- packages/store/test/StoreCore.t.sol | 226 ++-- packages/store/test/StoreCoreDynamic.t.sol | 27 +- packages/store/test/StoreCoreGas.t.sol | 51 +- packages/store/test/StoreHook.t.sol | 29 +- packages/store/test/StoreMock.sol | 35 +- packages/store/ts/codegen/ephemeral.ts | 5 +- packages/store/ts/codegen/record.ts | 129 +- packages/store/ts/codegen/renderTable.ts | 100 +- packages/store/ts/storeEvents.ts | 7 +- packages/world/gas-report.json | 110 +- packages/world/src/World.sol | 24 +- .../implementations/EphemeralRecordSystem.sol | 10 +- .../src/modules/core/tables/Balances.sol | 12 +- .../modules/core/tables/FunctionSelectors.sol | 26 +- .../src/modules/core/tables/ResourceType.sol | 12 +- .../src/modules/core/tables/SystemHooks.sol | 19 +- .../modules/core/tables/SystemRegistry.sol | 12 +- .../world/src/modules/core/tables/Systems.sol | 26 +- .../modules/keysintable/KeysInTableHook.sol | 19 +- .../world/src/modules/keysintable/query.sol | 41 +- .../keysintable/tables/KeysInTable.sol | 44 +- .../keysintable/tables/UsedKeysIndex.sol | 26 +- .../keyswithvalue/KeysWithValueHook.sol | 15 +- .../keyswithvalue/getKeysWithValue.sol | 24 +- .../keyswithvalue/tables/KeysWithValue.sol | 19 +- .../tables/CallboundDelegations.sol | 12 +- .../tables/TimeboundDelegations.sol | 12 +- .../uniqueentity/tables/UniqueEntity.sol | 12 +- packages/world/src/tables/Delegations.sol | 12 +- .../world/src/tables/InstalledModules.sol | 12 +- packages/world/src/tables/NamespaceOwner.sol | 12 +- packages/world/src/tables/ResourceAccess.sol | 12 +- packages/world/test/KeysInTableModule.t.sol | 145 ++- packages/world/test/KeysWithValueModule.t.sol | 109 +- packages/world/test/World.t.sol | 78 +- packages/world/test/query.t.sol | 159 +-- packages/world/test/tables/AddressArray.sol | 19 +- packages/world/test/tables/Bool.sol | 12 +- pnpm-lock.yaml | 36 +- .../packages/client/src/mud/setupNetwork.ts | 4 +- .../phaser/packages/client/src/ui/App.tsx | 2 +- .../contracts/src/codegen/tables/Counter.sol | 12 +- templates/react/packages/client/src/index.tsx | 2 +- .../packages/client/src/mud/setupNetwork.ts | 4 +- .../contracts/src/codegen/tables/Counter.sol | 12 +- .../threejs/packages/client/src/index.tsx | 2 +- .../packages/client/src/mud/setupNetwork.ts | 4 +- .../contracts/src/codegen/tables/Position.sol | 26 +- .../vanilla/packages/client/src/index.ts | 2 +- .../packages/client/src/mud/setupNetwork.ts | 4 +- .../contracts/src/codegen/tables/Counter.sol | 12 +- test-data/world-logs.json | 848 ++++++------- 175 files changed, 5711 insertions(+), 3350 deletions(-) create mode 100644 .changeset/cyan-hats-try.md create mode 100644 .changeset/fast-zebras-promise.md create mode 100644 .changeset/rotten-cats-lay.md create mode 100644 .changeset/shy-sheep-wait.md rename packages/{protocol-parser => common}/src/readHex.test.ts (100%) rename packages/{protocol-parser => common}/src/readHex.ts (100%) create mode 100644 packages/common/src/spliceHex.ts create mode 100644 packages/dev-tools/src/events/LogsTable.tsx delete mode 100644 packages/dev-tools/src/events/StorageOperationsTable.tsx create mode 100644 packages/protocol-parser/src/decodeValueArgs.ts create mode 100644 packages/protocol-parser/src/encodeLengths.test.ts create mode 100644 packages/protocol-parser/src/encodeLengths.ts create mode 100644 packages/protocol-parser/src/encodeValueArgs.ts delete mode 100644 packages/store-sync/src/blockLogsToStorage.test.ts delete mode 100644 packages/store-sync/src/blockLogsToStorage.ts create mode 100644 packages/store-sync/src/isTableRegistrationLog.ts create mode 100644 packages/store-sync/src/logToTable.test.ts create mode 100644 packages/store-sync/src/logToTable.ts delete mode 100644 packages/store-sync/src/postgres/getSchema.test.ts delete mode 100644 packages/store-sync/src/postgres/getSchema.ts rename packages/store-sync/src/sqlite/{buildSqliteColumn.ts => buildColumn.ts} (95%) create mode 100644 packages/store-sync/src/sqlite/buildTable.test.ts rename packages/store-sync/src/sqlite/{createSqliteTable.ts => buildTable.ts} (70%) delete mode 100644 packages/store-sync/src/sqlite/createSqliteTable.test.ts diff --git a/.changeset/cyan-hats-try.md b/.changeset/cyan-hats-try.md new file mode 100644 index 0000000000..877a795bba --- /dev/null +++ b/.changeset/cyan-hats-try.md @@ -0,0 +1,30 @@ +--- +"@latticexyz/store": major +"@latticexyz/world": major +--- + +We've updated Store events to be "schemaless", meaning there is enough information in each event to only need to operate on the bytes of each record to make an update to that record without having to first decode the record by its schema. This enables new kinds of indexers and sync strategies. + +If you've written your own sync logic or are interacting with Store calls directly, this is a breaking change. We have a few more breaking protocol changes upcoming, so you may hold off on upgrading until those land. + +If you are using MUD's built-in tooling (table codegen, indexer, store sync, etc.), you don't have to make any changes except upgrading to the latest versions and deploying a fresh World. + +- The `data` field in each `StoreSetRecord` and `StoreEphemeralRecord` has been replaced with three new fields: `staticData`, `encodedLengths`, and `dynamicData`. This better reflects the on-chain state and makes it easier to perform modifications to the raw bytes. We recommend storing each of these fields individually in your off-chain storage of choice (indexer, client, etc.). + + ```diff + - event StoreSetRecord(bytes32 tableId, bytes32[] keyTuple, bytes data); + + event StoreSetRecord(bytes32 tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData); + + - event StoreEphemeralRecord(bytes32 tableId, bytes32[] keyTuple, bytes data); + + event StoreEphemeralRecord(bytes32 tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData); + ``` + +- The `StoreSetField` event is now replaced by two new events: `StoreSpliceStaticData` and `StoreSpliceDynamicData`. Splicing allows us to perform efficient operations like push and pop, in addition to replacing a field value. We use two events because updating a dynamic-length field also requires updating the record's `encodedLengths` (aka PackedCounter). + + ```diff + - event StoreSetField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes data); + + event StoreSpliceStaticData(bytes32 tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data); + + event StoreSpliceDynamicData(bytes32 tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data, bytes32 encodedLengths); + ``` + +Similarly, Store setter methods (e.g. `setRecord`) have been updated to reflect the `data` to `staticData`, `encodedLengths`, and `dynamicData` changes. We'll be following up shortly with Store getter method changes for more gas efficient storage reads. diff --git a/.changeset/fast-zebras-promise.md b/.changeset/fast-zebras-promise.md new file mode 100644 index 0000000000..f7d1cef47e --- /dev/null +++ b/.changeset/fast-zebras-promise.md @@ -0,0 +1,6 @@ +--- +"@latticexyz/common": minor +"@latticexyz/protocol-parser": major +--- + +`readHex` was moved from `@latticexyz/protocol-parser` to `@latticexyz/common` diff --git a/.changeset/rotten-cats-lay.md b/.changeset/rotten-cats-lay.md new file mode 100644 index 0000000000..021154c423 --- /dev/null +++ b/.changeset/rotten-cats-lay.md @@ -0,0 +1,9 @@ +--- +"@latticexyz/common": minor +--- + +`spliceHex` was added, which has a similar API as JavaScript's [`Array.prototype.splice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice), but for `Hex` strings. + +```ts +spliceHex("0x123456", 1, 1, "0x0000"); // "0x12000056" +``` diff --git a/.changeset/shy-sheep-wait.md b/.changeset/shy-sheep-wait.md new file mode 100644 index 0000000000..baabf2b946 --- /dev/null +++ b/.changeset/shy-sheep-wait.md @@ -0,0 +1,9 @@ +--- +"@latticexyz/dev-tools": major +"@latticexyz/store-sync": major +"create-mud": minor +--- + +We've updated Store events to be "schemaless", meaning there is enough information in each event to only need to operate on the bytes of each record to make an update to that record without having to first decode the record by its schema. This enables new kinds of indexers and sync strategies. + +As such, we've replaced `blockStorageOperations$` with `storedBlockLogs$`, a stream of simplified Store event logs after they've been synced to the configured storage adapter. These logs may not reflect exactly the events that are on chain when e.g. hydrating from an indexer, but they will still allow the client to "catch up" to the on-chain state of your tables. diff --git a/e2e/packages/client-vanilla/src/mud/setupNetwork.ts b/e2e/packages/client-vanilla/src/mud/setupNetwork.ts index ae79c26916..34cb6e7329 100644 --- a/e2e/packages/client-vanilla/src/mud/setupNetwork.ts +++ b/e2e/packages/client-vanilla/src/mud/setupNetwork.ts @@ -33,7 +33,7 @@ export async function setupNetwork() { walletClient: burnerWalletClient, }); - const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({ + const { components, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToRecs({ world, config: mudConfig, address: networkConfig.worldAddress as Hex, @@ -74,7 +74,7 @@ export async function setupNetwork() { walletClient: burnerWalletClient, worldContract, latestBlock$, - blockStorageOperations$, + storedBlockLogs$, waitForTransaction, }; } diff --git a/e2e/packages/contracts/src/codegen/tables/Multi.sol b/e2e/packages/contracts/src/codegen/tables/Multi.sol index a634403932..a66e9b0d72 100644 --- a/e2e/packages/contracts/src/codegen/tables/Multi.sol +++ b/e2e/packages/contracts/src/codegen/tables/Multi.sol @@ -207,7 +207,10 @@ library Multi { /** Set the full data using individual values */ function set(uint32 a, bool b, uint256 c, int120 d, int256 num, bool value) internal { - bytes memory _data = encode(num, value); + bytes memory _staticData = encodeStatic(num, value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(a)); @@ -215,12 +218,15 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ function set(IStore _store, uint32 a, bool b, uint256 c, int120 d, int256 num, bool value) internal { - bytes memory _data = encode(num, value); + bytes memory _staticData = encodeStatic(num, value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(a)); @@ -228,7 +234,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using the data struct */ @@ -248,9 +254,19 @@ library Multi { _table.value = (_toBool(uint8(Bytes.slice1(_blob, 32)))); } + /** 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) { - return abi.encodePacked(num, value); + bytes memory _staticData = encodeStatic(num, value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/e2e/packages/contracts/src/codegen/tables/Number.sol b/e2e/packages/contracts/src/codegen/tables/Number.sol index 01127f809c..68d463bacd 100644 --- a/e2e/packages/contracts/src/codegen/tables/Number.sol +++ b/e2e/packages/contracts/src/codegen/tables/Number.sol @@ -109,9 +109,19 @@ library Number { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint32 value) internal pure returns (bytes memory) { + return abi.encodePacked(value); + } + /** Tightly pack full data using this table's field layout */ function encode(uint32 value) internal pure returns (bytes memory) { - return abi.encodePacked(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/e2e/packages/contracts/src/codegen/tables/NumberList.sol b/e2e/packages/contracts/src/codegen/tables/NumberList.sol index 60d34cc507..76ab24b8e5 100644 --- a/e2e/packages/contracts/src/codegen/tables/NumberList.sol +++ b/e2e/packages/contracts/src/codegen/tables/NumberList.sol @@ -207,15 +207,26 @@ library NumberList { } } - /** Tightly pack full data using this table's field layout */ - function encode(uint32[] memory value) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + /** 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 unchecked { _encodedLengths = PackedCounterLib.pack(value.length * 4); } + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(uint32[] memory value) internal pure returns (bytes memory) { + return abi.encodePacked(EncodeArray.encode((value))); + } + + /** Tightly pack full data using this table's field layout */ + function encode(uint32[] memory value) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(value); + bytes memory _dynamicData = encodeDynamic(value); - return abi.encodePacked(_encodedLengths.unwrap(), EncodeArray.encode((value))); + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/e2e/packages/contracts/src/codegen/tables/Vector.sol b/e2e/packages/contracts/src/codegen/tables/Vector.sol index e258fac50c..c64c1d9086 100644 --- a/e2e/packages/contracts/src/codegen/tables/Vector.sol +++ b/e2e/packages/contracts/src/codegen/tables/Vector.sol @@ -171,22 +171,28 @@ library Vector { /** Set the full data using individual values */ function set(uint32 key, int32 x, int32 y) internal { - bytes memory _data = encode(x, y); + bytes memory _staticData = encodeStatic(x, y); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ function set(IStore _store, uint32 key, int32 x, int32 y) internal { - bytes memory _data = encode(x, y); + bytes memory _staticData = encodeStatic(x, y); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using the data struct */ @@ -206,9 +212,19 @@ library Vector { _table.y = (int32(uint32(Bytes.slice4(_blob, 4)))); } + /** 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); + } + /** Tightly pack full data using this table's field layout */ function encode(int32 x, int32 y) internal pure returns (bytes memory) { - return abi.encodePacked(x, y); + bytes memory _staticData = encodeStatic(x, y); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/e2e/packages/contracts/worlds.json b/e2e/packages/contracts/worlds.json index bd48105fd7..a9623cfa62 100644 --- a/e2e/packages/contracts/worlds.json +++ b/e2e/packages/contracts/worlds.json @@ -1,5 +1,5 @@ { "31337": { - "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3" + "address": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c" } } \ No newline at end of file diff --git a/e2e/packages/sync-test/data/encodeTestData.test.ts b/e2e/packages/sync-test/data/encodeTestData.test.ts index df67bb56e2..11c919ac0e 100644 --- a/e2e/packages/sync-test/data/encodeTestData.test.ts +++ b/e2e/packages/sync-test/data/encodeTestData.test.ts @@ -3,24 +3,36 @@ import { encodeTestData } from "./encodeTestData"; describe("encodeTestData", () => { it("should encode numbers", () => { - expect(encodeTestData({ Number: [{ key: { key: 42 }, value: { value: 1337 } }] })).toStrictEqual({ - Number: [ - { - key: ["0x000000000000000000000000000000000000000000000000000000000000002a"], - value: "0x00000539", - valueSchema: "0x0004010003000000000000000000000000000000000000000000000000000000", - }, - ], - }); + expect(encodeTestData({ Number: [{ key: { key: 42 }, value: { value: 1337 } }] })).toMatchInlineSnapshot(` + { + "Number": [ + { + "dynamicData": "0x", + "encodedLengths": "0x0000000000000000000000000000000000000000000000000000000000000000", + "fieldLayout": "0x0004010004000000000000000000000000000000000000000000000000000000", + "key": [ + "0x000000000000000000000000000000000000000000000000000000000000002a", + ], + "staticData": "0x00000539", + }, + ], + } + `); - expect(encodeTestData({ Vector: [{ key: { key: 1337 }, value: { x: 42, y: -69 } }] })).toStrictEqual({ - Vector: [ - { - key: ["0x0000000000000000000000000000000000000000000000000000000000000539"], - value: "0x0000002affffffbb", - valueSchema: "0x0008020023230000000000000000000000000000000000000000000000000000", - }, - ], - }); + expect(encodeTestData({ Vector: [{ key: { key: 1337 }, value: { x: 42, y: -69 } }] })).toMatchInlineSnapshot(` + { + "Vector": [ + { + "dynamicData": "0x", + "encodedLengths": "0x0000000000000000000000000000000000000000000000000000000000000000", + "fieldLayout": "0x0008020004040000000000000000000000000000000000000000000000000000", + "key": [ + "0x0000000000000000000000000000000000000000000000000000000000000539", + ], + "staticData": "0x0000002affffffbb", + }, + ], + } + `); }); }); diff --git a/e2e/packages/sync-test/data/encodeTestData.ts b/e2e/packages/sync-test/data/encodeTestData.ts index a433626d61..891d770dc4 100644 --- a/e2e/packages/sync-test/data/encodeTestData.ts +++ b/e2e/packages/sync-test/data/encodeTestData.ts @@ -1,9 +1,7 @@ import { mapObject } from "@latticexyz/utils"; +import { encodeKey, encodeValueArgs, valueSchemaToFieldLayoutHex } from "@latticexyz/protocol-parser"; import { Data, EncodedData } from "./types"; -import { encodeAbiParameters, encodePacked } from "viem"; import config from "../../contracts/mud.config"; -import { abiTypesToSchema, schemaToHex } from "@latticexyz/protocol-parser"; -import { StaticAbiType } from "@latticexyz/schema-type"; /** * Turns the typed data into encoded data in the format expected by `world.setRecord` @@ -11,21 +9,16 @@ import { StaticAbiType } from "@latticexyz/schema-type"; export function encodeTestData(testData: Data) { return mapObject(testData, (records, table) => { if (!records) return undefined; - const keyConfig = config.tables[table].keySchema; + const tableConfig = config.tables[table]; return records.map((record) => { - const encodedKey = Object.entries(record.key).map(([keyName, keyValue]) => { - const keyType = keyConfig[keyName as keyof typeof keyConfig] as StaticAbiType; - return encodeAbiParameters([{ type: keyType }], [keyValue]); - }); - - const encodedValue = encodePacked(Object.values(config.tables[table].valueSchema), Object.values(record.value)); - - const encodedValueSchema = schemaToHex(abiTypesToSchema(Object.values(config.tables[table].valueSchema))); + const key = encodeKey(tableConfig.keySchema, record.key); + const valueArgs = encodeValueArgs(tableConfig.valueSchema, record.value); + const fieldLayout = valueSchemaToFieldLayoutHex(tableConfig.valueSchema); return { - key: encodedKey, - value: encodedValue, - valueSchema: encodedValueSchema, + key, + ...valueArgs, + fieldLayout, }; }); }) as EncodedData; diff --git a/e2e/packages/sync-test/data/expectClientData.ts b/e2e/packages/sync-test/data/expectClientData.ts index 6e52c0fc3d..92e81c323f 100644 --- a/e2e/packages/sync-test/data/expectClientData.ts +++ b/e2e/packages/sync-test/data/expectClientData.ts @@ -11,7 +11,7 @@ export async function expectClientData(page: Page, data: Data) { for (const [table, records] of Object.entries(data)) { for (const record of records) { const value = await readComponentValue(page, table, encodeEntity(config.tables[table].keySchema, record.key)); - expect(value).toEqual(record.value); + expect(value).toMatchObject(record.value); } } } diff --git a/e2e/packages/sync-test/data/setContractData.ts b/e2e/packages/sync-test/data/setContractData.ts index 5ca090cae8..323189d95c 100644 --- a/e2e/packages/sync-test/data/setContractData.ts +++ b/e2e/packages/sync-test/data/setContractData.ts @@ -16,8 +16,10 @@ export async function setContractData(page: Page, data: Data) { // TODO: add support for multiple namespaces after https://github.com/latticexyz/mud/issues/994 is resolved tableIdToHex("", table), record.key, - record.value, - record.valueSchema, + record.staticData, + record.encodedLengths, + record.dynamicData, + record.fieldLayout, ]); // Wait for transactions to be confirmed diff --git a/e2e/packages/sync-test/data/types.ts b/e2e/packages/sync-test/data/types.ts index 85abd2c90d..b79ac3f3b6 100644 --- a/e2e/packages/sync-test/data/types.ts +++ b/e2e/packages/sync-test/data/types.ts @@ -20,5 +20,5 @@ export type Datum> }; export type EncodedData = { - [Table in keyof T]: Array<{ key: Hex[]; value: Hex; valueSchema: Hex }>; + [Table in keyof T]: Array<{ key: Hex[]; staticData: Hex; encodedLengths: Hex; dynamicData: Hex; fieldLayout: Hex }>; }; diff --git a/e2e/packages/sync-test/rpcSync.test.ts b/e2e/packages/sync-test/rpcSync.test.ts index 7726f86995..39e786a319 100644 --- a/e2e/packages/sync-test/rpcSync.test.ts +++ b/e2e/packages/sync-test/rpcSync.test.ts @@ -1,7 +1,6 @@ import { afterEach, beforeEach, describe, test } from "vitest"; import type { ViteDevServer } from "vite"; import { Browser, Page } from "@playwright/test"; -import { ExecaChildProcess } from "execa"; import { createAsyncErrorHandler } from "./asyncErrors"; import { deployContracts, startViteServer, startBrowserAndPage, openClientWithRootAccount } from "./setup"; import { diff --git a/e2e/packages/sync-test/setup/startBrowserAndPage.ts b/e2e/packages/sync-test/setup/startBrowserAndPage.ts index f5ab642f9b..0f18151879 100644 --- a/e2e/packages/sync-test/setup/startBrowserAndPage.ts +++ b/e2e/packages/sync-test/setup/startBrowserAndPage.ts @@ -14,7 +14,7 @@ export async function startBrowserAndPage( // log uncaught errors in the browser page (browser and test consoles are separate) page.on("pageerror", (err) => { - console.log(chalk.yellow("[browser page error]:"), err.message); + console.log(chalk.yellow("[browser page error]:"), err.message, err); }); // log browser's console logs diff --git a/e2e/packages/sync-test/vite.config.ts b/e2e/packages/sync-test/vite.config.ts index aee36eb400..c6202f1992 100644 --- a/e2e/packages/sync-test/vite.config.ts +++ b/e2e/packages/sync-test/vite.config.ts @@ -1,6 +1,5 @@ import { defineConfig } from "vitest/config"; -// TODO should this along with `.test.ts` be in `client-vanilla`? export default defineConfig({ test: { environment: "jsdom", diff --git a/examples/minimal/packages/client-phaser/src/mud/setupNetwork.ts b/examples/minimal/packages/client-phaser/src/mud/setupNetwork.ts index 85bac97cd8..144ecd4a33 100644 --- a/examples/minimal/packages/client-phaser/src/mud/setupNetwork.ts +++ b/examples/minimal/packages/client-phaser/src/mud/setupNetwork.ts @@ -36,7 +36,7 @@ export async function setupNetwork() { onWrite: (write) => write$.next(write), }); - const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({ + const { components, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToRecs({ world, config: mudConfig, address: networkConfig.worldAddress as Hex, @@ -75,7 +75,7 @@ export async function setupNetwork() { publicClient, walletClient: burnerWalletClient, latestBlock$, - blockStorageOperations$, + storedBlockLogs$, waitForTransaction, worldContract, write$: write$.asObservable().pipe(share()), diff --git a/examples/minimal/packages/client-phaser/src/ui/App.tsx b/examples/minimal/packages/client-phaser/src/ui/App.tsx index 314e5572d4..69529815b5 100644 --- a/examples/minimal/packages/client-phaser/src/ui/App.tsx +++ b/examples/minimal/packages/client-phaser/src/ui/App.tsx @@ -21,7 +21,7 @@ export const App = () => { publicClient: networkLayer.network.publicClient, walletClient: networkLayer.network.walletClient, latestBlock$: networkLayer.network.latestBlock$, - blockStorageOperations$: networkLayer.network.blockStorageOperations$, + storedBlockLogs$: networkLayer.network.storedBlockLogs$, worldAddress: networkLayer.network.worldContract.address, worldAbi: networkLayer.network.worldContract.abi, write$: networkLayer.network.write$, diff --git a/examples/minimal/packages/client-react/src/index.tsx b/examples/minimal/packages/client-react/src/index.tsx index 9b3f9121e1..da8d70f020 100644 --- a/examples/minimal/packages/client-react/src/index.tsx +++ b/examples/minimal/packages/client-react/src/index.tsx @@ -24,7 +24,7 @@ setup().then(async (result) => { publicClient: result.network.publicClient, walletClient: result.network.walletClient, latestBlock$: result.network.latestBlock$, - blockStorageOperations$: result.network.blockStorageOperations$, + storedBlockLogs$: result.network.storedBlockLogs$, worldAddress: result.network.worldContract.address, worldAbi: result.network.worldContract.abi, write$: result.network.write$, diff --git a/examples/minimal/packages/client-react/src/mud/setupNetwork.ts b/examples/minimal/packages/client-react/src/mud/setupNetwork.ts index 9c42a54e14..d11cd48e24 100644 --- a/examples/minimal/packages/client-react/src/mud/setupNetwork.ts +++ b/examples/minimal/packages/client-react/src/mud/setupNetwork.ts @@ -36,7 +36,7 @@ export async function setupNetwork() { onWrite: (write) => write$.next(write), }); - const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({ + const { components, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToRecs({ world, config: mudConfig, address: networkConfig.worldAddress as Hex, @@ -75,7 +75,7 @@ export async function setupNetwork() { publicClient, walletClient: burnerWalletClient, latestBlock$, - blockStorageOperations$, + storedBlockLogs$, waitForTransaction, worldContract, write$: write$.asObservable().pipe(share()), diff --git a/examples/minimal/packages/client-vanilla/src/index.ts b/examples/minimal/packages/client-vanilla/src/index.ts index fe63aa1950..8666b71a68 100644 --- a/examples/minimal/packages/client-vanilla/src/index.ts +++ b/examples/minimal/packages/client-vanilla/src/index.ts @@ -62,7 +62,7 @@ if (import.meta.env.DEV) { publicClient: network.publicClient, walletClient: network.walletClient, latestBlock$: network.latestBlock$, - blockStorageOperations$: network.blockStorageOperations$, + storedBlockLogs$: network.storedBlockLogs$, worldAddress: network.worldContract.address, worldAbi: network.worldContract.abi, write$: network.write$, diff --git a/examples/minimal/packages/client-vanilla/src/mud/setupNetwork.ts b/examples/minimal/packages/client-vanilla/src/mud/setupNetwork.ts index 85bac97cd8..144ecd4a33 100644 --- a/examples/minimal/packages/client-vanilla/src/mud/setupNetwork.ts +++ b/examples/minimal/packages/client-vanilla/src/mud/setupNetwork.ts @@ -36,7 +36,7 @@ export async function setupNetwork() { onWrite: (write) => write$.next(write), }); - const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({ + const { components, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToRecs({ world, config: mudConfig, address: networkConfig.worldAddress as Hex, @@ -75,7 +75,7 @@ export async function setupNetwork() { publicClient, walletClient: burnerWalletClient, latestBlock$, - blockStorageOperations$, + storedBlockLogs$, waitForTransaction, worldContract, write$: write$.asObservable().pipe(share()), diff --git a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol index ed4f112789..0de74a8c72 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol @@ -103,9 +103,19 @@ library CounterTable { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint32 value) internal pure returns (bytes memory) { + return abi.encodePacked(value); + } + /** Tightly pack full data using this table's field layout */ function encode(uint32 value) internal pure returns (bytes memory) { - return abi.encodePacked(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol index 96df3c93dd..15c35b4678 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol @@ -121,9 +121,19 @@ library Inventory { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((amount)), getFieldLayout()); } + /** 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) { - return abi.encodePacked(amount); + bytes memory _staticData = encodeStatic(amount); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol index 5fe5d13250..142691da0a 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol @@ -74,31 +74,46 @@ library MessageTable { /** Emit the ephemeral event using individual values */ function emitEphemeral(string memory value) internal { - bytes memory _data = encode(value); + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(value); + bytes memory _dynamicData = encodeDynamic(value); bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Emit the ephemeral event using individual values (using the specified store) */ function emitEphemeral(IStore _store, string memory value) internal { - bytes memory _data = encode(value); + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(value); + bytes memory _dynamicData = encodeDynamic(value); bytes32[] memory _keyTuple = new bytes32[](0); - _store.emitEphemeralRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } - /** Tightly pack full data using this table's field layout */ - function encode(string memory value) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + /** Tightly pack dynamic data using this table's schema */ + function encodeLengths(string memory value) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits unchecked { _encodedLengths = PackedCounterLib.pack(bytes(value).length); } + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(string memory value) internal pure returns (bytes memory) { + return abi.encodePacked(bytes((value))); + } + + /** Tightly pack full data using this table's field layout */ + function encode(string memory value) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(value); + bytes memory _dynamicData = encodeDynamic(value); - return abi.encodePacked(_encodedLengths.unwrap(), bytes((value))); + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol b/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol index ac62fff28f..0bd179745f 100644 --- a/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol +++ b/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol @@ -13,8 +13,15 @@ import { IChatNamespacedSystem } from "../src/interfaces/IChatNamespacedSystem.s contract ChatNamespacedTest is MudTest { function testEmitEphemeral() public { bytes32[] memory keyTuple; + string memory value = "test"; vm.expectEmit(true, true, true, true); - emit StoreCore.StoreEphemeralRecord(MessageTableTableId, keyTuple, MessageTable.encode("test")); - IChatNamespacedSystem(worldAddress).namespace_ChatNamespaced_sendMessage("test"); + emit StoreCore.StoreEphemeralRecord( + MessageTableTableId, + keyTuple, + new bytes(0), + MessageTable.encodeLengths(value).unwrap(), + MessageTable.encodeDynamic(value) + ); + IChatNamespacedSystem(worldAddress).namespace_ChatNamespaced_sendMessage(value); } } diff --git a/packages/block-logs-stream/src/groupLogsByBlockNumber.ts b/packages/block-logs-stream/src/groupLogsByBlockNumber.ts index e0d2f1144e..b0656acfbc 100644 --- a/packages/block-logs-stream/src/groupLogsByBlockNumber.ts +++ b/packages/block-logs-stream/src/groupLogsByBlockNumber.ts @@ -4,7 +4,7 @@ import { bigIntSort, isDefined } from "@latticexyz/common/utils"; type PartialLog = { blockNumber: bigint; logIndex: number }; export type GroupLogsByBlockNumberResult = { - blockNumber: BlockNumber; + blockNumber: TLog["blockNumber"]; logs: TLog[]; }[]; diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol index 368c3b73f4..f32451cf30 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol @@ -925,12 +925,14 @@ library Dynamics1 { address[4] memory staticAddrs, bool[5] memory staticBools ) internal { - bytes memory _data = encode(staticB32, staticI32, staticU128, staticAddrs, staticBools); + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(staticB32, staticI32, staticU128, staticAddrs, staticBools); + bytes memory _dynamicData = encodeDynamic(staticB32, staticI32, staticU128, staticAddrs, staticBools); bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ @@ -943,12 +945,14 @@ library Dynamics1 { address[4] memory staticAddrs, bool[5] memory staticBools ) internal { - bytes memory _data = encode(staticB32, staticI32, staticU128, staticAddrs, staticBools); + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(staticB32, staticI32, staticU128, staticAddrs, staticBools); + bytes memory _dynamicData = encodeDynamic(staticB32, staticI32, staticU128, staticAddrs, staticBools); bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using the data struct */ @@ -1005,15 +1009,14 @@ library Dynamics1 { } } - /** Tightly pack full data using this table's field layout */ - function encode( + /** Tightly pack dynamic data using this table's schema */ + function encodeLengths( bytes32[1] memory staticB32, int32[2] memory staticI32, uint128[3] memory staticU128, address[4] memory staticAddrs, bool[5] memory staticBools - ) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + ) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits unchecked { _encodedLengths = PackedCounterLib.pack( @@ -1024,10 +1027,18 @@ library Dynamics1 { staticBools.length * 1 ); } + } + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic( + bytes32[1] memory staticB32, + int32[2] memory staticI32, + uint128[3] memory staticU128, + address[4] memory staticAddrs, + bool[5] memory staticBools + ) internal pure returns (bytes memory) { return abi.encodePacked( - _encodedLengths.unwrap(), EncodeArray.encode(fromStaticArray_bytes32_1(staticB32)), EncodeArray.encode(fromStaticArray_int32_2(staticI32)), EncodeArray.encode(fromStaticArray_uint128_3(staticU128)), @@ -1036,6 +1047,21 @@ library Dynamics1 { ); } + /** Tightly pack full data using this table's field layout */ + function encode( + bytes32[1] memory staticB32, + int32[2] memory staticI32, + uint128[3] memory staticU128, + address[4] memory staticAddrs, + bool[5] memory staticBools + ) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(staticB32, staticI32, staticU128, staticAddrs, staticBools); + bytes memory _dynamicData = encodeDynamic(staticB32, staticI32, staticU128, staticAddrs, staticBools); + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + } + /** Encode keys as a bytes32 array using this table's field layout */ function encodeKeyTuple(bytes32 key) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](1); diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol index 3bcbe30cd3..9ced950df1 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol @@ -551,22 +551,26 @@ library Dynamics2 { /** Set the full data using individual values */ function set(bytes32 key, uint64[] memory u64, string memory str, bytes memory b) internal { - bytes memory _data = encode(u64, str, b); + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(u64, str, b); + bytes memory _dynamicData = encodeDynamic(u64, str, b); bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 key, uint64[] memory u64, string memory str, bytes memory b) internal { - bytes memory _data = encode(u64, str, b); + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(u64, str, b); + bytes memory _dynamicData = encodeDynamic(u64, str, b); bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using the data struct */ @@ -611,15 +615,30 @@ library Dynamics2 { } } - /** Tightly pack full data using this table's field layout */ - function encode(uint64[] memory u64, string memory str, bytes memory b) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + /** Tightly pack dynamic data using this table's schema */ + function encodeLengths( + uint64[] memory u64, + string memory str, + bytes memory b + ) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits unchecked { _encodedLengths = PackedCounterLib.pack(u64.length * 8, bytes(str).length, bytes(b).length); } + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(uint64[] memory u64, string memory str, bytes memory b) internal pure returns (bytes memory) { + return abi.encodePacked(EncodeArray.encode((u64)), bytes((str)), bytes((b))); + } + + /** Tightly pack full data using this table's field layout */ + function encode(uint64[] memory u64, string memory str, bytes memory b) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(u64, str, b); + bytes memory _dynamicData = encodeDynamic(u64, str, b); - return abi.encodePacked(_encodedLengths.unwrap(), EncodeArray.encode((u64)), bytes((str)), bytes((b))); + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol b/packages/cli/contracts/src/codegen/tables/Ephemeral.sol index 0f9cec20cc..0742a42eb8 100644 --- a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol +++ b/packages/cli/contracts/src/codegen/tables/Ephemeral.sol @@ -77,27 +77,43 @@ library Ephemeral { /** Emit the ephemeral event using individual values */ function emitEphemeral(bytes32 key, uint256 value) internal { - bytes memory _data = encode(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Emit the ephemeral event using individual values (using the specified store) */ function emitEphemeral(IStore _store, bytes32 key, uint256 value) internal { - bytes memory _data = encode(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.emitEphemeralRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + } + + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint256 value) internal pure returns (bytes memory) { + return abi.encodePacked(value); } /** Tightly pack full data using this table's field layout */ function encode(uint256 value) internal pure returns (bytes memory) { - return abi.encodePacked(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/cli/contracts/src/codegen/tables/Singleton.sol b/packages/cli/contracts/src/codegen/tables/Singleton.sol index c309eedd60..29ef27a1d8 100644 --- a/packages/cli/contracts/src/codegen/tables/Singleton.sol +++ b/packages/cli/contracts/src/codegen/tables/Singleton.sol @@ -534,20 +534,26 @@ library Singleton { /** Set the full data using individual values */ function set(int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) internal { - bytes memory _data = encode(v1, v2, v3, v4); + bytes memory _staticData = encodeStatic(v1); + + PackedCounter _encodedLengths = encodeLengths(v2, v3, v4); + bytes memory _dynamicData = encodeDynamic(v2, v3, v4); bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ function set(IStore _store, int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) internal { - bytes memory _data = encode(v1, v2, v3, v4); + bytes memory _staticData = encodeStatic(v1); + + PackedCounter _encodedLengths = encodeLengths(v2, v3, v4); + bytes memory _dynamicData = encodeDynamic(v2, v3, v4); bytes32[] memory _keyTuple = new bytes32[](0); - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** @@ -586,29 +592,52 @@ library Singleton { } } - /** Tightly pack full data using this table's field layout */ - function encode( - int256 v1, + /** Tightly pack static data using this table's schema */ + function encodeStatic(int256 v1) internal pure returns (bytes memory) { + return abi.encodePacked(v1); + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeLengths( uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4 - ) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + ) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits unchecked { _encodedLengths = PackedCounterLib.pack(v2.length * 4, v3.length * 4, v4.length * 4); } + } + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic( + uint32[2] memory v2, + uint32[2] memory v3, + uint32[1] memory v4 + ) internal pure returns (bytes memory) { return abi.encodePacked( - v1, - _encodedLengths.unwrap(), EncodeArray.encode(fromStaticArray_uint32_2(v2)), EncodeArray.encode(fromStaticArray_uint32_2(v3)), EncodeArray.encode(fromStaticArray_uint32_1(v4)) ); } + /** Tightly pack full data using this table's field layout */ + function encode( + int256 v1, + uint32[2] memory v2, + uint32[2] memory v3, + uint32[1] memory v4 + ) internal pure returns (bytes memory) { + bytes memory _staticData = encodeStatic(v1); + + PackedCounter _encodedLengths = encodeLengths(v2, v3, v4); + bytes memory _dynamicData = encodeDynamic(v2, v3, v4); + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + } + /** Encode keys as a bytes32 array using this table's field layout */ function encodeKeyTuple() internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](0); diff --git a/packages/cli/contracts/src/codegen/tables/Statics.sol b/packages/cli/contracts/src/codegen/tables/Statics.sol index 089552188c..9d6fcab330 100644 --- a/packages/cli/contracts/src/codegen/tables/Statics.sol +++ b/packages/cli/contracts/src/codegen/tables/Statics.sol @@ -19,7 +19,7 @@ import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; // Import user types -import { Enum1, Enum2 } from "./../Types.sol"; +import { Enum2, Enum1 } from "./../Types.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Statics"))); bytes32 constant StaticsTableId = _tableId; @@ -31,74 +31,68 @@ struct StaticsData { address v4; bool v5; Enum1 v6; - Enum2 v7; } library Statics { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](7); + uint256[] memory _fieldLayout = new uint256[](6); _fieldLayout[0] = 32; _fieldLayout[1] = 4; _fieldLayout[2] = 16; _fieldLayout[3] = 20; _fieldLayout[4] = 1; _fieldLayout[5] = 1; - _fieldLayout[6] = 1; return FieldLayoutLib.encode(_fieldLayout, 0); } /** Get the table's key schema */ function getKeySchema() internal pure returns (Schema) { - SchemaType[] memory _keySchema = new SchemaType[](7); + SchemaType[] memory _keySchema = new SchemaType[](6); _keySchema[0] = SchemaType.UINT256; _keySchema[1] = SchemaType.INT32; _keySchema[2] = SchemaType.BYTES16; _keySchema[3] = SchemaType.ADDRESS; _keySchema[4] = SchemaType.BOOL; _keySchema[5] = SchemaType.UINT8; - _keySchema[6] = SchemaType.UINT8; return SchemaLib.encode(_keySchema); } /** Get the table's value schema */ function getValueSchema() internal pure returns (Schema) { - SchemaType[] memory _valueSchema = new SchemaType[](7); + SchemaType[] memory _valueSchema = new SchemaType[](6); _valueSchema[0] = SchemaType.UINT256; _valueSchema[1] = SchemaType.INT32; _valueSchema[2] = SchemaType.BYTES16; _valueSchema[3] = SchemaType.ADDRESS; _valueSchema[4] = SchemaType.BOOL; _valueSchema[5] = SchemaType.UINT8; - _valueSchema[6] = SchemaType.UINT8; return SchemaLib.encode(_valueSchema); } /** Get the table's key names */ function getKeyNames() internal pure returns (string[] memory keyNames) { - keyNames = new string[](7); + keyNames = new string[](6); keyNames[0] = "k1"; keyNames[1] = "k2"; keyNames[2] = "k3"; keyNames[3] = "k4"; keyNames[4] = "k5"; keyNames[5] = "k6"; - keyNames[6] = "k7"; } /** Get the table's field names */ function getFieldNames() internal pure returns (string[] memory fieldNames) { - fieldNames = new string[](7); + fieldNames = new string[](6); fieldNames[0] = "v1"; fieldNames[1] = "v2"; fieldNames[2] = "v3"; fieldNames[3] = "v4"; fieldNames[4] = "v5"; fieldNames[5] = "v6"; - fieldNames[6] = "v7"; } /** Register the table with its config */ @@ -119,23 +113,14 @@ library Statics { } /** Get v1 */ - function getV1( - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7 - ) internal view returns (uint256 v1) { - bytes32[] memory _keyTuple = new bytes32[](7); + function getV1(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (uint256 v1) { + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); return (uint256(Bytes.slice32(_blob, 0))); @@ -149,78 +134,55 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7 + Enum2 k6 ) internal view returns (uint256 v1) { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); return (uint256(Bytes.slice32(_blob, 0))); } /** Set v1 */ - function setV1(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum1 k6, Enum2 k7, uint256 v1) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV1(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, uint256 v1) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), getFieldLayout()); } /** Set v1 (using the specified store) */ - function setV1( - IStore _store, - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7, - uint256 v1 - ) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV1(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, uint256 v1) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), getFieldLayout()); } /** Get v2 */ - function getV2( - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7 - ) internal view returns (int32 v2) { - bytes32[] memory _keyTuple = new bytes32[](7); + function getV2(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (int32 v2) { + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); return (int32(uint32(Bytes.slice4(_blob, 0)))); @@ -234,78 +196,55 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7 + Enum2 k6 ) internal view returns (int32 v2) { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); return (int32(uint32(Bytes.slice4(_blob, 0)))); } /** Set v2 */ - function setV2(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum1 k6, Enum2 k7, int32 v2) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV2(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, int32 v2) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((v2)), getFieldLayout()); } /** Set v2 (using the specified store) */ - function setV2( - IStore _store, - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7, - int32 v2 - ) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV2(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, int32 v2) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((v2)), getFieldLayout()); } /** Get v3 */ - function getV3( - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7 - ) internal view returns (bytes16 v3) { - bytes32[] memory _keyTuple = new bytes32[](7); + function getV3(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (bytes16 v3) { + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, getFieldLayout()); return (Bytes.slice16(_blob, 0)); @@ -319,78 +258,55 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7 + Enum2 k6 ) internal view returns (bytes16 v3) { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, getFieldLayout()); return (Bytes.slice16(_blob, 0)); } /** Set v3 */ - function setV3(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum1 k6, Enum2 k7, bytes16 v3) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV3(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, bytes16 v3) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _keyTuple, 2, abi.encodePacked((v3)), getFieldLayout()); } /** Set v3 (using the specified store) */ - function setV3( - IStore _store, - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7, - bytes16 v3 - ) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV3(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, bytes16 v3) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); _store.setField(_tableId, _keyTuple, 2, abi.encodePacked((v3)), getFieldLayout()); } /** Get v4 */ - function getV4( - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7 - ) internal view returns (address v4) { - bytes32[] memory _keyTuple = new bytes32[](7); + function getV4(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (address v4) { + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, getFieldLayout()); return (address(Bytes.slice20(_blob, 0))); @@ -404,78 +320,55 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7 + Enum2 k6 ) internal view returns (address v4) { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, getFieldLayout()); return (address(Bytes.slice20(_blob, 0))); } /** Set v4 */ - function setV4(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum1 k6, Enum2 k7, address v4) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV4(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, address v4) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _keyTuple, 3, abi.encodePacked((v4)), getFieldLayout()); } /** Set v4 (using the specified store) */ - function setV4( - IStore _store, - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7, - address v4 - ) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV4(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, address v4) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); _store.setField(_tableId, _keyTuple, 3, abi.encodePacked((v4)), getFieldLayout()); } /** Get v5 */ - function getV5( - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7 - ) internal view returns (bool v5) { - bytes32[] memory _keyTuple = new bytes32[](7); + function getV5(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (bool v5) { + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, getFieldLayout()); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); @@ -489,78 +382,55 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7 + Enum2 k6 ) internal view returns (bool v5) { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, getFieldLayout()); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } /** Set v5 */ - function setV5(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum1 k6, Enum2 k7, bool v5) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV5(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, bool v5) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _keyTuple, 4, abi.encodePacked((v5)), getFieldLayout()); } /** Set v5 (using the specified store) */ - function setV5( - IStore _store, - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7, - bool v5 - ) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV5(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, bool v5) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); _store.setField(_tableId, _keyTuple, 4, abi.encodePacked((v5)), getFieldLayout()); } /** Get v6 */ - function getV6( - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7 - ) internal view returns (Enum1 v6) { - bytes32[] memory _keyTuple = new bytes32[](7); + function getV6(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (Enum1 v6) { + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 5, getFieldLayout()); return Enum1(uint8(Bytes.slice1(_blob, 0))); @@ -574,145 +444,46 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7 + Enum2 k6 ) internal view returns (Enum1 v6) { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = _store.getField(_tableId, _keyTuple, 5, getFieldLayout()); return Enum1(uint8(Bytes.slice1(_blob, 0))); } /** Set v6 */ - function setV6(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum1 k6, Enum2 k7, Enum1 v6) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV6(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, Enum1 v6) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _keyTuple, 5, abi.encodePacked(uint8(v6)), getFieldLayout()); } /** Set v6 (using the specified store) */ - function setV6( - IStore _store, - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7, - Enum1 v6 - ) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + function setV6(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, Enum1 v6) 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); _store.setField(_tableId, _keyTuple, 5, abi.encodePacked(uint8(v6)), getFieldLayout()); } - /** Get v7 */ - function getV7( - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7 - ) internal view returns (Enum2 v7) { - bytes32[] memory _keyTuple = new bytes32[](7); - _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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); - - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 6, getFieldLayout()); - return Enum2(uint8(Bytes.slice1(_blob, 0))); - } - - /** Get v7 (using the specified store) */ - function getV7( - IStore _store, - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7 - ) internal view returns (Enum2 v7) { - bytes32[] memory _keyTuple = new bytes32[](7); - _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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); - - bytes memory _blob = _store.getField(_tableId, _keyTuple, 6, getFieldLayout()); - return Enum2(uint8(Bytes.slice1(_blob, 0))); - } - - /** Set v7 */ - function setV7(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum1 k6, Enum2 k7, Enum2 v7) internal { - bytes32[] memory _keyTuple = new bytes32[](7); - _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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); - - StoreSwitch.setField(_tableId, _keyTuple, 6, abi.encodePacked(uint8(v7)), getFieldLayout()); - } - - /** Set v7 (using the specified store) */ - function setV7( - IStore _store, - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7, - Enum2 v7 - ) internal { - bytes32[] memory _keyTuple = new bytes32[](7); - _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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); - - _store.setField(_tableId, _keyTuple, 6, abi.encodePacked(uint8(v7)), getFieldLayout()); - } - /** Get the full data */ function get( uint256 k1, @@ -720,17 +491,15 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7 + Enum2 k6 ) internal view returns (StaticsData memory _table) { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); return decode(_blob); @@ -744,17 +513,15 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7 + Enum2 k6 ) internal view returns (StaticsData memory _table) { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); return decode(_blob); @@ -767,28 +534,28 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7, + Enum2 k6, uint256 v1, int32 v2, bytes16 v3, address v4, bool v5, - Enum1 v6, - Enum2 v7 + Enum1 v6 ) internal { - bytes memory _data = encode(v1, v2, v3, v4, v5, v6, v7); + bytes memory _staticData = encodeStatic(v1, v2, v3, v4, v5, v6); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ @@ -799,42 +566,33 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7, + Enum2 k6, uint256 v1, int32 v2, bytes16 v3, address v4, bool v5, - Enum1 v6, - Enum2 v7 + Enum1 v6 ) internal { - bytes memory _data = encode(v1, v2, v3, v4, v5, v6, v7); + bytes memory _staticData = encodeStatic(v1, v2, v3, v4, v5, v6); - bytes32[] memory _keyTuple = new bytes32[](7); + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using the data struct */ - function set( - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7, - StaticsData memory _table - ) internal { - set(k1, k2, k3, k4, k5, k6, k7, _table.v1, _table.v2, _table.v3, _table.v4, _table.v5, _table.v6, _table.v7); + function set(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, StaticsData memory _table) internal { + set(k1, k2, k3, k4, k5, k6, _table.v1, _table.v2, _table.v3, _table.v4, _table.v5, _table.v6); } /** Set the full data using the data struct (using the specified store) */ @@ -845,27 +603,10 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7, + Enum2 k6, StaticsData memory _table ) internal { - set( - _store, - k1, - k2, - k3, - k4, - k5, - k6, - k7, - _table.v1, - _table.v2, - _table.v3, - _table.v4, - _table.v5, - _table.v6, - _table.v7 - ); + set(_store, k1, k2, k3, k4, k5, k6, _table.v1, _table.v2, _table.v3, _table.v4, _table.v5, _table.v6); } /** Decode the tightly packed blob using this table's field layout */ @@ -881,8 +622,18 @@ library Statics { _table.v5 = (_toBool(uint8(Bytes.slice1(_blob, 72)))); _table.v6 = Enum1(uint8(Bytes.slice1(_blob, 73))); + } - _table.v7 = Enum2(uint8(Bytes.slice1(_blob, 74))); + /** Tightly pack static data using this table's schema */ + function encodeStatic( + uint256 v1, + int32 v2, + bytes16 v3, + address v4, + bool v5, + Enum1 v6 + ) internal pure returns (bytes memory) { + return abi.encodePacked(v1, v2, v3, v4, v5, v6); } /** Tightly pack full data using this table's field layout */ @@ -892,10 +643,14 @@ library Statics { bytes16 v3, address v4, bool v5, - Enum1 v6, - Enum2 v7 + Enum1 v6 ) internal pure returns (bytes memory) { - return abi.encodePacked(v1, v2, v3, v4, v5, v6, v7); + bytes memory _staticData = encodeStatic(v1, v2, v3, v4, v5, v6); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ @@ -905,54 +660,41 @@ library Statics { bytes16 k3, address k4, bool k5, - Enum1 k6, - Enum2 k7 + Enum2 k6 ) internal pure returns (bytes32[] memory) { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); return _keyTuple; } /* Delete all data for given keys */ - function deleteRecord(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum1 k6, Enum2 k7) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); } /* Delete all data for given keys (using the specified store) */ - function deleteRecord( - IStore _store, - uint256 k1, - int32 k2, - bytes16 k3, - address k4, - bool k5, - Enum1 k6, - Enum2 k7 - ) internal { - bytes32[] memory _keyTuple = new bytes32[](7); + 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))); - _keyTuple[6] = bytes32(uint256(uint8(k7))); _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); } diff --git a/packages/cli/contracts/test/Tablegen.t.sol b/packages/cli/contracts/test/Tablegen.t.sol index 29f6ec8b29..af41a9f635 100644 --- a/packages/cli/contracts/test/Tablegen.t.sol +++ b/packages/cli/contracts/test/Tablegen.t.sol @@ -17,15 +17,14 @@ contract TablegenTest is Test, StoreMock { bytes16 k3 = hex"02"; address k4 = address(123); bool k5 = true; - Enum1 k6 = Enum1.E3; - Enum2 k7 = Enum2.E1; + Enum2 k6 = Enum2.E1; - Statics.setV1(k1, k2, k3, k4, k5, k6, k7, 4); - assertEq(Statics.getV1(k1, k2, k3, k4, k5, k6, k7), 4); + Statics.setV1(k1, k2, k3, k4, k5, k6, 4); + assertEq(Statics.getV1(k1, k2, k3, k4, k5, k6), 4); - StaticsData memory data = StaticsData(4, -5, hex"06", address(456), false, Enum1.E2, Enum2.E1); - Statics.set(k1, k2, k3, k4, k5, k6, k7, data); - assertEq(abi.encode(Statics.get(k1, k2, k3, k4, k5, k6, k7)), abi.encode(data)); + StaticsData memory data = StaticsData(4, -5, hex"06", address(456), false, Enum1.E2); + Statics.set(k1, k2, k3, k4, k5, k6, data); + assertEq(abi.encode(Statics.get(k1, k2, k3, k4, k5, k6)), abi.encode(data)); } function testDynamicsSetAndGet() public { diff --git a/packages/cli/scripts/generate-test-tables.ts b/packages/cli/scripts/generate-test-tables.ts index d7ca0db655..74ecec0817 100644 --- a/packages/cli/scripts/generate-test-tables.ts +++ b/packages/cli/scripts/generate-test-tables.ts @@ -18,8 +18,7 @@ try { k3: "bytes16", k4: "address", k5: "bool", - k6: "Enum1", - k7: "Enum2", + k6: "Enum2", }, valueSchema: { v1: "uint256", @@ -28,7 +27,6 @@ try { v4: "address", v5: "bool", v6: "Enum1", - v7: "Enum2", }, }, Dynamics1: { diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 95489023b1..d6a59390fa 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -3,5 +3,7 @@ export * from "./createContract"; export * from "./createNonceManager"; export * from "./getBurnerPrivateKey"; export * from "./hexToTableId"; +export * from "./readHex"; +export * from "./spliceHex"; export * from "./tableIdToHex"; export * from "./transportObserver"; diff --git a/packages/protocol-parser/src/readHex.test.ts b/packages/common/src/readHex.test.ts similarity index 100% rename from packages/protocol-parser/src/readHex.test.ts rename to packages/common/src/readHex.test.ts diff --git a/packages/protocol-parser/src/readHex.ts b/packages/common/src/readHex.ts similarity index 100% rename from packages/protocol-parser/src/readHex.ts rename to packages/common/src/readHex.ts diff --git a/packages/common/src/spliceHex.ts b/packages/common/src/spliceHex.ts new file mode 100644 index 0000000000..5ce8c1f6d0 --- /dev/null +++ b/packages/common/src/spliceHex.ts @@ -0,0 +1,6 @@ +import { Hex, concatHex } from "viem"; +import { readHex } from "./readHex"; + +export function spliceHex(data: Hex, start: number, deleteCount = 0, newData: Hex = "0x"): Hex { + return concatHex([readHex(data, 0, start), newData, readHex(data, start + deleteCount)]); +} diff --git a/packages/common/src/type-utils/common.ts b/packages/common/src/type-utils/common.ts index 2e7d66225c..e75f5054dc 100644 --- a/packages/common/src/type-utils/common.ts +++ b/packages/common/src/type-utils/common.ts @@ -19,3 +19,5 @@ export type OrDefaults = { }; export type UnionOmit = T extends any ? Omit : never; +export type UnionKeys = T extends any ? keyof T : never; +export type UnionPick> = T extends any ? Pick> : never; diff --git a/packages/dev-tools/README.md b/packages/dev-tools/README.md index cbab052e80..2b3da880e7 100644 --- a/packages/dev-tools/README.md +++ b/packages/dev-tools/README.md @@ -21,7 +21,7 @@ if (import.meta.env.DEV) { publicClient, walletClient, latestBlock$, - blockStorageOperations$, + storedBlockLogs$, worldAddress, worldAbi, write$, diff --git a/packages/dev-tools/src/DevToolsContext.tsx b/packages/dev-tools/src/DevToolsContext.tsx index 8a9d359e1f..2bc811dec5 100644 --- a/packages/dev-tools/src/DevToolsContext.tsx +++ b/packages/dev-tools/src/DevToolsContext.tsx @@ -1,12 +1,11 @@ import { createContext, ReactNode, useContext, useEffect, useState } from "react"; import { DevToolsOptions } from "./common"; import { ContractWrite } from "@latticexyz/common"; -import { StorageOperation } from "@latticexyz/store-sync"; -import { StoreConfig } from "@latticexyz/store"; +import { StorageAdapterLog } from "@latticexyz/store-sync"; type DevToolsContextValue = DevToolsOptions & { writes: ContractWrite[]; - storageOperations: StorageOperation[]; + storedLogs: StorageAdapterLog[]; }; const DevToolsContext = createContext(null); @@ -28,20 +27,20 @@ export const DevToolsProvider = ({ children, value }: Props) => { return () => sub.unsubscribe(); }, [value.write$]); - const [storageOperations, setStorageOperations] = useState[]>([]); + const [storedLogs, setStoredLogs] = useState([]); useEffect(() => { - const sub = value.blockStorageOperations$.subscribe(({ operations }) => { - setStorageOperations((val) => [...val, ...operations]); + const sub = value.storedBlockLogs$.subscribe(({ logs }) => { + setStoredLogs((val) => [...val, ...logs]); }); return () => sub.unsubscribe(); - }, [value.blockStorageOperations$]); + }, [value.storedBlockLogs$]); return ( {children} diff --git a/packages/dev-tools/src/actions/WriteSummary.tsx b/packages/dev-tools/src/actions/WriteSummary.tsx index fb281fa85d..f7f4dca1a5 100644 --- a/packages/dev-tools/src/actions/WriteSummary.tsx +++ b/packages/dev-tools/src/actions/WriteSummary.tsx @@ -132,6 +132,7 @@ export function WriteSummary({ write }: Props) { {events.map(({ eventName, args }, i) => { const table = hexToTableId((args as any).tableId); + // TODO: dedupe this with logs table so we can get both rendering the same return (
diff --git a/packages/dev-tools/src/common.ts b/packages/dev-tools/src/common.ts index 8ecbcac88c..42475fbab3 100644 --- a/packages/dev-tools/src/common.ts +++ b/packages/dev-tools/src/common.ts @@ -1,7 +1,7 @@ import { Observable } from "rxjs"; import { Abi, Block, Chain, PublicClient, Transport, WalletClient } from "viem"; import { StoreConfig } from "@latticexyz/store"; -import { BlockStorageOperations } from "@latticexyz/store-sync"; +import { StorageAdapterBlock } from "@latticexyz/store-sync"; import { ContractWrite } from "@latticexyz/common"; import { World as RecsWorld } from "@latticexyz/recs"; @@ -10,7 +10,7 @@ export type DevToolsOptions = { publicClient: PublicClient; walletClient: WalletClient; latestBlock$: Observable; - blockStorageOperations$: Observable>; + storedBlockLogs$: Observable; worldAddress: string | null; worldAbi: Abi; write$: Observable; diff --git a/packages/dev-tools/src/events/EventIcon.tsx b/packages/dev-tools/src/events/EventIcon.tsx index 8b6aa682e3..8b40c01690 100644 --- a/packages/dev-tools/src/events/EventIcon.tsx +++ b/packages/dev-tools/src/events/EventIcon.tsx @@ -1,22 +1,22 @@ import { assertExhaustive } from "@latticexyz/common/utils"; -import { StoreConfig } from "@latticexyz/store"; -import { StorageOperation } from "@latticexyz/store-sync"; +import { StorageAdapterLog } from "@latticexyz/store-sync"; type Props = { - type: StorageOperation["type"]; + type: StorageAdapterLog["eventName"]; }; export function EventIcon({ type }: Props) { switch (type) { - case "SetRecord": + case "StoreSetRecord": return =; - case "SetField": + case "StoreSpliceStaticData": + case "StoreSpliceDynamicData": return +; - case "DeleteRecord": + case "StoreDeleteRecord": return -; - // case "EphemeralRecord": - // return ~; + case "StoreEphemeralRecord": + return ~; default: - return assertExhaustive(type, `Unexpected storage operation type: ${type}`); + return assertExhaustive(type, `Unexpected event type: ${type}`); } } diff --git a/packages/dev-tools/src/events/EventsPage.tsx b/packages/dev-tools/src/events/EventsPage.tsx index 59e3f21888..e07a463810 100644 --- a/packages/dev-tools/src/events/EventsPage.tsx +++ b/packages/dev-tools/src/events/EventsPage.tsx @@ -1,9 +1,9 @@ import { useRef, useEffect } from "react"; import { useDevToolsContext } from "../DevToolsContext"; -import { StorageOperationsTable } from "./StorageOperationsTable"; +import { LogsTable } from "./LogsTable"; export function EventsPage() { - const { storageOperations } = useDevToolsContext(); + const { storedLogs } = useDevToolsContext(); const containerRef = useRef(null); const hoveredRef = useRef(false); const scrollBehaviorRef = useRef("auto"); @@ -13,7 +13,7 @@ export function EventsPage() { containerRef.current?.scrollIntoView({ behavior: scrollBehaviorRef.current, block: "end" }); } scrollBehaviorRef.current = "smooth"; - }, [storageOperations]); + }, [storedLogs]); return (
- +
); } diff --git a/packages/dev-tools/src/events/LogsTable.tsx b/packages/dev-tools/src/events/LogsTable.tsx new file mode 100644 index 0000000000..ac4779fb2b --- /dev/null +++ b/packages/dev-tools/src/events/LogsTable.tsx @@ -0,0 +1,72 @@ +import { StorageAdapterLog } from "@latticexyz/store-sync"; +import { EventIcon } from "./EventIcon"; +import { hexToTableId } from "@latticexyz/common"; + +// TODO: use react-table or similar for better perf with lots of logs + +type Props = { + logs: StorageAdapterLog[]; +}; + +export function LogsTable({ logs }: Props) { + return ( + + + + + + + + + + + + {logs.map((log) => { + const { namespace, name } = hexToTableId(log.args.tableId); + return ( + + + + + + + + ); + })} + +
blocktablekeyvalue
+ {log.blockNumber?.toString()} + + {namespace}:{name} + {log.args.keyTuple.join(",")} + + + {/* TODO: decode these values if we can */} + {log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord" + ? JSON.stringify({ + staticData: log.args.staticData, + encodedLengths: log.args.encodedLengths, + dynamicData: log.args.dynamicData, + }) + : null} + {log.eventName === "StoreSpliceStaticData" + ? JSON.stringify({ start: log.args.start, deleteCount: log.args.deleteCount, data: log.args.data }) + : null} + {log.eventName === "StoreSpliceDynamicData" + ? JSON.stringify({ + start: log.args.start, + deleteCount: log.args.deleteCount, + data: log.args.data, + encodedLengths: log.args.encodedLengths, + }) + : null} +
+ ); +} diff --git a/packages/dev-tools/src/events/StorageOperationsTable.tsx b/packages/dev-tools/src/events/StorageOperationsTable.tsx deleted file mode 100644 index bcf63d8876..0000000000 --- a/packages/dev-tools/src/events/StorageOperationsTable.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { StorageOperation } from "@latticexyz/store-sync"; -import { serialize } from "../serialize"; -import { EventIcon } from "./EventIcon"; -import { StoreConfig } from "@latticexyz/store"; - -// TODO: use react-table or similar for better perf with lots of logs - -type Props = { - operations: StorageOperation[]; -}; - -export function StorageOperationsTable({ operations }: Props) { - return ( - - - - - - - - - - - - {operations.map((operation) => ( - - - - - - - - ))} - -
blocktablekeyvalue
- {operation.log?.blockNumber.toString()} - - {operation.namespace}:{operation.name} - {serialize(operation.key)} - - - {operation.type === "SetRecord" ? serialize(operation.value) : null} - {operation.type === "SetField" ? serialize({ [operation.fieldName]: operation.fieldValue }) : null} -
- ); -} diff --git a/packages/dev-tools/src/summary/EventsSummary.tsx b/packages/dev-tools/src/summary/EventsSummary.tsx index 34e7bcebfb..fbc2ad87cb 100644 --- a/packages/dev-tools/src/summary/EventsSummary.tsx +++ b/packages/dev-tools/src/summary/EventsSummary.tsx @@ -1,12 +1,12 @@ import { NavButton } from "../NavButton"; import { useDevToolsContext } from "../DevToolsContext"; -import { StorageOperationsTable } from "../events/StorageOperationsTable"; +import { LogsTable } from "../events/LogsTable"; export function EventsSummary() { - const { storageOperations } = useDevToolsContext(); + const { storedLogs } = useDevToolsContext(); return ( <> - + See more diff --git a/packages/protocol-parser/src/common.ts b/packages/protocol-parser/src/common.ts index cf205abafd..377e6e9267 100644 --- a/packages/protocol-parser/src/common.ts +++ b/packages/protocol-parser/src/common.ts @@ -1,4 +1,5 @@ import { DynamicAbiType, SchemaAbiType, SchemaAbiTypeToPrimitiveType, StaticAbiType } from "@latticexyz/schema-type"; +import { Hex } from "viem"; /** @deprecated use `KeySchema` or `ValueSchema` instead */ export type Schema = { @@ -29,3 +30,9 @@ export type TableRecord; value: SchemaToPrimitives; }; + +export type ValueArgs = { + staticData: Hex; + encodedLengths: Hex; + dynamicData: Hex; +}; diff --git a/packages/protocol-parser/src/decodeRecord.ts b/packages/protocol-parser/src/decodeRecord.ts index c48dc0bd24..411d93327c 100644 --- a/packages/protocol-parser/src/decodeRecord.ts +++ b/packages/protocol-parser/src/decodeRecord.ts @@ -10,7 +10,7 @@ import { decodeDynamicField } from "./decodeDynamicField"; import { decodeStaticField } from "./decodeStaticField"; import { hexToPackedCounter } from "./hexToPackedCounter"; import { staticDataLength } from "./staticDataLength"; -import { readHex } from "./readHex"; +import { readHex } from "@latticexyz/common"; /** @deprecated use `decodeValue` instead */ export function decodeRecord(valueSchema: Schema, data: Hex): readonly (StaticPrimitiveType | DynamicPrimitiveType)[] { diff --git a/packages/protocol-parser/src/decodeValueArgs.ts b/packages/protocol-parser/src/decodeValueArgs.ts new file mode 100644 index 0000000000..d9f5e5161f --- /dev/null +++ b/packages/protocol-parser/src/decodeValueArgs.ts @@ -0,0 +1,20 @@ +import { concatHex } from "viem"; +import { isStaticAbiType } from "@latticexyz/schema-type"; +import { SchemaToPrimitives, ValueArgs, ValueSchema } from "./common"; +import { decodeValue } from "./decodeValue"; +import { staticDataLength } from "./staticDataLength"; +import { readHex } from "@latticexyz/common"; + +export function decodeValueArgs( + valueSchema: TSchema, + { staticData, encodedLengths, dynamicData }: ValueArgs +): SchemaToPrimitives { + return decodeValue( + valueSchema, + concatHex([ + readHex(staticData, 0, staticDataLength(Object.values(valueSchema).filter(isStaticAbiType))), + encodedLengths, + dynamicData, + ]) + ); +} diff --git a/packages/protocol-parser/src/encodeLengths.test.ts b/packages/protocol-parser/src/encodeLengths.test.ts new file mode 100644 index 0000000000..c55204ddc6 --- /dev/null +++ b/packages/protocol-parser/src/encodeLengths.test.ts @@ -0,0 +1,10 @@ +import { describe, expect, it } from "vitest"; +import { encodeLengths } from "./encodeLengths"; + +describe("encodeLengths", () => { + it("can encode bool key tuple", () => { + expect(encodeLengths(["0x1234", "0x12345678"])).toMatchInlineSnapshot( + '"0x0000000000000000000000000000000000000004000000000200000000000006"' + ); + }); +}); diff --git a/packages/protocol-parser/src/encodeLengths.ts b/packages/protocol-parser/src/encodeLengths.ts new file mode 100644 index 0000000000..5a3bbf0827 --- /dev/null +++ b/packages/protocol-parser/src/encodeLengths.ts @@ -0,0 +1,12 @@ +import { Hex, concatHex, padHex, size } from "viem"; +import { encodeField } from "./encodeField"; + +export function encodeLengths(values: Hex[]): Hex { + const byteLengths = values.map(size).reverse(); + const totalByteLength = byteLengths.reduce((total, length) => total + BigInt(length), 0n); + + return padHex( + concatHex([...byteLengths.map((length) => encodeField("uint40", length)), encodeField("uint56", totalByteLength)]), + { size: 32, dir: "left" } + ); +} diff --git a/packages/protocol-parser/src/encodeValue.ts b/packages/protocol-parser/src/encodeValue.ts index f953ccee21..df85964b65 100644 --- a/packages/protocol-parser/src/encodeValue.ts +++ b/packages/protocol-parser/src/encodeValue.ts @@ -1,18 +1,11 @@ -import { isStaticAbiType, isDynamicAbiType } from "@latticexyz/schema-type"; -import { Hex } from "viem"; +import { Hex, concatHex } from "viem"; import { SchemaToPrimitives, ValueSchema } from "./common"; -import { encodeRecord } from "./encodeRecord"; +import { encodeValueArgs } from "./encodeValueArgs"; export function encodeValue( valueSchema: TSchema, value: SchemaToPrimitives ): Hex { - const staticFields = Object.values(valueSchema).filter(isStaticAbiType); - const dynamicFields = Object.values(valueSchema).filter(isDynamicAbiType); - - // TODO: refactor and move all encodeRecord logic into this method so we can delete encodeRecord - - // This currently assumes fields/values are ordered by static, dynamic - // TODO: make sure we preserve ordering based on value schema definition - return encodeRecord({ staticFields, dynamicFields }, Object.values(value)); + const { staticData, encodedLengths, dynamicData } = encodeValueArgs(valueSchema, value); + return concatHex([staticData, encodedLengths, dynamicData]); } diff --git a/packages/protocol-parser/src/encodeValueArgs.ts b/packages/protocol-parser/src/encodeValueArgs.ts new file mode 100644 index 0000000000..0f58a01b8a --- /dev/null +++ b/packages/protocol-parser/src/encodeValueArgs.ts @@ -0,0 +1,27 @@ +import { StaticPrimitiveType, DynamicPrimitiveType, isStaticAbiType, isDynamicAbiType } from "@latticexyz/schema-type"; +import { concatHex } from "viem"; +import { encodeField } from "./encodeField"; +import { SchemaToPrimitives, ValueArgs, ValueSchema } from "./common"; +import { encodeLengths } from "./encodeLengths"; + +export function encodeValueArgs( + valueSchema: TSchema, + value: SchemaToPrimitives +): ValueArgs { + const staticFields = Object.values(valueSchema).filter(isStaticAbiType); + const dynamicFields = Object.values(valueSchema).filter(isDynamicAbiType); + + const values = Object.values(value); + const staticValues = values.slice(0, staticFields.length) as readonly StaticPrimitiveType[]; + const dynamicValues = values.slice(staticFields.length) as readonly DynamicPrimitiveType[]; + + const encodedStaticValues = staticValues.map((value, i) => encodeField(staticFields[i], value)); + const encodedDynamicValues = dynamicValues.map((value, i) => encodeField(dynamicFields[i], value)); + const encodedLengths = encodeLengths(encodedDynamicValues); + + return { + staticData: concatHex(encodedStaticValues), + encodedLengths, + dynamicData: concatHex(encodedDynamicValues), + }; +} diff --git a/packages/protocol-parser/src/hexToPackedCounter.ts b/packages/protocol-parser/src/hexToPackedCounter.ts index c8816d15f7..d29121b7ff 100644 --- a/packages/protocol-parser/src/hexToPackedCounter.ts +++ b/packages/protocol-parser/src/hexToPackedCounter.ts @@ -2,7 +2,7 @@ import { Hex } from "viem"; import { decodeStaticField } from "./decodeStaticField"; import { decodeDynamicField } from "./decodeDynamicField"; import { InvalidHexLengthForPackedCounterError, PackedCounterLengthMismatchError } from "./errors"; -import { readHex } from "./readHex"; +import { readHex } from "@latticexyz/common"; // Keep this logic in sync with PackedCounter.sol diff --git a/packages/protocol-parser/src/index.ts b/packages/protocol-parser/src/index.ts index 805719cc39..9874481e71 100644 --- a/packages/protocol-parser/src/index.ts +++ b/packages/protocol-parser/src/index.ts @@ -7,18 +7,19 @@ export * from "./decodeKeyTuple"; export * from "./decodeRecord"; export * from "./decodeStaticField"; export * from "./decodeValue"; +export * from "./decodeValueArgs"; export * from "./encodeField"; export * from "./encodeKey"; export * from "./encodeKeyTuple"; export * from "./encodeRecord"; export * from "./encodeValue"; +export * from "./encodeValueArgs"; export * from "./errors"; export * from "./fieldLayoutToHex"; export * from "./hexToPackedCounter"; export * from "./hexToSchema"; export * from "./hexToTableSchema"; export * from "./keySchemaToHex"; -export * from "./readHex"; export * from "./schemaIndexToAbiType"; export * from "./schemaToHex"; export * from "./staticDataLength"; diff --git a/packages/store-indexer/bin/postgres-indexer.ts b/packages/store-indexer/bin/postgres-indexer.ts index 9a7ea96d1e..8370b10338 100644 --- a/packages/store-indexer/bin/postgres-indexer.ts +++ b/packages/store-indexer/bin/postgres-indexer.ts @@ -67,14 +67,14 @@ const database = drizzle(postgres(env.DATABASE_URL), { let startBlock = env.START_BLOCK; -const storageAdapter = await postgresStorage({ database, publicClient }); +const { storageAdapter, internalTables } = await postgresStorage({ database, publicClient }); // Resume from latest block stored in DB. This will throw if the DB doesn't exist yet, so we wrap in a try/catch and ignore the error. try { const currentChainStates = await database .select() - .from(storageAdapter.internalTables.chain) - .where(eq(storageAdapter.internalTables.chain.chainId, chainId)) + .from(internalTables.chain) + .where(eq(internalTables.chain.chainId, chainId)) .execute(); // TODO: replace this type workaround with `noUncheckedIndexedAccess: true` when we can fix all the issues related (https://github.com/latticexyz/mud/issues/1212) const currentChainState: (typeof currentChainStates)[number] | undefined = currentChainStates[0]; @@ -98,14 +98,14 @@ try { // ignore errors, this is optional } -const { latestBlockNumber$, blockStorageOperations$ } = await createStoreSync({ +const { latestBlockNumber$, storedBlockLogs$ } = await createStoreSync({ storageAdapter, publicClient, startBlock, maxBlockRange: env.MAX_BLOCK_RANGE, }); -combineLatest([latestBlockNumber$, blockStorageOperations$]) +combineLatest([latestBlockNumber$, storedBlockLogs$]) .pipe( filter( ([latestBlockNumber, { blockNumber: lastBlockNumberProcessed }]) => latestBlockNumber === lastBlockNumberProcessed diff --git a/packages/store-indexer/bin/sqlite-indexer.ts b/packages/store-indexer/bin/sqlite-indexer.ts index 1433768aef..7cdaa50c87 100644 --- a/packages/store-indexer/bin/sqlite-indexer.ts +++ b/packages/store-indexer/bin/sqlite-indexer.ts @@ -90,14 +90,14 @@ try { // ignore errors, this is optional } -const { latestBlockNumber$, blockStorageOperations$ } = await syncToSqlite({ +const { latestBlockNumber$, storedBlockLogs$ } = await syncToSqlite({ database, publicClient, startBlock, maxBlockRange: env.MAX_BLOCK_RANGE, }); -combineLatest([latestBlockNumber$, blockStorageOperations$]) +combineLatest([latestBlockNumber$, storedBlockLogs$]) .pipe( filter( ([latestBlockNumber, { blockNumber: lastBlockNumberProcessed }]) => latestBlockNumber === lastBlockNumberProcessed diff --git a/packages/store-indexer/package.json b/packages/store-indexer/package.json index c17410cf6b..175b8b7090 100644 --- a/packages/store-indexer/package.json +++ b/packages/store-indexer/package.json @@ -40,9 +40,9 @@ "@trpc/client": "10.34.0", "@trpc/server": "10.34.0", "@wagmi/chains": "^0.2.22", - "better-sqlite3": "^8.4.0", + "better-sqlite3": "^8.6.0", "debug": "^4.3.4", - "drizzle-orm": "^0.27.0", + "drizzle-orm": "^0.28.5", "fastify": "^4.21.0", "postgres": "^3.3.5", "rxjs": "7.5.5", diff --git a/packages/store-indexer/src/sqlite/createQueryAdapter.ts b/packages/store-indexer/src/sqlite/createQueryAdapter.ts index eae41e90c4..07d4e86949 100644 --- a/packages/store-indexer/src/sqlite/createQueryAdapter.ts +++ b/packages/store-indexer/src/sqlite/createQueryAdapter.ts @@ -1,6 +1,6 @@ import { eq } from "drizzle-orm"; import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; -import { createSqliteTable, chainState, getTables } from "@latticexyz/store-sync/sqlite"; +import { buildTable, chainState, getTables } from "@latticexyz/store-sync/sqlite"; import { QueryAdapter } from "@latticexyz/store-sync/trpc-indexer"; import { debug } from "../debug"; @@ -16,7 +16,7 @@ export async function createQueryAdapter(database: BaseSQLiteDatabase<"sync", an const tables = getTables(database).filter((table) => table.address === address); const tablesWithRecords = tables.map((table) => { - const sqliteTable = createSqliteTable(table); + const sqliteTable = buildTable(table); const records = database.select().from(sqliteTable).where(eq(sqliteTable.__isDeleted, false)).all(); return { ...table, diff --git a/packages/store-sync/package.json b/packages/store-sync/package.json index 74ac0cd678..ca4ce4abbc 100644 --- a/packages/store-sync/package.json +++ b/packages/store-sync/package.json @@ -56,8 +56,8 @@ "@trpc/client": "10.34.0", "@trpc/server": "10.34.0", "debug": "^4.3.4", - "drizzle-orm": "^0.27.0", - "kysely": "^0.26.1", + "drizzle-orm": "^0.28.5", + "kysely": "^0.26.3", "postgres": "^3.3.5", "rxjs": "7.5.5", "sql.js": "^1.8.0", diff --git a/packages/store-sync/src/blockLogsToStorage.test.ts b/packages/store-sync/src/blockLogsToStorage.test.ts deleted file mode 100644 index e3f134db48..0000000000 --- a/packages/store-sync/src/blockLogsToStorage.test.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; -import { blockLogsToStorage } from "./blockLogsToStorage"; -import storeConfig from "@latticexyz/store/mud.config"; -import { isDefined } from "@latticexyz/common/utils"; -import { tableIdToHex } from "@latticexyz/common"; -import { StorageAdapter } from "./common"; - -const mockedCallbacks = { - registerTables: vi.fn, ReturnType>(), - getTables: vi.fn, ReturnType>(), - storeOperations: vi.fn< - Parameters, - ReturnType - >(), -}; - -const mockedDecode = blockLogsToStorage( - mockedCallbacks as any as StorageAdapter -); - -describe("blockLogsToStorage", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - it("call setField with data properly decoded", async () => { - mockedCallbacks.getTables.mockImplementation(async ({ tables }) => { - return tables - .map((table) => { - if (table.namespace === "" && table.name === "Inventory") { - return { - ...table, - tableId: tableIdToHex("", "Inventory"), - keySchema: { - owner: "address", - item: "uint32", - itemVariant: "uint32", - } as const, - valueSchema: { - amount: "uint32", - } as const, - }; - } - }) - .filter(isDefined); - }); - - const operations = await mockedDecode({ - blockNumber: 5448n, - logs: [ - { - address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", - topics: ["0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32"], - data: "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e76656e746f72790000000000000000000000000000000000000000000000000000000000000000000000000002800004010004000000000000000000000000000000000000000000000000000000001c030061030300000000000000000000000000000000000000000000000000000401000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000001600000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000056f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046974656d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6974656d56617269616e740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006616d6f756e740000000000000000000000000000000000000000000000000000", - blockHash: "0x50b3e15ef79abc7c72126ca5ecbd0cf0773c48ade0528e1e3debaf9bbe3643da", - blockNumber: 5448n, - transactionHash: "0xd66a9f982ddb8da9ca15a72c5713c3390fb3a6c2f7fe81a8c9026d0ba8130189", - transactionIndex: 16, - logIndex: 53, - removed: false, - args: { - tableId: "0x6d756473746f726500000000000000005461626c657300000000000000000000", - keyTuple: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"], - data: "0x0004010004000000000000000000000000000000000000000000000000000000001c030061030300000000000000000000000000000000000000000000000000000401000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000001600000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000056f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046974656d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6974656d56617269616e740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006616d6f756e740000000000000000000000000000000000000000000000000000", - }, - eventName: "StoreSetRecord", - }, - { - address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", - topics: ["0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46"], - data: "0x00000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000", - blockHash: "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", - blockNumber: 5448n, - transactionHash: "0xa6986924609542dc4c2d81c53799d8eab47109ef34ee1e422de595e19ee9bfa4", - transactionIndex: 88, - logIndex: 88, - removed: false, - args: { - tableId: "0x00000000000000000000000000000000496e76656e746f727900000000000000", - keyTuple: [ - "0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - schemaIndex: 0, - data: "0x00000008", - }, - eventName: "StoreSetField", - }, - ], - }); - - expect(mockedCallbacks.storeOperations).toMatchInlineSnapshot(` - [MockFunction spy] { - "calls": [ - [ - { - "blockNumber": 5448n, - "operations": [ - { - "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", - "fieldName": "amount", - "fieldValue": 8, - "key": { - "item": 1, - "itemVariant": 1, - "owner": "0x796eb990A3F9C431C69149c7a168b91596D87F60", - }, - "log": { - "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", - "args": { - "data": "0x00000008", - "keyTuple": [ - "0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - "schemaIndex": 0, - "tableId": "0x00000000000000000000000000000000496e76656e746f727900000000000000", - }, - "blockHash": "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", - "blockNumber": 5448n, - "data": "0x00000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000", - "eventName": "StoreSetField", - "logIndex": 88, - "removed": false, - "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46", - ], - "transactionHash": "0xa6986924609542dc4c2d81c53799d8eab47109ef34ee1e422de595e19ee9bfa4", - "transactionIndex": 88, - }, - "name": "Inventory", - "namespace": "", - "type": "SetField", - }, - ], - }, - ], - ], - "results": [ - { - "type": "return", - "value": undefined, - }, - ], - } - `); - - expect(operations).toMatchInlineSnapshot(` - { - "blockNumber": 5448n, - "operations": [ - { - "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", - "fieldName": "amount", - "fieldValue": 8, - "key": { - "item": 1, - "itemVariant": 1, - "owner": "0x796eb990A3F9C431C69149c7a168b91596D87F60", - }, - "log": { - "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", - "args": { - "data": "0x00000008", - "keyTuple": [ - "0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - "schemaIndex": 0, - "tableId": "0x00000000000000000000000000000000496e76656e746f727900000000000000", - }, - "blockHash": "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", - "blockNumber": 5448n, - "data": "0x00000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000", - "eventName": "StoreSetField", - "logIndex": 88, - "removed": false, - "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46", - ], - "transactionHash": "0xa6986924609542dc4c2d81c53799d8eab47109ef34ee1e422de595e19ee9bfa4", - "transactionIndex": 88, - }, - "name": "Inventory", - "namespace": "", - "type": "SetField", - }, - ], - } - `); - }); -}); diff --git a/packages/store-sync/src/blockLogsToStorage.ts b/packages/store-sync/src/blockLogsToStorage.ts deleted file mode 100644 index e2d025f3e3..0000000000 --- a/packages/store-sync/src/blockLogsToStorage.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { decodeField, decodeKeyTuple, decodeRecord, abiTypesToSchema, hexToSchema } from "@latticexyz/protocol-parser"; -import { - StoreConfig, - ConfigToKeyPrimitives as Key, - ConfigToValuePrimitives as Value, - ConfigToValuePrimitives, -} from "@latticexyz/store"; -import { decodeAbiParameters, getAddress, parseAbiParameters } from "viem"; -import { debug } from "./debug"; -import { isDefined } from "@latticexyz/common/utils"; -import { BlockLogs, StorageAdapter, StorageOperation, Table } from "./common"; -import { hexToTableId, tableIdToHex } from "@latticexyz/common"; -import storeConfig from "@latticexyz/store/mud.config"; - -// 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) -const schemasTable = storeConfig.tables.Tables; -const schemasTableId = tableIdToHex(storeConfig.namespace, schemasTable.name); - -export type BlockStorageOperations = { - blockNumber: BlockLogs["blockNumber"]; - operations: StorageOperation[]; -}; - -export type BlockLogsToStorageResult = ( - block: BlockLogs -) => Promise>; - -export function blockLogsToStorage({ - registerTables, - getTables, - storeOperations, -}: StorageAdapter): BlockLogsToStorageResult { - return async (block) => { - // Find table schema registration events - const newTables = block.logs - .map((log) => { - try { - if (log.eventName !== "StoreSetRecord") return; - if (log.args.tableId !== schemasTableId) return; - - // TODO: refactor encode/decode to use Record schemas - // TODO: refactor to decode key with protocol-parser utils - - const [tableId, ...otherKeys] = log.args.keyTuple; - if (otherKeys.length) { - console.warn("registerSchema event is expected to have only one key in key tuple, but got multiple", log); - } - - const table = hexToTableId(tableId); - - const valueTuple = decodeRecord(abiTypesToSchema(Object.values(schemasTable.valueSchema)), log.args.data); - const value = Object.fromEntries( - Object.keys(schemasTable.valueSchema).map((name, i) => [name, valueTuple[i]]) - ) as ConfigToValuePrimitives; - - const keySchema = hexToSchema(value.keySchema); - const valueSchema = hexToSchema(value.valueSchema); - const keyNames = decodeAbiParameters(parseAbiParameters("string[]"), value.abiEncodedKeyNames)[0]; - const fieldNames = decodeAbiParameters(parseAbiParameters("string[]"), value.abiEncodedFieldNames)[0]; - - const valueAbiTypes = [...valueSchema.staticFields, ...valueSchema.dynamicFields]; - - return { - address: log.address, - tableId, - namespace: table.namespace, - name: table.name, - keySchema: Object.fromEntries(keySchema.staticFields.map((abiType, i) => [keyNames[i], abiType])), - valueSchema: Object.fromEntries(valueAbiTypes.map((abiType, i) => [fieldNames[i], abiType])), - }; - } catch (error: unknown) { - console.error("Failed to get table from log", log, error); - } - }) - .filter(isDefined); - - // Then register tables before we start storing data in them - if (newTables.length > 0) { - await registerTables({ - blockNumber: block.blockNumber, - tables: newTables, - }); - } - - const tablesToFetch = Array.from( - new Set( - block.logs.map((log) => - JSON.stringify({ - address: getAddress(log.address), - tableId: log.args.tableId, - ...hexToTableId(log.args.tableId), - }) - ) - ) - ).map((json) => JSON.parse(json)); - - const tables = Object.fromEntries( - ( - await getTables({ - blockNumber: block.blockNumber, - tables: tablesToFetch, - }) - ).map((table) => [`${getAddress(table.address)}:${table.tableId}`, table]) - ) as Record; - - const operations = block.logs - .map((log): StorageOperation | undefined => { - try { - const table = tables[`${getAddress(log.address)}:${log.args.tableId}`]; - if (!table) { - debug("no table found for event, skipping", hexToTableId(log.args.tableId), log); - return; - } - - const keyNames = Object.keys(table.keySchema); - const keyValues = decodeKeyTuple( - { staticFields: Object.values(table.keySchema), dynamicFields: [] }, - log.args.keyTuple - ); - const key = Object.fromEntries(keyValues.map((value, i) => [keyNames[i], value])) as Key< - TConfig, - keyof TConfig["tables"] - >; - - const valueAbiTypes = Object.values(table.valueSchema); - const valueSchema = abiTypesToSchema(valueAbiTypes); - const fieldNames = Object.keys(table.valueSchema); - - // TODO: decide if we should split these up into distinct operations so the storage adapter can decide whether to combine or not - if (log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord") { - const valueTuple = decodeRecord(valueSchema, log.args.data); - const value = Object.fromEntries(fieldNames.map((name, i) => [name, valueTuple[i]])) as Value< - TConfig, - keyof TConfig["tables"] - >; - return { - log, - address: getAddress(log.address), - namespace: table.namespace, - name: table.name, - type: "SetRecord", - key, - value, - }; - } - - if (log.eventName === "StoreSetField") { - const fieldName = fieldNames[log.args.schemaIndex] as string & - keyof Value; - const fieldValue = decodeField(valueAbiTypes[log.args.schemaIndex], log.args.data) as Value< - TConfig, - keyof TConfig["tables"] - >[typeof fieldName]; - return { - log, - address: getAddress(log.address), - namespace: table.namespace, - name: table.name, - type: "SetField", - key, - fieldName, - fieldValue, - }; - } - - if (log.eventName === "StoreDeleteRecord") { - return { - log, - address: getAddress(log.address), - namespace: table.namespace, - name: table.name, - type: "DeleteRecord", - key, - }; - } - - debug("unknown store event or log, skipping", log); - return; - } catch (error: unknown) { - console.error("Failed to translate log to storage operation", log, error); - } - }) - .filter(isDefined); - - await storeOperations({ blockNumber: block.blockNumber, operations }); - - return { - blockNumber: block.blockNumber, - operations, - }; - }; -} diff --git a/packages/store-sync/src/common.ts b/packages/store-sync/src/common.ts index d903b05ba1..4927923521 100644 --- a/packages/store-sync/src/common.ts +++ b/packages/store-sync/src/common.ts @@ -1,15 +1,10 @@ import { Address, Block, Hex, Log, PublicClient } from "viem"; -import { GroupLogsByBlockNumberResult } from "@latticexyz/block-logs-stream"; -import { - StoreConfig, - ConfigToKeyPrimitives as Key, - ConfigToValuePrimitives as Value, - StoreEventsAbiItem, - StoreEventsAbi, -} from "@latticexyz/store"; +import { StoreConfig, StoreEventsAbiItem, StoreEventsAbi } from "@latticexyz/store"; +import storeConfig from "@latticexyz/store/mud.config"; import { Observable } from "rxjs"; -import { BlockStorageOperations } from "./blockLogsToStorage"; -import { KeySchema, ValueSchema, TableRecord } from "@latticexyz/protocol-parser"; +import { tableIdToHex } from "@latticexyz/common"; +import { UnionPick } from "@latticexyz/common/type-utils"; +import { KeySchema, TableRecord, ValueSchema } from "@latticexyz/protocol-parser"; export type ChainId = number; export type WorldId = `${ChainId}:${Address}`; @@ -29,52 +24,7 @@ export type Table = { export type TableWithRecords = Table & { records: TableRecord[] }; export type StoreEventsLog = Log; -export type BlockLogs = GroupLogsByBlockNumberResult[number]; - -export type BaseStorageOperation = { - log?: StoreEventsLog; - address: Hex; - namespace: TableNamespace; - name: TableName; -}; - -export type SetRecordOperation = BaseStorageOperation & { - type: "SetRecord"; -} & { - [TTable in keyof TConfig["tables"]]: { - name: TTable & string; - key: Key; - value: Value; - }; - }[keyof TConfig["tables"]]; - -export type SetFieldOperation = BaseStorageOperation & { - type: "SetField"; -} & { - [TTable in keyof TConfig["tables"]]: { - name: TTable & string; - key: Key; - } & { - [TValue in keyof Value]: { - fieldName: TValue & string; - fieldValue: Value[TValue]; - }; - }[keyof Value]; - }[keyof TConfig["tables"]]; - -export type DeleteRecordOperation = BaseStorageOperation & { - type: "DeleteRecord"; -} & { - [TTable in keyof TConfig["tables"]]: { - name: TTable & string; - key: Key; - }; - }[keyof TConfig["tables"]]; - -export type StorageOperation = - | SetFieldOperation - | SetRecordOperation - | DeleteRecordOperation; +export type BlockLogs = { blockNumber: StoreEventsLog["blockNumber"]; logs: StoreEventsLog[] }; export type SyncOptions = { /** @@ -112,22 +62,19 @@ export type SyncOptions = { }; }; -export type SyncResult = { +export type SyncResult = { latestBlock$: Observable; latestBlockNumber$: Observable; blockLogs$: Observable; - blockStorageOperations$: Observable>; + storedBlockLogs$: Observable; waitForTransaction: (tx: Hex) => Promise; }; -export type StorageAdapter = { - registerTables: (opts: { blockNumber: BlockLogs["blockNumber"]; tables: Table[] }) => Promise; - getTables: (opts: { - blockNumber: BlockLogs["blockNumber"]; - tables: Pick[]; - }) => Promise; - storeOperations: (opts: { - blockNumber: BlockLogs["blockNumber"]; - operations: StorageOperation[]; - }) => Promise; -}; +// TODO: add optional, original log to this? +export type StorageAdapterLog = Partial & UnionPick; +export type StorageAdapterBlock = { blockNumber: BlockLogs["blockNumber"]; logs: StorageAdapterLog[] }; +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 = tableIdToHex(storeConfig.namespace, schemasTable.name); diff --git a/packages/store-sync/src/createStoreSync.ts b/packages/store-sync/src/createStoreSync.ts index 2e0cfc0857..dcd8852df4 100644 --- a/packages/store-sync/src/createStoreSync.ts +++ b/packages/store-sync/src/createStoreSync.ts @@ -1,6 +1,13 @@ -import { ConfigToKeyPrimitives, ConfigToValuePrimitives, StoreConfig, storeEventsAbi } from "@latticexyz/store"; +import { StoreConfig, storeEventsAbi } from "@latticexyz/store"; import { Hex, TransactionReceiptNotFoundError } from "viem"; -import { SetRecordOperation, StorageAdapter, SyncOptions, SyncResult, TableWithRecords } from "./common"; +import { + StorageAdapter, + StorageAdapterBlock, + StorageAdapterLog, + SyncOptions, + SyncResult, + TableWithRecords, +} from "./common"; import { createBlockStream, blockRangeToLogs, groupLogsByBlockNumber } from "@latticexyz/block-logs-stream"; import { filter, @@ -20,16 +27,16 @@ import { scan, identity, } from "rxjs"; -import { BlockStorageOperations, blockLogsToStorage } from "./blockLogsToStorage"; import { debug as parentDebug } from "./debug"; import { createIndexerClient } from "./trpc-indexer"; import { SyncStep } from "./SyncStep"; import { chunk, isDefined } from "@latticexyz/common/utils"; +import { encodeKey, encodeValueArgs } from "@latticexyz/protocol-parser"; const debug = parentDebug.extend("createStoreSync"); type CreateStoreSyncOptions = SyncOptions & { - storageAdapter: StorageAdapter; + storageAdapter: StorageAdapter; onProgress?: (opts: { step: SyncStep; percentage: number; @@ -39,8 +46,6 @@ type CreateStoreSyncOptions = SyncOpt }) => void; }; -type CreateStoreSyncResult = SyncResult; - export async function createStoreSync({ storageAdapter, onProgress, @@ -50,7 +55,7 @@ export async function createStoreSync maxBlockRange, initialState, indexerUrl, -}: CreateStoreSyncOptions): Promise> { +}: CreateStoreSyncOptions): Promise { const initialState$ = defer( async (): Promise< | { @@ -109,7 +114,7 @@ export async function createStoreSync tap((startBlock) => debug("starting sync from block", startBlock)) ); - const initialStorageOperations$ = initialState$.pipe( + const initialLogs$ = initialState$.pipe( filter( (initialState): initialState is { blockNumber: bigint; tables: TableWithRecords[] } => initialState != null && initialState.blockNumber != null && initialState.tables.length > 0 @@ -125,27 +130,28 @@ export async function createStoreSync message: "Hydrating from snapshot", }); - await storageAdapter.registerTables({ blockNumber, tables }); - - const operations: SetRecordOperation[] = tables.flatMap((table) => - table.records.map((record) => ({ - type: "SetRecord", - address: table.address, - namespace: table.namespace, - name: table.name, - key: record.key as ConfigToKeyPrimitives, - value: record.value as ConfigToValuePrimitives, - })) + const logs: StorageAdapterLog[] = tables.flatMap((table) => + table.records.map( + (record): StorageAdapterLog => ({ + eventName: "StoreSetRecord", + address: table.address, + args: { + tableId: table.tableId, + keyTuple: encodeKey(table.keySchema, record.key), + ...encodeValueArgs(table.valueSchema, record.value), + }, + }) + ) ); // Split snapshot operations into chunks so we can update the progress callback (and ultimately render visual progress for the user). // This isn't ideal if we want to e.g. batch load these into a DB in a single DB tx, but we'll take it. // // Split into 50 equal chunks (for better `onProgress` updates) but only if we have 100+ items per chunk - const chunkSize = Math.max(100, Math.floor(operations.length / 50)); - const chunks = Array.from(chunk(operations, chunkSize)); + const chunkSize = Math.max(100, Math.floor(logs.length / 50)); + const chunks = Array.from(chunk(logs, chunkSize)); for (const [i, chunk] of chunks.entries()) { - await storageAdapter.storeOperations({ blockNumber, operations: chunk }); + await storageAdapter({ blockNumber, logs: chunk }); onProgress?.({ step: SyncStep.SNAPSHOT, percentage: (i + chunk.length) / chunks.length, @@ -163,7 +169,7 @@ export async function createStoreSync message: "Hydrated from snapshot", }); - return { blockNumber, operations }; + return { blockNumber, logs }; }), shareReplay(1) ); @@ -196,12 +202,15 @@ export async function createStoreSync ); let lastBlockNumberProcessed: bigint | null = null; - const blockStorageOperations$ = concat( - initialStorageOperations$, + const storedBlockLogs$ = concat( + initialLogs$, blockLogs$.pipe( - concatMap(blockLogsToStorage(storageAdapter)), - tap(({ blockNumber, operations }) => { - debug("stored", operations.length, "operations for block", blockNumber); + concatMap(async (block) => { + await storageAdapter(block); + return block; + }), + tap(({ blockNumber, logs }) => { + debug("stored", logs.length, "logs for block", blockNumber); lastBlockNumberProcessed = blockNumber; if (startBlock != null && endBlock != null) { @@ -232,8 +241,8 @@ export async function createStoreSync // keep 10 blocks worth processed transactions in memory const recentBlocksWindow = 10; // most recent block first, for ease of pulling the first one off the array - const recentBlocks$ = blockStorageOperations$.pipe( - scan( + const recentBlocks$ = storedBlockLogs$.pipe( + scan( (recentBlocks, block) => [block, ...recentBlocks].slice(0, recentBlocksWindow), [] ), @@ -249,7 +258,7 @@ export async function createStoreSync // We could potentially speed this up a tiny bit by racing to see if 1) tx exists in processed block or 2) fetch tx receipt for latest block processed const hasTransaction$ = recentBlocks$.pipe( concatMap(async (blocks) => { - const txs = blocks.flatMap((block) => block.operations.map((op) => op.log?.transactionHash).filter(isDefined)); + const txs = blocks.flatMap((block) => block.logs.map((op) => op.transactionHash).filter(isDefined)); if (txs.includes(tx)) return true; try { @@ -274,7 +283,7 @@ export async function createStoreSync latestBlock$, latestBlockNumber$, blockLogs$, - blockStorageOperations$, + storedBlockLogs$, waitForTransaction, }; } diff --git a/packages/store-sync/src/index.ts b/packages/store-sync/src/index.ts index 01c883d7e2..2e0771488d 100644 --- a/packages/store-sync/src/index.ts +++ b/packages/store-sync/src/index.ts @@ -1,4 +1,3 @@ -export * from "./blockLogsToStorage"; export * from "./common"; export * from "./createStoreSync"; export * from "./SyncStep"; diff --git a/packages/store-sync/src/isTableRegistrationLog.ts b/packages/store-sync/src/isTableRegistrationLog.ts new file mode 100644 index 0000000000..ca937f8030 --- /dev/null +++ b/packages/store-sync/src/isTableRegistrationLog.ts @@ -0,0 +1,7 @@ +import { StorageAdapterLog, schemasTableId } from "./common"; + +export function isTableRegistrationLog( + log: StorageAdapterLog +): log is StorageAdapterLog & { eventName: "StoreSetRecord" } { + return log.eventName === "StoreSetRecord" && log.args.tableId === schemasTableId; +} diff --git a/packages/store-sync/src/logToTable.test.ts b/packages/store-sync/src/logToTable.test.ts new file mode 100644 index 0000000000..53ec2a6a5e --- /dev/null +++ b/packages/store-sync/src/logToTable.test.ts @@ -0,0 +1,39 @@ +import { describe, it, expect } from "vitest"; +import { logToTable } from "./logToTable"; + +describe("logToTable", () => { + it("should convert a table registration log to table object", async () => { + expect( + logToTable({ + address: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", + eventName: "StoreSetRecord", + args: { + tableId: "0x6d756473746f726500000000000000005461626c657300000000000000000000", + keyTuple: ["0x6d756473746f726500000000000000005461626c657300000000000000000000"], + staticData: + "0x0060030220202000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000006003025f5f5fc4c40000000000000000000000000000000000000000000000", + encodedLengths: "0x000000000000000000000000000000000000022000000000a0000000000002c0", // "0x00000000000000000000000000000000000000a00000000220000000000002c0", + dynamicData: + "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000077461626c654964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000b6669656c644c61796f757400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096b6579536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76616c7565536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012616269456e636f6465644b65794e616d657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014616269456e636f6465644669656c644e616d6573000000000000000000000000", + }, + }) + ).toMatchInlineSnapshot(` + { + "address": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", + "keySchema": { + "tableId": "bytes32", + }, + "name": "Tables", + "namespace": "mudstore", + "tableId": "0x6d756473746f726500000000000000005461626c657300000000000000000000", + "valueSchema": { + "abiEncodedFieldNames": "bytes", + "abiEncodedKeyNames": "bytes", + "fieldLayout": "bytes32", + "keySchema": "bytes32", + "valueSchema": "bytes32", + }, + } + `); + }); +}); diff --git a/packages/store-sync/src/logToTable.ts b/packages/store-sync/src/logToTable.ts new file mode 100644 index 0000000000..72f7f01d47 --- /dev/null +++ b/packages/store-sync/src/logToTable.ts @@ -0,0 +1,37 @@ +import { hexToSchema, decodeValue } from "@latticexyz/protocol-parser"; +import { concatHex, decodeAbiParameters, parseAbiParameters } from "viem"; +import { StorageAdapterLog, Table, schemasTable } from "./common"; +import { hexToTableId } from "@latticexyz/common"; + +// TODO: add tableToLog + +export function logToTable(log: StorageAdapterLog & { eventName: "StoreSetRecord" }): Table { + const [tableId, ...otherKeys] = log.args.keyTuple; + if (otherKeys.length) { + console.warn("registerSchema event is expected to have only one key in key tuple, but got multiple", log); + } + + const table = hexToTableId(tableId); + + const value = decodeValue( + schemasTable.valueSchema, + concatHex([log.args.staticData, log.args.encodedLengths, log.args.dynamicData]) + ); + + const keySchema = hexToSchema(value.keySchema); + const valueSchema = hexToSchema(value.valueSchema); + + const keyNames = decodeAbiParameters(parseAbiParameters("string[]"), value.abiEncodedKeyNames)[0]; + const fieldNames = decodeAbiParameters(parseAbiParameters("string[]"), value.abiEncodedFieldNames)[0]; + + const valueAbiTypes = [...valueSchema.staticFields, ...valueSchema.dynamicFields]; + + return { + address: log.address, + tableId, + namespace: table.namespace, + name: table.name, + keySchema: Object.fromEntries(keySchema.staticFields.map((abiType, i) => [keyNames[i], abiType])), + valueSchema: Object.fromEntries(valueAbiTypes.map((abiType, i) => [fieldNames[i], abiType])), + }; +} diff --git a/packages/store-sync/src/postgres/buildColumn.ts b/packages/store-sync/src/postgres/buildColumn.ts index 86ea59c268..d9ffa6db99 100644 --- a/packages/store-sync/src/postgres/buildColumn.ts +++ b/packages/store-sync/src/postgres/buildColumn.ts @@ -1,9 +1,10 @@ -import { AnyPgColumnBuilder, boolean, text } from "drizzle-orm/pg-core"; +import { boolean, text } from "drizzle-orm/pg-core"; import { SchemaAbiType } from "@latticexyz/schema-type"; import { assertExhaustive } from "@latticexyz/common/utils"; import { asAddress, asBigInt, asHex, asJson, asNumber } from "./columnTypes"; -export function buildColumn(name: string, schemaAbiType: SchemaAbiType): AnyPgColumnBuilder { +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export function buildColumn(name: string, schemaAbiType: SchemaAbiType) { switch (schemaAbiType) { case "bool": return boolean(name); diff --git a/packages/store-sync/src/postgres/buildTable.test.ts b/packages/store-sync/src/postgres/buildTable.test.ts index 5d9d192a88..b13b991393 100644 --- a/packages/store-sync/src/postgres/buildTable.test.ts +++ b/packages/store-sync/src/postgres/buildTable.test.ts @@ -13,35 +13,131 @@ describe("buildTable", () => { expect(table).toMatchInlineSnapshot(` PgTable { + "__dynamicData": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__dynamicData", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___dynamicData_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__dynamicData", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___dynamicData_unique", + "uniqueType": undefined, + }, + "__encodedLengths": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__encodedLengths", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___encodedLengths_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__encodedLengths", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___encodedLengths_unique", + "uniqueType": undefined, + }, "__isDeleted": PgBoolean { + "columnType": "PgBoolean", "config": { + "columnType": "PgBoolean", + "dataType": "boolean", "default": undefined, + "hasDefault": false, + "isUnique": false, "name": "__isDeleted", "notNull": true, "primaryKey": false, + "uniqueName": "users___isDeleted_unique", + "uniqueType": undefined, }, + "dataType": "boolean", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "name": "__isDeleted", "notNull": true, "primary": false, "table": [Circular], + "uniqueName": "users___isDeleted_unique", + "uniqueType": undefined, }, "__key": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "__key", "notNull": true, "primaryKey": true, + "uniqueName": "users___key_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "__key", @@ -49,22 +145,35 @@ describe("buildTable", () => { "primary": true, "sqlName": "bytea", "table": [Circular], + "uniqueName": "users___key_unique", + "uniqueType": undefined, }, "__lastUpdatedBlockNumber": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "__lastUpdatedBlockNumber", "notNull": true, "primaryKey": false, + "uniqueName": "users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "__lastUpdatedBlockNumber", @@ -72,22 +181,71 @@ describe("buildTable", () => { "primary": false, "sqlName": "numeric", "table": [Circular], + "uniqueName": "users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "__staticData": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__staticData", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___staticData_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__staticData", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___staticData_unique", + "uniqueType": undefined, }, "addr": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "addr", "notNull": true, "primaryKey": false, + "uniqueName": "users_addr_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "addr", @@ -95,38 +253,63 @@ describe("buildTable", () => { "primary": false, "sqlName": "bytea", "table": [Circular], + "uniqueName": "users_addr_unique", + "uniqueType": undefined, }, "name": PgText { + "columnType": "PgText", "config": { + "columnType": "PgText", + "dataType": "string", "default": undefined, - "enumValues": [], + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "name": "name", "notNull": true, "primaryKey": false, + "uniqueName": "users_name_unique", + "uniqueType": undefined, }, + "dataType": "string", "default": undefined, - "enumValues": [], - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "name": "name", "notNull": true, "primary": false, "table": [Circular], + "uniqueName": "users_name_unique", + "uniqueType": undefined, }, "x": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "x", "notNull": true, "primaryKey": false, + "uniqueName": "users_x_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "x", @@ -134,22 +317,35 @@ describe("buildTable", () => { "primary": false, "sqlName": "integer", "table": [Circular], + "uniqueName": "users_x_unique", + "uniqueType": undefined, }, "y": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "y", "notNull": true, "primaryKey": false, + "uniqueName": "users_y_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "y", @@ -157,40 +353,138 @@ describe("buildTable", () => { "primary": false, "sqlName": "integer", "table": [Circular], + "uniqueName": "users_y_unique", + "uniqueType": undefined, }, Symbol(drizzle:Name): "users", Symbol(drizzle:OriginalName): "users", Symbol(drizzle:Schema): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test", Symbol(drizzle:Columns): { + "__dynamicData": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__dynamicData", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___dynamicData_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__dynamicData", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___dynamicData_unique", + "uniqueType": undefined, + }, + "__encodedLengths": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__encodedLengths", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___encodedLengths_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__encodedLengths", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___encodedLengths_unique", + "uniqueType": undefined, + }, "__isDeleted": PgBoolean { + "columnType": "PgBoolean", "config": { + "columnType": "PgBoolean", + "dataType": "boolean", "default": undefined, + "hasDefault": false, + "isUnique": false, "name": "__isDeleted", "notNull": true, "primaryKey": false, + "uniqueName": "users___isDeleted_unique", + "uniqueType": undefined, }, + "dataType": "boolean", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "name": "__isDeleted", "notNull": true, "primary": false, "table": [Circular], + "uniqueName": "users___isDeleted_unique", + "uniqueType": undefined, }, "__key": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "__key", "notNull": true, "primaryKey": true, + "uniqueName": "users___key_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "__key", @@ -198,22 +492,35 @@ describe("buildTable", () => { "primary": true, "sqlName": "bytea", "table": [Circular], + "uniqueName": "users___key_unique", + "uniqueType": undefined, }, "__lastUpdatedBlockNumber": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "__lastUpdatedBlockNumber", "notNull": true, "primaryKey": false, + "uniqueName": "users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "__lastUpdatedBlockNumber", @@ -221,22 +528,71 @@ describe("buildTable", () => { "primary": false, "sqlName": "numeric", "table": [Circular], + "uniqueName": "users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "__staticData": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__staticData", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___staticData_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__staticData", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___staticData_unique", + "uniqueType": undefined, }, "addr": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "addr", "notNull": true, "primaryKey": false, + "uniqueName": "users_addr_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "addr", @@ -244,38 +600,63 @@ describe("buildTable", () => { "primary": false, "sqlName": "bytea", "table": [Circular], + "uniqueName": "users_addr_unique", + "uniqueType": undefined, }, "name": PgText { + "columnType": "PgText", "config": { + "columnType": "PgText", + "dataType": "string", "default": undefined, - "enumValues": [], + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "name": "name", "notNull": true, "primaryKey": false, + "uniqueName": "users_name_unique", + "uniqueType": undefined, }, + "dataType": "string", "default": undefined, - "enumValues": [], - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "name": "name", "notNull": true, "primary": false, "table": [Circular], + "uniqueName": "users_name_unique", + "uniqueType": undefined, }, "x": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "x", "notNull": true, "primaryKey": false, + "uniqueName": "users_x_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "x", @@ -283,22 +664,35 @@ describe("buildTable", () => { "primary": false, "sqlName": "integer", "table": [Circular], + "uniqueName": "users_x_unique", + "uniqueType": undefined, }, "y": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "y", "notNull": true, "primaryKey": false, + "uniqueName": "users_y_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "y", @@ -306,6 +700,8 @@ describe("buildTable", () => { "primary": false, "sqlName": "integer", "table": [Circular], + "uniqueName": "users_y_unique", + "uniqueType": undefined, }, }, Symbol(drizzle:BaseName): "users", @@ -328,35 +724,131 @@ describe("buildTable", () => { expect(table).toMatchInlineSnapshot(` PgTable { + "__dynamicData": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__dynamicData", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___dynamicData_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__dynamicData", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___dynamicData_unique", + "uniqueType": undefined, + }, + "__encodedLengths": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__encodedLengths", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___encodedLengths_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__encodedLengths", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___encodedLengths_unique", + "uniqueType": undefined, + }, "__isDeleted": PgBoolean { + "columnType": "PgBoolean", "config": { + "columnType": "PgBoolean", + "dataType": "boolean", "default": undefined, + "hasDefault": false, + "isUnique": false, "name": "__isDeleted", "notNull": true, "primaryKey": false, + "uniqueName": "users___isDeleted_unique", + "uniqueType": undefined, }, + "dataType": "boolean", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "name": "__isDeleted", "notNull": true, "primary": false, "table": [Circular], + "uniqueName": "users___isDeleted_unique", + "uniqueType": undefined, }, "__key": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "__key", "notNull": true, "primaryKey": true, + "uniqueName": "users___key_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "__key", @@ -364,22 +856,35 @@ describe("buildTable", () => { "primary": true, "sqlName": "bytea", "table": [Circular], + "uniqueName": "users___key_unique", + "uniqueType": undefined, }, "__lastUpdatedBlockNumber": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "__lastUpdatedBlockNumber", "notNull": true, "primaryKey": false, + "uniqueName": "users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "__lastUpdatedBlockNumber", @@ -387,22 +892,71 @@ describe("buildTable", () => { "primary": false, "sqlName": "numeric", "table": [Circular], + "uniqueName": "users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "__staticData": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__staticData", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___staticData_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__staticData", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___staticData_unique", + "uniqueType": undefined, }, "addrs": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "addrs", "notNull": true, "primaryKey": false, + "uniqueName": "users_addrs_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "addrs", @@ -410,40 +964,138 @@ describe("buildTable", () => { "primary": false, "sqlName": "text", "table": [Circular], + "uniqueName": "users_addrs_unique", + "uniqueType": undefined, }, Symbol(drizzle:Name): "users", Symbol(drizzle:OriginalName): "users", Symbol(drizzle:Schema): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test", Symbol(drizzle:Columns): { + "__dynamicData": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__dynamicData", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___dynamicData_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__dynamicData", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___dynamicData_unique", + "uniqueType": undefined, + }, + "__encodedLengths": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__encodedLengths", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___encodedLengths_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__encodedLengths", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___encodedLengths_unique", + "uniqueType": undefined, + }, "__isDeleted": PgBoolean { + "columnType": "PgBoolean", "config": { + "columnType": "PgBoolean", + "dataType": "boolean", "default": undefined, + "hasDefault": false, + "isUnique": false, "name": "__isDeleted", "notNull": true, "primaryKey": false, + "uniqueName": "users___isDeleted_unique", + "uniqueType": undefined, }, + "dataType": "boolean", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "name": "__isDeleted", "notNull": true, "primary": false, "table": [Circular], + "uniqueName": "users___isDeleted_unique", + "uniqueType": undefined, }, "__key": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "__key", "notNull": true, "primaryKey": true, + "uniqueName": "users___key_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "__key", @@ -451,22 +1103,35 @@ describe("buildTable", () => { "primary": true, "sqlName": "bytea", "table": [Circular], + "uniqueName": "users___key_unique", + "uniqueType": undefined, }, "__lastUpdatedBlockNumber": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "__lastUpdatedBlockNumber", "notNull": true, "primaryKey": false, + "uniqueName": "users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "__lastUpdatedBlockNumber", @@ -474,22 +1139,71 @@ describe("buildTable", () => { "primary": false, "sqlName": "numeric", "table": [Circular], + "uniqueName": "users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "__staticData": PgCustomColumn { + "columnType": "PgCustomColumn", + "config": { + "columnType": "PgCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__staticData", + "notNull": false, + "primaryKey": false, + "uniqueName": "users___staticData_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "__staticData", + "notNull": false, + "primary": false, + "sqlName": "bytea", + "table": [Circular], + "uniqueName": "users___staticData_unique", + "uniqueType": undefined, }, "addrs": PgCustomColumn { + "columnType": "PgCustomColumn", "config": { + "columnType": "PgCustomColumn", "customTypeParams": { "dataType": [Function], "fromDriver": [Function], "toDriver": [Function], }, + "dataType": "custom", "default": undefined, "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, "name": "addrs", "notNull": true, "primaryKey": false, + "uniqueName": "users_addrs_unique", + "uniqueType": undefined, }, + "dataType": "custom", "default": undefined, - "hasDefault": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, "mapFrom": [Function], "mapTo": [Function], "name": "addrs", @@ -497,6 +1211,8 @@ describe("buildTable", () => { "primary": false, "sqlName": "text", "table": [Circular], + "uniqueName": "users_addrs_unique", + "uniqueType": undefined, }, }, Symbol(drizzle:BaseName): "users", diff --git a/packages/store-sync/src/postgres/buildTable.ts b/packages/store-sync/src/postgres/buildTable.ts index 0a9e24cd42..2fb7feb499 100644 --- a/packages/store-sync/src/postgres/buildTable.ts +++ b/packages/store-sync/src/postgres/buildTable.ts @@ -1,4 +1,4 @@ -import { AnyPgColumnBuilder, PgTableWithColumns, pgSchema } from "drizzle-orm/pg-core"; +import { PgColumnBuilderBase, PgTableWithColumns, pgSchema } from "drizzle-orm/pg-core"; import { buildColumn } from "./buildColumn"; import { Address, getAddress } from "viem"; import { transformSchemaName } from "./transformSchemaName"; @@ -6,13 +6,17 @@ import { KeySchema, ValueSchema } from "@latticexyz/protocol-parser"; // TODO: convert camel case to snake case for DB storage? export const metaColumns = { - __key: buildColumn("__key", "bytes").notNull().primaryKey(), + __key: buildColumn("__key", "bytes").primaryKey(), + __staticData: buildColumn("__staticData", "bytes"), + __encodedLengths: buildColumn("__encodedLengths", "bytes"), + __dynamicData: buildColumn("__dynamicData", "bytes"), __lastUpdatedBlockNumber: buildColumn("__lastUpdatedBlockNumber", "uint256").notNull(), // TODO: last updated block hash? __isDeleted: buildColumn("__isDeleted", "bool").notNull(), -} as const satisfies Record; +} as const satisfies Record; type PgTableFromSchema = PgTableWithColumns<{ + dialect: "pg"; name: string; schema: string; columns: { diff --git a/packages/store-sync/src/postgres/cleanDatabase.ts b/packages/store-sync/src/postgres/cleanDatabase.ts index eff82aaf50..26d22ad31c 100644 --- a/packages/store-sync/src/postgres/cleanDatabase.ts +++ b/packages/store-sync/src/postgres/cleanDatabase.ts @@ -1,11 +1,10 @@ -import { PgDatabase } from "drizzle-orm/pg-core"; +import { PgDatabase, getTableConfig } from "drizzle-orm/pg-core"; import { buildInternalTables } from "./buildInternalTables"; import { getTables } from "./getTables"; import { buildTable } from "./buildTable"; -import { getSchema } from "./getSchema"; import { isDefined } from "@latticexyz/common/utils"; import { debug } from "./debug"; -import { getTableName, sql } from "drizzle-orm"; +import { sql } from "drizzle-orm"; import { pgDialect } from "./pgDialect"; // This intentionally just cleans up known schemas/tables/rows. We could drop the database but that's scary. @@ -16,7 +15,7 @@ export async function cleanDatabase(db: PgDatabase): Promise { const tables = (await getTables(db)).map(buildTable); - const schemaNames = [...new Set(tables.map(getSchema))].filter(isDefined); + const schemaNames = [...new Set(tables.map((table) => getTableConfig(table).schema))].filter(isDefined); for (const schemaName of schemaNames) { try { @@ -28,7 +27,8 @@ export async function cleanDatabase(db: PgDatabase): Promise { } for (const internalTable of Object.values(internalTables)) { - debug(`deleting all rows from ${getSchema(internalTable)}.${getTableName(internalTable)}`); + const tableConfig = getTableConfig(internalTable); + debug(`deleting all rows from ${tableConfig.schema}.${tableConfig.name}`); await db.delete(internalTable); } } diff --git a/packages/store-sync/src/postgres/columnTypes.ts b/packages/store-sync/src/postgres/columnTypes.ts index 97fd352080..da9d9761f8 100644 --- a/packages/store-sync/src/postgres/columnTypes.ts +++ b/packages/store-sync/src/postgres/columnTypes.ts @@ -1,11 +1,9 @@ -import { customType, PgCustomColumnBuilder } from "drizzle-orm/pg-core"; -import { ColumnBuilderBaseConfig } from "drizzle-orm"; +import { customType } from "drizzle-orm/pg-core"; import superjson from "superjson"; import { Address, ByteArray, bytesToHex, getAddress, Hex, hexToBytes } from "viem"; -export const asJson = ( - name: string -): PgCustomColumnBuilder => +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export const asJson = (name: string) => customType<{ data: TData; driverData: string }>({ dataType() { // TODO: move to json column type? if we do, we'll prob wanna choose something other than superjson since it adds one level of depth (json/meta keys) @@ -19,10 +17,8 @@ export const asJson = ( }, })(name); -export const asNumber = ( - name: string, - columnType: string -): PgCustomColumnBuilder => +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export const asNumber = (name: string, columnType: string) => customType<{ data: number; driverData: string }>({ dataType() { return columnType; @@ -35,10 +31,8 @@ export const asNumber = ( }, })(name); -export const asBigInt = ( - name: string, - columnType: string -): PgCustomColumnBuilder => +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export const asBigInt = (name: string, columnType: string) => customType<{ data: bigint; driverData: string }>({ dataType() { return columnType; @@ -51,9 +45,8 @@ export const asBigInt = ( }, })(name); -export const asHex = ( - name: string -): PgCustomColumnBuilder => +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export const asHex = (name: string) => customType<{ data: Hex; driverData: ByteArray }>({ dataType() { return "bytea"; @@ -66,9 +59,8 @@ export const asHex = ( }, })(name); -export const asAddress = ( - name: string -): PgCustomColumnBuilder => +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export const asAddress = (name: string) => customType<{ data: Address; driverData: ByteArray }>({ dataType() { return "bytea"; diff --git a/packages/store-sync/src/postgres/getSchema.test.ts b/packages/store-sync/src/postgres/getSchema.test.ts deleted file mode 100644 index c0c9a045a5..0000000000 --- a/packages/store-sync/src/postgres/getSchema.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { describe, it, expect } from "vitest"; -import { getSchema } from "./getSchema"; -import { pgTable, pgSchema } from "drizzle-orm/pg-core"; - -// Test to make sure getSchema matches drizzle internals. May need to update getSchema if these tests start failing. Hopefully by then, drizzle will have exposed their own getSchema method. - -describe("getSchema", () => { - it("should return schema if set", async () => { - expect(getSchema(pgTable("no schema", {}))).toBeUndefined(); - expect(getSchema(pgSchema("some schema").table("with schema", {}))).toBe("some schema"); - }); -}); diff --git a/packages/store-sync/src/postgres/getSchema.ts b/packages/store-sync/src/postgres/getSchema.ts deleted file mode 100644 index 240046fcd4..0000000000 --- a/packages/store-sync/src/postgres/getSchema.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { PgTable } from "drizzle-orm/pg-core"; - -// TODO: PR to drizzle to expose `getSchema` like `getTableName` -export function getSchema(table: PgTable): string | undefined { - return (table as any)[Symbol.for("drizzle:Schema")]; -} diff --git a/packages/store-sync/src/postgres/getTableKey.ts b/packages/store-sync/src/postgres/getTableKey.ts index 423830ce23..3c58cae80e 100644 --- a/packages/store-sync/src/postgres/getTableKey.ts +++ b/packages/store-sync/src/postgres/getTableKey.ts @@ -1,6 +1,8 @@ import { getAddress } from "viem"; import { Table } from "../common"; +import { hexToTableId } from "@latticexyz/common"; -export function getTableKey(table: Pick): string { - return `${getAddress(table.address)}:${table.namespace}:${table.name}`; +export function getTableKey({ address, tableId }: Pick): string { + const { namespace, name } = hexToTableId(tableId); + return `${getAddress(address)}:${namespace}:${name}`; } diff --git a/packages/store-sync/src/postgres/postgresStorage.test.ts b/packages/store-sync/src/postgres/postgresStorage.test.ts index 47c29b5ee9..341546978a 100644 --- a/packages/store-sync/src/postgres/postgresStorage.test.ts +++ b/packages/store-sync/src/postgres/postgresStorage.test.ts @@ -1,15 +1,29 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -import { DefaultLogger } from "drizzle-orm"; +import { DefaultLogger, eq } from "drizzle-orm"; import { drizzle } from "drizzle-orm/postgres-js"; import postgres from "postgres"; -import { createPublicClient, http } from "viem"; +import { Hex, RpcLog, createPublicClient, decodeEventLog, formatLog, http } from "viem"; import { foundry } from "viem/chains"; -import { blockLogsToStorage } from "../blockLogsToStorage"; import * as transformSchemaNameExports from "./transformSchemaName"; import { getTables } from "./getTables"; import { PostgresStorageAdapter, postgresStorage } from "./postgresStorage"; import { buildTable } from "./buildTable"; +import { groupLogsByBlockNumber } from "@latticexyz/block-logs-stream"; +import { storeEventsAbi } from "@latticexyz/store"; import { StoreEventsLog } from "../common"; +import worldRpcLogs from "../../../../test-data/world-logs.json"; + +const blocks = groupLogsByBlockNumber( + worldRpcLogs.map((log) => { + const { eventName, args } = decodeEventLog({ + abi: storeEventsAbi, + data: log.data as Hex, + topics: log.topics as [Hex, ...Hex[]], + strict: true, + }); + return formatLog(log as any as RpcLog, { args, eventName: eventName as string }) as StoreEventsLog; + }) +); vi.spyOn(transformSchemaNameExports, "transformSchemaName").mockImplementation( (schemaName) => `${process.pid}_${process.env.VITEST_POOL_ID}__${schemaName}` @@ -33,104 +47,79 @@ describe("postgresStorage", async () => { }); it("should create tables and data from block log", async () => { - await blockLogsToStorage(storageAdapter)({ - blockNumber: 5448n, - logs: [ - { - address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", - topics: ["0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46"], - data: "0x000000000000000000000000000000005265736f7572636554797065000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e76656e746f72790000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - blockHash: "0x4ad3752c86f900332e0d2d8903480e7206747d233586574d16f006eebdb5138b", - blockNumber: 2n, - transactionHash: "0xaa54bf18053cce5d4d2906538a60cb1d9958cc3c10c34b5f9fdc92fe6a6abab4", - transactionIndex: 16, - logIndex: 54, - removed: false, - args: { - tableId: "0x000000000000000000000000000000005265736f757263655479706500000000", - keyTuple: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"], - schemaIndex: 0, - data: "0x02", - }, - eventName: "StoreSetField", - }, - { - address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", - topics: ["0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32"], - data: "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e76656e746f72790000000000000000000000000000000000000000000000000000000000000000000000000002800004010004000000000000000000000000000000000000000000000000000000001c030061030300000000000000000000000000000000000000000000000000000401000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000001600000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000056f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046974656d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6974656d56617269616e740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006616d6f756e740000000000000000000000000000000000000000000000000000", - blockHash: "0x4ad3752c86f900332e0d2d8903480e7206747d233586574d16f006eebdb5138b", - blockNumber: 2n, - transactionHash: "0xaa54bf18053cce5d4d2906538a60cb1d9958cc3c10c34b5f9fdc92fe6a6abab4", - transactionIndex: 16, - logIndex: 55, - removed: false, - args: { - tableId: "0x6d756473746f726500000000000000005461626c657300000000000000000000", - keyTuple: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"], - data: "0x0004010004000000000000000000000000000000000000000000000000000000001c030061030300000000000000000000000000000000000000000000000000000401000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000001600000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000056f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046974656d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6974656d56617269616e740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006616d6f756e740000000000000000000000000000000000000000000000000000", - }, - eventName: "StoreSetRecord", - }, - ] satisfies StoreEventsLog[], - }); + for (const block of blocks) { + await storageAdapter.storageAdapter(block); + } expect(await db.select().from(storageAdapter.internalTables.chain)).toMatchInlineSnapshot(` [ { "chainId": 31337, "lastError": null, - "lastUpdatedBlockNumber": 5448n, + "lastUpdatedBlockNumber": 6n, "schemaVersion": 1, }, ] `); - expect(await db.select().from(storageAdapter.internalTables.tables)).toMatchInlineSnapshot(` + expect( + await db + .select() + .from(storageAdapter.internalTables.tables) + .where(eq(storageAdapter.internalTables.tables.name, "NumberList")) + ).toMatchInlineSnapshot(` [ { "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", - "key": "0x5FbDB2315678afecb367f032d93F642f64180aa3::Inventory", - "keySchema": { - "item": "uint32", - "itemVariant": "uint32", - "owner": "address", - }, + "key": "0x5FbDB2315678afecb367f032d93F642f64180aa3::NumberList", + "keySchema": {}, "lastError": null, - "lastUpdatedBlockNumber": 5448n, - "name": "Inventory", + "lastUpdatedBlockNumber": 6n, + "name": "NumberList", "namespace": "", "schemaVersion": 1, - "tableId": "0x00000000000000000000000000000000496e76656e746f727900000000000000", + "tableId": "0x000000000000000000000000000000004e756d6265724c697374000000000000", "valueSchema": { - "amount": "uint32", + "value": "uint32[]", }, }, ] `); - const tables = await getTables(db, []); + const tables = (await getTables(db)).filter((table) => table.name === "NumberList"); expect(tables).toMatchInlineSnapshot(` [ { "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", - "keySchema": { - "item": "uint32", - "itemVariant": "uint32", - "owner": "address", - }, - "lastUpdatedBlockNumber": 5448n, - "name": "Inventory", + "keySchema": {}, + "lastUpdatedBlockNumber": 6n, + "name": "NumberList", "namespace": "", - "tableId": "0x00000000000000000000000000000000496e76656e746f727900000000000000", + "tableId": "0x000000000000000000000000000000004e756d6265724c697374000000000000", "valueSchema": { - "amount": "uint32", + "value": "uint32[]", }, }, ] `); const sqlTable = buildTable(tables[0]); - expect(await db.select().from(sqlTable)).toMatchInlineSnapshot("[]"); + expect(await db.select().from(sqlTable)).toMatchInlineSnapshot(` + [ + { + "__dynamicData": "0x000001a400000045", + "__encodedLengths": "0x0000000000000000000000000000000000000000000000000800000000000008", + "__isDeleted": false, + "__key": "0x", + "__lastUpdatedBlockNumber": 6n, + "__staticData": null, + "value": [ + 420, + 69, + ], + }, + ] + `); await storageAdapter.cleanUp(); }); diff --git a/packages/store-sync/src/postgres/postgresStorage.ts b/packages/store-sync/src/postgres/postgresStorage.ts index 1937a9796a..7e61e5f5d7 100644 --- a/packages/store-sync/src/postgres/postgresStorage.ts +++ b/packages/store-sync/src/postgres/postgresStorage.ts @@ -1,21 +1,24 @@ -import { PublicClient, concatHex, encodeAbiParameters } from "viem"; +import { Hex, PublicClient, concatHex } from "viem"; import { PgDatabase, QueryResultHKT } from "drizzle-orm/pg-core"; import { eq, inArray } from "drizzle-orm"; import { buildTable } from "./buildTable"; -import { schemaToDefaults } from "../schemaToDefaults"; import { StoreConfig } from "@latticexyz/store"; import { debug } from "./debug"; import { buildInternalTables } from "./buildInternalTables"; import { getTables } from "./getTables"; import { schemaVersion } from "./schemaVersion"; -import { tableIdToHex } from "@latticexyz/common"; +import { hexToTableId, spliceHex, tableIdToHex } from "@latticexyz/common"; import { setupTables } from "./setupTables"; import { getTableKey } from "./getTableKey"; -import { StorageAdapter } from "../common"; +import { StorageAdapter, StorageAdapterBlock } from "../common"; +import { isTableRegistrationLog } from "../isTableRegistrationLog"; +import { logToTable } from "../logToTable"; +import { decodeKey, decodeValueArgs } from "@latticexyz/protocol-parser"; // Currently assumes one DB per chain ID -export type PostgresStorageAdapter = StorageAdapter & { +export type PostgresStorageAdapter = { + storageAdapter: StorageAdapter; internalTables: ReturnType; cleanUp: () => Promise; }; @@ -27,7 +30,7 @@ export async function postgresStorage database: PgDatabase; publicClient: PublicClient; config?: TConfig; -}): Promise> { +}): Promise { const cleanUp: (() => Promise)[] = []; const chainId = publicClient.chain?.id ?? (await publicClient.getChainId()); @@ -35,153 +38,229 @@ export async function postgresStorage const internalTables = buildInternalTables(); cleanUp.push(await setupTables(database, Object.values(internalTables))); - const storageAdapter = { - async registerTables({ blockNumber, tables }) { - const sqlTables = tables.map((table) => - buildTable({ - address: table.address, - namespace: table.namespace, - name: table.name, - keySchema: table.keySchema, - valueSchema: table.valueSchema, - }) - ); + async function postgresStorageAdapter({ blockNumber, logs }: StorageAdapterBlock): Promise { + const newTables = logs.filter(isTableRegistrationLog).map(logToTable); + const newSqlTables = newTables.map((table) => + buildTable({ + address: table.address, + namespace: table.namespace, + name: table.name, + keySchema: table.keySchema, + valueSchema: table.valueSchema, + }) + ); - cleanUp.push(await setupTables(database, sqlTables)); + cleanUp.push(await setupTables(database, newSqlTables)); - await database.transaction(async (tx) => { - for (const table of tables) { - await tx - .insert(internalTables.tables) - .values({ - schemaVersion, - key: getTableKey(table), - address: table.address, - tableId: tableIdToHex(table.namespace, table.name), - namespace: table.namespace, - name: table.name, - keySchema: table.keySchema, - valueSchema: table.valueSchema, - lastUpdatedBlockNumber: blockNumber, - }) - .onConflictDoNothing() - .execute(); - } - }); - }, - async getTables({ tables }) { - // TODO: fetch any missing schemas from RPC - // TODO: cache schemas in memory? - return getTables(database, tables.map(getTableKey)); - }, - async storeOperations({ blockNumber, operations }) { - // This is currently parallelized per world (each world has its own database). - // This may need to change if we decide to put multiple worlds into one DB (e.g. a namespace per world, but all under one DB). - // If so, we'll probably want to wrap the entire block worth of operations in a transaction. + await database.transaction(async (tx) => { + for (const table of newTables) { + await tx + .insert(internalTables.tables) + .values({ + schemaVersion, + key: getTableKey(table), + address: table.address, + tableId: tableIdToHex(table.namespace, table.name), + namespace: table.namespace, + name: table.name, + keySchema: table.keySchema, + valueSchema: table.valueSchema, + lastUpdatedBlockNumber: blockNumber, + }) + .onConflictDoNothing() + .execute(); + } + }); + + const tables = await getTables( + database, + logs.map((log) => getTableKey({ address: log.address, tableId: log.args.tableId })) + ); + + // This is currently parallelized per world (each world has its own database). + // This may need to change if we decide to put multiple worlds into one DB (e.g. a namespace per world, but all under one DB). + // If so, we'll probably want to wrap the entire block worth of operations in a transaction. - const tables = await getTables(database, operations.map(getTableKey)); + await database.transaction(async (tx) => { + const tablesWithOperations = tables.filter((table) => + logs.some((log) => getTableKey({ address: log.address, tableId: log.args.tableId }) === getTableKey(table)) + ); + if (tablesWithOperations.length) { + await tx + .update(internalTables.tables) + .set({ lastUpdatedBlockNumber: blockNumber }) + .where(inArray(internalTables.tables.key, [...new Set(tablesWithOperations.map(getTableKey))])) + .execute(); + } - await database.transaction(async (tx) => { - const tablesWithOperations = tables.filter((table) => - operations.some((op) => getTableKey(op) === getTableKey(table)) + for (const log of logs) { + const table = tables.find( + (table) => getTableKey(table) === getTableKey({ address: log.address, tableId: log.args.tableId }) ); - if (tablesWithOperations.length) { - await tx - .update(internalTables.tables) - .set({ lastUpdatedBlockNumber: blockNumber }) - .where(inArray(internalTables.tables.key, [...new Set(tablesWithOperations.map(getTableKey))])) - .execute(); + if (!table) { + const { namespace, name } = hexToTableId(log.args.tableId); + debug(`table ${namespace}:${name} not found, skipping log`, log); + continue; } - for (const operation of operations) { - const table = tables.find((table) => getTableKey(table) === getTableKey(operation)); - if (!table) { - debug(`table ${operation.namespace}:${operation.name} not found, skipping operation`, operation); - continue; - } - - const sqlTable = buildTable(table); - const key = concatHex( - Object.entries(table.keySchema).map(([keyName, type]) => - encodeAbiParameters([{ type }], [operation.key[keyName]]) - ) - ); - - if (operation.type === "SetRecord") { - debug("SetRecord", operation); - await tx - .insert(sqlTable) - .values({ - __key: key, + const sqlTable = buildTable(table); + const uniqueKey = concatHex(log.args.keyTuple as Hex[]); + const key = decodeKey(table.keySchema, log.args.keyTuple); + + debug(log.eventName, log); + + if (log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord") { + const value = decodeValueArgs(table.valueSchema, log.args); + debug("upserting record", { + namespace: table.namespace, + name: table.name, + key, + value, + }); + await tx + .insert(sqlTable) + .values({ + __key: uniqueKey, + __staticData: log.args.staticData, + __encodedLengths: log.args.encodedLengths, + __dynamicData: log.args.dynamicData, + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: false, + ...key, + ...value, + }) + .onConflictDoUpdate({ + target: sqlTable.__key, + set: { + __staticData: log.args.staticData, + __encodedLengths: log.args.encodedLengths, + __dynamicData: log.args.dynamicData, __lastUpdatedBlockNumber: blockNumber, __isDeleted: false, - ...operation.key, - ...operation.value, - }) - .onConflictDoUpdate({ - target: sqlTable.__key, - set: { - __lastUpdatedBlockNumber: blockNumber, - __isDeleted: false, - ...operation.value, - }, - }) - .execute(); - } else if (operation.type === "SetField") { - debug("SetField", operation); - await tx - .insert(sqlTable) - .values({ - __key: key, + ...value, + }, + }) + .execute(); + } else if (log.eventName === "StoreSpliceStaticData") { + // TODO: verify that this returns what we expect (doesn't error/undefined on no record) + const previousValue = (await tx.select().from(sqlTable).where(eq(sqlTable.__key, uniqueKey)).execute())[0]; + const previousStaticData = (previousValue?.__staticData as Hex) ?? "0x"; + const newStaticData = spliceHex(previousStaticData, log.args.start, log.args.deleteCount, log.args.data); + const newValue = decodeValueArgs(table.valueSchema, { + staticData: newStaticData, + encodedLengths: (previousValue?.__encodedLengths as Hex) ?? "0x", + dynamicData: (previousValue?.__dynamicData as Hex) ?? "0x", + }); + debug("upserting record via splice static", { + namespace: table.namespace, + name: table.name, + key, + previousStaticData, + newStaticData, + previousValue, + newValue, + }); + await tx + .insert(sqlTable) + .values({ + __key: uniqueKey, + __staticData: newStaticData, + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: false, + ...key, + ...newValue, + }) + .onConflictDoUpdate({ + target: sqlTable.__key, + set: { + __staticData: newStaticData, __lastUpdatedBlockNumber: blockNumber, __isDeleted: false, - ...operation.key, - ...schemaToDefaults(table.valueSchema), - [operation.fieldName]: operation.fieldValue, - }) - .onConflictDoUpdate({ - target: sqlTable.__key, - set: { - __lastUpdatedBlockNumber: blockNumber, - __isDeleted: false, - [operation.fieldName]: operation.fieldValue, - }, - }) - .execute(); - } else if (operation.type === "DeleteRecord") { - // TODO: should we upsert so we at least have a DB record of when a thing was created/deleted within the same block? - debug("DeleteRecord", operation); - await tx - .update(sqlTable) - .set({ + ...newValue, + }, + }) + .execute(); + } else if (log.eventName === "StoreSpliceDynamicData") { + // TODO: verify that this returns what we expect (doesn't error/undefined on no record) + const previousValue = (await tx.select().from(sqlTable).where(eq(sqlTable.__key, uniqueKey)).execute())[0]; + const previousDynamicData = (previousValue?.__dynamicData as Hex) ?? "0x"; + const newDynamicData = spliceHex(previousDynamicData, log.args.start, log.args.deleteCount, log.args.data); + const newValue = decodeValueArgs(table.valueSchema, { + staticData: (previousValue?.__staticData as Hex) ?? "0x", + // TODO: handle unchanged encoded lengths + encodedLengths: log.args.encodedLengths, + dynamicData: newDynamicData, + }); + debug("upserting record via splice dynamic", { + namespace: table.namespace, + name: table.name, + key, + previousDynamicData, + newDynamicData, + previousValue, + newValue, + }); + await tx + .insert(sqlTable) + .values({ + __key: uniqueKey, + // TODO: handle unchanged encoded lengths + __encodedLengths: log.args.encodedLengths, + __dynamicData: newDynamicData, + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: false, + ...key, + ...newValue, + }) + .onConflictDoUpdate({ + target: sqlTable.__key, + set: { + // TODO: handle unchanged encoded lengths + __encodedLengths: log.args.encodedLengths, + __dynamicData: newDynamicData, __lastUpdatedBlockNumber: blockNumber, - __isDeleted: true, - }) - .where(eq(sqlTable.__key, key)) - .execute(); - } + __isDeleted: false, + ...newValue, + }, + }) + .execute(); + } else if (log.eventName === "StoreDeleteRecord") { + // TODO: should we upsert so we at least have a DB record of when a thing was created/deleted within the same block? + debug("deleting record", { + namespace: table.namespace, + name: table.name, + key, + }); + await tx + .update(sqlTable) + .set({ + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: true, + }) + .where(eq(sqlTable.__key, uniqueKey)) + .execute(); } + } - await tx - .insert(internalTables.chain) - .values({ - schemaVersion, - chainId, + await tx + .insert(internalTables.chain) + .values({ + schemaVersion, + chainId, + lastUpdatedBlockNumber: blockNumber, + }) + .onConflictDoUpdate({ + target: [internalTables.chain.schemaVersion, internalTables.chain.chainId], + set: { lastUpdatedBlockNumber: blockNumber, - }) - .onConflictDoUpdate({ - target: [internalTables.chain.schemaVersion, internalTables.chain.chainId], - set: { - lastUpdatedBlockNumber: blockNumber, - }, - }) - .execute(); - }); - }, - } as StorageAdapter; + }, + }) + .execute(); + }); + } return { - ...storageAdapter, + storageAdapter: postgresStorageAdapter, internalTables, cleanUp: async (): Promise => { for (const fn of cleanUp) { diff --git a/packages/store-sync/src/postgres/setupTables.ts b/packages/store-sync/src/postgres/setupTables.ts index 1ddcedaa6f..d15f92ce54 100644 --- a/packages/store-sync/src/postgres/setupTables.ts +++ b/packages/store-sync/src/postgres/setupTables.ts @@ -1,7 +1,6 @@ -import { AnyPgColumn, PgTableWithColumns, PgDatabase } from "drizzle-orm/pg-core"; -import { getTableColumns, getTableName, sql } from "drizzle-orm"; +import { AnyPgColumn, PgTableWithColumns, PgDatabase, getTableConfig } from "drizzle-orm/pg-core"; +import { getTableColumns, sql } from "drizzle-orm"; import { ColumnDataType } from "kysely"; -import { getSchema } from "./getSchema"; import { isDefined } from "@latticexyz/common/utils"; import { debug } from "./debug"; import { pgDialect } from "./pgDialect"; @@ -13,7 +12,7 @@ export async function setupTables( // TODO: add table to internal tables here // TODO: look up table schema and check if it matches expected schema, drop if not - const schemaNames = [...new Set(tables.map(getSchema).filter(isDefined))]; + const schemaNames = [...new Set(tables.map((table) => getTableConfig(table).schema).filter(isDefined))]; await db.transaction(async (tx) => { for (const schemaName of schemaNames) { @@ -22,12 +21,10 @@ export async function setupTables( } for (const table of tables) { - const schemaName = getSchema(table); - const scopedDb = schemaName ? pgDialect.withSchema(schemaName) : pgDialect; + const tableConfig = getTableConfig(table); + const scopedDb = tableConfig.schema ? pgDialect.withSchema(tableConfig.schema) : pgDialect; - const tableName = getTableName(table); - - let query = scopedDb.schema.createTable(tableName).ifNotExists(); + let query = scopedDb.schema.createTable(tableConfig.name).ifNotExists(); const columns = Object.values(getTableColumns(table)) as AnyPgColumn[]; for (const column of columns) { @@ -44,10 +41,10 @@ export async function setupTables( const primaryKeys = columns.filter((column) => column.primary).map((column) => column.name); if (primaryKeys.length) { - query = query.addPrimaryKeyConstraint(`${tableName}__pk`, primaryKeys as any); + query = query.addPrimaryKeyConstraint(`${tableConfig.name}__pk`, primaryKeys as any); } - debug(`creating table ${tableName} in namespace ${schemaName}`); + debug(`creating table ${tableConfig.name} in namespace ${tableConfig.schema}`); await tx.execute(sql.raw(query.compile().sql)); } }); diff --git a/packages/store-sync/src/postgres/syncToPostgres.ts b/packages/store-sync/src/postgres/syncToPostgres.ts index be649f4e78..1042ab2832 100644 --- a/packages/store-sync/src/postgres/syncToPostgres.ts +++ b/packages/store-sync/src/postgres/syncToPostgres.ts @@ -14,7 +14,7 @@ type SyncToPostgresOptions = SyncOpti startSync?: boolean; }; -type SyncToPostgresResult = SyncResult & { +type SyncToPostgresResult = SyncResult & { stopSync: () => void; }; @@ -34,9 +34,10 @@ export async function syncToPostgres( indexerUrl, initialState, startSync = true, -}: SyncToPostgresOptions): Promise> { +}: SyncToPostgresOptions): Promise { + const { storageAdapter } = await postgresStorage({ database, publicClient, config }); const storeSync = await createStoreSync({ - storageAdapter: await postgresStorage({ database, publicClient, config }), + storageAdapter, config, address, publicClient, @@ -46,7 +47,7 @@ export async function syncToPostgres( initialState, }); - const sub = startSync ? storeSync.blockStorageOperations$.subscribe() : null; + const sub = startSync ? storeSync.storedBlockLogs$.subscribe() : null; const stopSync = (): void => { sub?.unsubscribe(); }; diff --git a/packages/store-sync/src/recs/common.test-d.ts b/packages/store-sync/src/recs/common.test-d.ts index bf1e450859..a2f81ff7a4 100644 --- a/packages/store-sync/src/recs/common.test-d.ts +++ b/packages/store-sync/src/recs/common.test-d.ts @@ -4,18 +4,27 @@ import storeConfig from "@latticexyz/store/mud.config"; import { ConfigToRecsComponents } from "./common"; describe("ConfigToRecsComponents", () => { - expectTypeOf["StoreMetadata"]>().toEqualTypeOf< + expectTypeOf["Tables"]>().toEqualTypeOf< Component< { - tableName: RecsType.String; + keySchema: RecsType.String; + valueSchema: RecsType.String; + abiEncodedKeyNames: RecsType.String; abiEncodedFieldNames: RecsType.String; }, { - componentName: "StoreMetadata"; + componentName: "Tables"; // TODO: fix config namespace so it comes back as a const - tableName: `${string}:StoreMetadata`; - keySchema: { tableId: "bytes32" }; - valueSchema: { tableName: "string"; abiEncodedFieldNames: "bytes" }; + tableName: `${string}:Tables`; + keySchema: { + tableId: "bytes32"; + }; + valueSchema: { + keySchema: "bytes32"; + valueSchema: "bytes32"; + abiEncodedKeyNames: "bytes"; + abiEncodedFieldNames: "bytes"; + }; } > >(); diff --git a/packages/store-sync/src/recs/common.ts b/packages/store-sync/src/recs/common.ts index d33aeb5b93..09622f2fe8 100644 --- a/packages/store-sync/src/recs/common.ts +++ b/packages/store-sync/src/recs/common.ts @@ -14,6 +14,10 @@ export type StoreComponentMetadata = RecsMetadata & { export type ConfigToRecsComponents = { [tableName in keyof TConfig["tables"] & string]: RecsComponent< { + __staticData: RecsType.OptionalString; + __encodedLengths: RecsType.OptionalString; + __dynamicData: RecsType.OptionalString; + } & { [fieldName in keyof TConfig["tables"][tableName]["valueSchema"] & string]: RecsType & SchemaAbiTypeToRecsType; }, diff --git a/packages/store-sync/src/recs/configToRecsComponents.ts b/packages/store-sync/src/recs/configToRecsComponents.ts index 1d5b9e760e..9243f846c9 100644 --- a/packages/store-sync/src/recs/configToRecsComponents.ts +++ b/packages/store-sync/src/recs/configToRecsComponents.ts @@ -1,7 +1,7 @@ import { StoreConfig } from "@latticexyz/store"; import { SchemaAbiType } from "@latticexyz/schema-type"; import { tableIdToHex } from "@latticexyz/common"; -import { World, defineComponent } from "@latticexyz/recs"; +import { World, defineComponent, Type } from "@latticexyz/recs"; import { ConfigToRecsComponents } from "./common"; import { schemaAbiTypeToRecsType } from "./schemaAbiTypeToRecsType"; @@ -14,12 +14,17 @@ export function configToRecsComponents( tableName, defineComponent( world, - Object.fromEntries( - Object.entries(table.valueSchema).map(([fieldName, schemaAbiType]) => [ - fieldName, - schemaAbiTypeToRecsType[schemaAbiType as SchemaAbiType], - ]) - ), + { + ...Object.fromEntries( + Object.entries(table.valueSchema).map(([fieldName, schemaAbiType]) => [ + fieldName, + schemaAbiTypeToRecsType[schemaAbiType as SchemaAbiType], + ]) + ), + __staticData: Type.OptionalString, + __encodedLengths: Type.OptionalString, + __dynamicData: Type.OptionalString, + }, { id: tableIdToHex(config.namespace, tableName), metadata: { diff --git a/packages/store-sync/src/recs/decodeEntity.ts b/packages/store-sync/src/recs/decodeEntity.ts index 90167726f0..ba2c084a7f 100644 --- a/packages/store-sync/src/recs/decodeEntity.ts +++ b/packages/store-sync/src/recs/decodeEntity.ts @@ -1,7 +1,7 @@ import { Entity } from "@latticexyz/recs"; import { Hex, decodeAbiParameters } from "viem"; -import { KeySchema, SchemaToPrimitives } from "@latticexyz/protocol-parser"; import { entityToHexKeyTuple } from "./entityToHexKeyTuple"; +import { KeySchema, SchemaToPrimitives } from "@latticexyz/protocol-parser"; export function decodeEntity( keySchema: TKeySchema, diff --git a/packages/store-sync/src/recs/encodeEntity.ts b/packages/store-sync/src/recs/encodeEntity.ts index e0e155371c..bef8a33c1b 100644 --- a/packages/store-sync/src/recs/encodeEntity.ts +++ b/packages/store-sync/src/recs/encodeEntity.ts @@ -1,7 +1,7 @@ import { Entity } from "@latticexyz/recs"; import { encodeAbiParameters } from "viem"; -import { KeySchema, SchemaToPrimitives } from "@latticexyz/protocol-parser"; import { hexKeyTupleToEntity } from "./hexKeyTupleToEntity"; +import { KeySchema, SchemaToPrimitives } from "@latticexyz/protocol-parser"; export function encodeEntity( keySchema: TKeySchema, diff --git a/packages/store-sync/src/recs/getTableEntity.ts b/packages/store-sync/src/recs/getTableEntity.ts index 83b746e89b..5b92368da3 100644 --- a/packages/store-sync/src/recs/getTableEntity.ts +++ b/packages/store-sync/src/recs/getTableEntity.ts @@ -1,4 +1,4 @@ -import { Address, Hex, getAddress, stringToHex } from "viem"; +import { stringToHex } from "viem"; import { Table } from "../common"; import { Entity } from "@latticexyz/recs"; import { encodeEntity } from "./encodeEntity"; diff --git a/packages/store-sync/src/recs/recsStorage.test.ts b/packages/store-sync/src/recs/recsStorage.test.ts index 3b8e401444..4bb747b0dc 100644 --- a/packages/store-sync/src/recs/recsStorage.test.ts +++ b/packages/store-sync/src/recs/recsStorage.test.ts @@ -1,5 +1,4 @@ import { describe, expect, it } from "vitest"; -import { blockLogsToStorage } from "../blockLogsToStorage"; import { recsStorage } from "./recsStorage"; import { createWorld, getComponentEntities, getComponentValue } from "@latticexyz/recs"; import mudConfig from "../../../../e2e/packages/contracts/mud.config"; @@ -10,15 +9,18 @@ import { singletonEntity } from "./singletonEntity"; import { RpcLog, formatLog, decodeEventLog, Hex } from "viem"; import { storeEventsAbi } from "@latticexyz/store"; -const worldLogs = worldRpcLogs.map((log) => { - const { eventName, args } = decodeEventLog({ - abi: storeEventsAbi, - data: log.data as Hex, - topics: log.topics as [Hex, ...Hex[]], - strict: true, - }); - return formatLog(log as any as RpcLog, { args, eventName: eventName as string }) as StoreEventsLog; -}); +// TODO: make test-data a proper package and export this +const blocks = groupLogsByBlockNumber( + worldRpcLogs.map((log) => { + const { eventName, args } = decodeEventLog({ + abi: storeEventsAbi, + data: log.data as Hex, + topics: log.topics as [Hex, ...Hex[]], + strict: true, + }); + return formatLog(log as any as RpcLog, { args, eventName: eventName as string }) as StoreEventsLog; + }) +); describe("recsStorage", () => { it("creates components", async () => { @@ -33,8 +35,9 @@ describe("recsStorage", () => { const world = createWorld(); const { storageAdapter, components } = recsStorage({ world, config: mudConfig }); - const blocks = groupLogsByBlockNumber(worldLogs); - await Promise.all(blocks.map(async (block) => await blockLogsToStorage(storageAdapter)(block))); + for (const block of blocks) { + await storageAdapter(block); + } expect(Array.from(getComponentEntities(components.NumberList))).toMatchInlineSnapshot(` [ @@ -44,6 +47,9 @@ describe("recsStorage", () => { expect(getComponentValue(components.NumberList, singletonEntity)).toMatchInlineSnapshot(` { + "__dynamicData": "0x000001a400000045", + "__encodedLengths": "0x0000000000000000000000000000000000000000000000000800000000000008", + "__staticData": undefined, "value": [ 420, 69, diff --git a/packages/store-sync/src/recs/recsStorage.ts b/packages/store-sync/src/recs/recsStorage.ts index 9debe2652f..457eb88793 100644 --- a/packages/store-sync/src/recs/recsStorage.ts +++ b/packages/store-sync/src/recs/recsStorage.ts @@ -1,21 +1,16 @@ import { StoreConfig } from "@latticexyz/store"; import { debug } from "./debug"; -import { - ComponentValue, - World as RecsWorld, - getComponentValue, - removeComponent, - setComponent, - updateComponent, -} from "@latticexyz/recs"; -import { isDefined } from "@latticexyz/common/utils"; -import { schemaToDefaults } from "../schemaToDefaults"; +import { World as RecsWorld, getComponentValue, hasComponent, removeComponent, setComponent } from "@latticexyz/recs"; import { defineInternalComponents } from "./defineInternalComponents"; import { getTableEntity } from "./getTableEntity"; +import { hexToTableId, spliceHex } from "@latticexyz/common"; +import { decodeValueArgs } from "@latticexyz/protocol-parser"; +import { Hex } from "viem"; +import { isTableRegistrationLog } from "../isTableRegistrationLog"; +import { logToTable } from "../logToTable"; +import { hexKeyTupleToEntity } from "./hexKeyTupleToEntity"; import { ConfigToRecsComponents } from "./common"; -import { tableIdToHex } from "@latticexyz/common"; -import { encodeEntity } from "./encodeEntity"; -import { StorageAdapter } from "../common"; +import { StorageAdapter, StorageAdapterBlock } from "../common"; import { configToRecsComponents } from "./configToRecsComponents"; import { singletonEntity } from "./singletonEntity"; import storeConfig from "@latticexyz/store/mud.config"; @@ -23,18 +18,18 @@ import worldConfig from "@latticexyz/world/mud.config"; export type RecsStorageOptions = { world: RecsWorld; + // TODO: make config optional? config: TConfig; }; export type RecsStorageAdapter = { - storageAdapter: StorageAdapter; + storageAdapter: StorageAdapter; components: ConfigToRecsComponents & ConfigToRecsComponents & ConfigToRecsComponents & ReturnType; }; -// TODO: make config optional? export function recsStorage({ world, config, @@ -48,63 +43,115 @@ export function recsStorage({ ...defineInternalComponents(world), }; - const storageAdapter = { - async registerTables({ tables }) { - for (const table of tables) { - // TODO: check if table exists already and skip/warn? - setComponent(components.RegisteredTables, getTableEntity(table), { table }); + async function recsStorageAdapter({ logs }: StorageAdapterBlock): Promise { + const newTables = logs.filter(isTableRegistrationLog).map(logToTable); + for (const newTable of newTables) { + const tableEntity = getTableEntity(newTable); + if (hasComponent(components.RegisteredTables, tableEntity)) { + console.warn("table already registered, ignoring", { + newTable, + existingTable: getComponentValue(components.RegisteredTables, tableEntity)?.table, + }); + } else { + setComponent(components.RegisteredTables, tableEntity, { table: newTable }); } - }, - async getTables({ tables }) { - // TODO: fetch schema from RPC if table not found? - return tables - .map((table) => getComponentValue(components.RegisteredTables, getTableEntity(table))?.table) - .filter(isDefined); - }, - async storeOperations({ operations }) { - for (const operation of operations) { - const table = getComponentValue( - components.RegisteredTables, - getTableEntity({ - address: operation.address, - namespace: operation.namespace, - name: operation.name, - }) - )?.table; - if (!table) { - debug(`skipping update for unknown table: ${operation.namespace}:${operation.name} at ${operation.address}`); - continue; - } + } - const tableId = tableIdToHex(operation.namespace, operation.name); - const component = world.components.find((component) => component.id === tableId); - if (!component) { - debug(`skipping update for unknown component: ${tableId}. Available components: ${Object.keys(components)}`); - continue; - } + for (const log of logs) { + const { namespace, name } = hexToTableId(log.args.tableId); + const table = getComponentValue( + components.RegisteredTables, + getTableEntity({ address: log.address, namespace, name }) + )?.table; + if (!table) { + debug(`skipping update for unknown table: ${namespace}:${name} at ${log.address}`); + continue; + } + + const component = world.components.find((c) => c.id === table.tableId); + if (!component) { + debug( + `skipping update for unknown component: ${table.tableId} (${table.namespace}:${ + table.name + }). Available components: ${Object.keys(components)}` + ); + continue; + } - const entity = encodeEntity(table.keySchema, operation.key); + const entity = hexKeyTupleToEntity(log.args.keyTuple); - if (operation.type === "SetRecord") { - debug("setting component", tableId, entity, operation.value); - setComponent(component, entity, operation.value as ComponentValue); - } else if (operation.type === "SetField") { - debug("updating component", tableId, entity, { - [operation.fieldName]: operation.fieldValue, - }); - updateComponent( - component, - entity, - { [operation.fieldName]: operation.fieldValue } as ComponentValue, - schemaToDefaults(table.valueSchema) as ComponentValue - ); - } else if (operation.type === "DeleteRecord") { - debug("deleting component", tableId, entity); - removeComponent(component, entity); - } + if (log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord") { + const value = decodeValueArgs(table.valueSchema, log.args); + debug("setting component", { + namespace: table.namespace, + name: table.name, + entity, + value, + }); + setComponent(component, entity, { + ...value, + __staticData: log.args.staticData, + __encodedLengths: log.args.encodedLengths, + __dynamicData: log.args.dynamicData, + }); + } else if (log.eventName === "StoreSpliceStaticData") { + // TODO: add tests that this works when no record had been set before + const previousValue = getComponentValue(component, entity); + const previousStaticData = (previousValue?.__staticData as Hex) ?? "0x"; + const newStaticData = spliceHex(previousStaticData, log.args.start, log.args.deleteCount, log.args.data); + const newValue = decodeValueArgs(table.valueSchema, { + staticData: newStaticData, + encodedLengths: (previousValue?.__encodedLengths as Hex) ?? "0x", + dynamicData: (previousValue?.__dynamicData as Hex) ?? "0x", + }); + debug("setting component via splice static", { + namespace: table.namespace, + name: table.name, + entity, + previousStaticData, + newStaticData, + previousValue, + newValue, + }); + setComponent(component, entity, { + ...newValue, + __staticData: newStaticData, + }); + } else if (log.eventName === "StoreSpliceDynamicData") { + // TODO: add tests that this works when no record had been set before + const previousValue = getComponentValue(component, entity); + const previousDynamicData = (previousValue?.__dynamicData as Hex) ?? "0x"; + const newDynamicData = spliceHex(previousDynamicData, log.args.start, log.args.deleteCount, log.args.data); + const newValue = decodeValueArgs(table.valueSchema, { + staticData: (previousValue?.__staticData as Hex) ?? "0x", + // TODO: handle unchanged encoded lengths + encodedLengths: log.args.encodedLengths, + dynamicData: newDynamicData, + }); + debug("setting component via splice dynamic", { + namespace: table.namespace, + name: table.name, + entity, + previousDynamicData, + newDynamicData, + previousValue, + newValue, + }); + setComponent(component, entity, { + ...newValue, + __encodedLengths: log.args.encodedLengths, + __dynamicData: newDynamicData, + }); + } else if (log.eventName === "StoreDeleteRecord") { + debug("deleting component", { + namespace: table.namespace, + name: table.name, + entity, + }); + removeComponent(component, entity); } - }, - } as StorageAdapter; + } + } - return { storageAdapter, components }; + return { storageAdapter: recsStorageAdapter, components }; } diff --git a/packages/store-sync/src/recs/syncToRecs.ts b/packages/store-sync/src/recs/syncToRecs.ts index aecf0231ec..2d439e0512 100644 --- a/packages/store-sync/src/recs/syncToRecs.ts +++ b/packages/store-sync/src/recs/syncToRecs.ts @@ -12,7 +12,7 @@ type SyncToRecsOptions = SyncOptions< startSync?: boolean; }; -type SyncToRecsResult = SyncResult & { +type SyncToRecsResult = SyncResult & { components: RecsStorageAdapter["components"]; stopSync: () => void; }; @@ -52,7 +52,7 @@ export async function syncToRecs({ }, }); - const sub = startSync ? storeSync.blockStorageOperations$.subscribe() : null; + const sub = startSync ? storeSync.storedBlockLogs$.subscribe() : null; const stopSync = (): void => { sub?.unsubscribe(); }; diff --git a/packages/store-sync/src/schemaToDefaults.ts b/packages/store-sync/src/schemaToDefaults.ts index 15be27c54c..278b4c77c7 100644 --- a/packages/store-sync/src/schemaToDefaults.ts +++ b/packages/store-sync/src/schemaToDefaults.ts @@ -1,5 +1,5 @@ +import { SchemaToPrimitives, ValueSchema } from "@latticexyz/protocol-parser"; import { schemaAbiTypeToDefaultValue } from "@latticexyz/schema-type"; -import { ValueSchema, SchemaToPrimitives } from "@latticexyz/protocol-parser"; export function schemaToDefaults(valueSchema: TSchema): SchemaToPrimitives { return Object.fromEntries( diff --git a/packages/store-sync/src/sqlite/buildSqliteColumn.ts b/packages/store-sync/src/sqlite/buildColumn.ts similarity index 95% rename from packages/store-sync/src/sqlite/buildSqliteColumn.ts rename to packages/store-sync/src/sqlite/buildColumn.ts index f4e07e73cf..354600b146 100644 --- a/packages/store-sync/src/sqlite/buildSqliteColumn.ts +++ b/packages/store-sync/src/sqlite/buildColumn.ts @@ -1,9 +1,10 @@ -import { AnySQLiteColumnBuilder, blob, integer, text } from "drizzle-orm/sqlite-core"; +import { blob, integer, text } from "drizzle-orm/sqlite-core"; import { SchemaAbiType } from "@latticexyz/schema-type"; import { assertExhaustive } from "@latticexyz/common/utils"; import { address, json } from "./columnTypes"; -export function buildSqliteColumn(name: string, schemaAbiType: SchemaAbiType): AnySQLiteColumnBuilder { +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export function buildColumn(name: string, schemaAbiType: SchemaAbiType) { switch (schemaAbiType) { case "bool": return integer(name, { mode: "boolean" }); diff --git a/packages/store-sync/src/sqlite/buildTable.test.ts b/packages/store-sync/src/sqlite/buildTable.test.ts new file mode 100644 index 0000000000..22b1eb0a42 --- /dev/null +++ b/packages/store-sync/src/sqlite/buildTable.test.ts @@ -0,0 +1,1086 @@ +import { describe, it, expect } from "vitest"; +import { buildTable } from "./buildTable"; + +describe("buildTable", () => { + it("should create table from schema", async () => { + const table = buildTable({ + address: "0xffffffffffffffffffffffffffffffffffffffff", + namespace: "test", + name: "users", + keySchema: { x: "uint32", y: "uint32" }, + valueSchema: { name: "string", addr: "address" }, + }); + + expect(table).toMatchInlineSnapshot(` + SQLiteTable { + "__dynamicData": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__dynamicData", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___dynamicData_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__dynamicData", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___dynamicData_unique", + "uniqueType": undefined, + }, + "__encodedLengths": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__encodedLengths", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___encodedLengths_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__encodedLengths", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___encodedLengths_unique", + "uniqueType": undefined, + }, + "__isDeleted": SQLiteBoolean { + "autoIncrement": false, + "columnType": "SQLiteBoolean", + "config": { + "autoIncrement": false, + "columnType": "SQLiteBoolean", + "dataType": "boolean", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___isDeleted_unique", + "uniqueType": undefined, + }, + "dataType": "boolean", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___isDeleted_unique", + "uniqueType": undefined, + }, + "__key": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__key", + "notNull": true, + "primaryKey": true, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___key_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__key", + "notNull": true, + "primary": true, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___key_unique", + "uniqueType": undefined, + }, + "__lastUpdatedBlockNumber": SQLiteBigInt { + "columnType": "SQLiteBigInt", + "config": { + "columnType": "SQLiteBigInt", + "dataType": "bigint", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "dataType": "bigint", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "__staticData": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__staticData", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___staticData_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__staticData", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___staticData_unique", + "uniqueType": undefined, + }, + "addr": SQLiteCustomColumn { + "columnType": "SQLiteCustomColumn", + "config": { + "columnType": "SQLiteCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "addr", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_addr_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "addr", + "notNull": true, + "primary": false, + "sqlName": "text", + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_addr_unique", + "uniqueType": undefined, + }, + "name": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "name", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_name_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "name", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_name_unique", + "uniqueType": undefined, + }, + "x": SQLiteInteger { + "autoIncrement": false, + "columnType": "SQLiteInteger", + "config": { + "autoIncrement": false, + "columnType": "SQLiteInteger", + "dataType": "number", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "name": "x", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_x_unique", + "uniqueType": undefined, + }, + "dataType": "number", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "name": "x", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_x_unique", + "uniqueType": undefined, + }, + "y": SQLiteInteger { + "autoIncrement": false, + "columnType": "SQLiteInteger", + "config": { + "autoIncrement": false, + "columnType": "SQLiteInteger", + "dataType": "number", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "name": "y", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_y_unique", + "uniqueType": undefined, + }, + "dataType": "number", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "name": "y", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_y_unique", + "uniqueType": undefined, + }, + Symbol(drizzle:Name): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:OriginalName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:Schema): undefined, + Symbol(drizzle:Columns): { + "__dynamicData": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__dynamicData", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___dynamicData_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__dynamicData", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___dynamicData_unique", + "uniqueType": undefined, + }, + "__encodedLengths": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__encodedLengths", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___encodedLengths_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__encodedLengths", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___encodedLengths_unique", + "uniqueType": undefined, + }, + "__isDeleted": SQLiteBoolean { + "autoIncrement": false, + "columnType": "SQLiteBoolean", + "config": { + "autoIncrement": false, + "columnType": "SQLiteBoolean", + "dataType": "boolean", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___isDeleted_unique", + "uniqueType": undefined, + }, + "dataType": "boolean", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___isDeleted_unique", + "uniqueType": undefined, + }, + "__key": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__key", + "notNull": true, + "primaryKey": true, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___key_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__key", + "notNull": true, + "primary": true, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___key_unique", + "uniqueType": undefined, + }, + "__lastUpdatedBlockNumber": SQLiteBigInt { + "columnType": "SQLiteBigInt", + "config": { + "columnType": "SQLiteBigInt", + "dataType": "bigint", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "dataType": "bigint", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "__staticData": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__staticData", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___staticData_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__staticData", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___staticData_unique", + "uniqueType": undefined, + }, + "addr": SQLiteCustomColumn { + "columnType": "SQLiteCustomColumn", + "config": { + "columnType": "SQLiteCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "addr", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_addr_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "addr", + "notNull": true, + "primary": false, + "sqlName": "text", + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_addr_unique", + "uniqueType": undefined, + }, + "name": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "name", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_name_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "name", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_name_unique", + "uniqueType": undefined, + }, + "x": SQLiteInteger { + "autoIncrement": false, + "columnType": "SQLiteInteger", + "config": { + "autoIncrement": false, + "columnType": "SQLiteInteger", + "dataType": "number", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "name": "x", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_x_unique", + "uniqueType": undefined, + }, + "dataType": "number", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "name": "x", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_x_unique", + "uniqueType": undefined, + }, + "y": SQLiteInteger { + "autoIncrement": false, + "columnType": "SQLiteInteger", + "config": { + "autoIncrement": false, + "columnType": "SQLiteInteger", + "dataType": "number", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "name": "y", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_y_unique", + "uniqueType": undefined, + }, + "dataType": "number", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "name": "y", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_y_unique", + "uniqueType": undefined, + }, + }, + Symbol(drizzle:BaseName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:IsAlias): false, + Symbol(drizzle:ExtraConfigBuilder): undefined, + Symbol(drizzle:IsDrizzleTable): true, + Symbol(drizzle:SQLiteInlineForeignKeys): [], + } + `); + }); + + it("can create a singleton table", async () => { + const table = buildTable({ + address: "0xffffffffffffffffffffffffffffffffffffffff", + namespace: "test", + name: "users", + keySchema: {}, + valueSchema: { addrs: "address[]" }, + }); + + expect(table).toMatchInlineSnapshot(` + SQLiteTable { + "__dynamicData": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__dynamicData", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___dynamicData_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__dynamicData", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___dynamicData_unique", + "uniqueType": undefined, + }, + "__encodedLengths": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__encodedLengths", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___encodedLengths_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__encodedLengths", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___encodedLengths_unique", + "uniqueType": undefined, + }, + "__isDeleted": SQLiteBoolean { + "autoIncrement": false, + "columnType": "SQLiteBoolean", + "config": { + "autoIncrement": false, + "columnType": "SQLiteBoolean", + "dataType": "boolean", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___isDeleted_unique", + "uniqueType": undefined, + }, + "dataType": "boolean", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___isDeleted_unique", + "uniqueType": undefined, + }, + "__key": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__key", + "notNull": true, + "primaryKey": true, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___key_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__key", + "notNull": true, + "primary": true, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___key_unique", + "uniqueType": undefined, + }, + "__lastUpdatedBlockNumber": SQLiteBigInt { + "columnType": "SQLiteBigInt", + "config": { + "columnType": "SQLiteBigInt", + "dataType": "bigint", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "dataType": "bigint", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "__staticData": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__staticData", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___staticData_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__staticData", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___staticData_unique", + "uniqueType": undefined, + }, + "addrs": SQLiteCustomColumn { + "columnType": "SQLiteCustomColumn", + "config": { + "columnType": "SQLiteCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "addrs", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_addrs_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "addrs", + "notNull": true, + "primary": false, + "sqlName": "text", + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_addrs_unique", + "uniqueType": undefined, + }, + Symbol(drizzle:Name): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:OriginalName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:Schema): undefined, + Symbol(drizzle:Columns): { + "__dynamicData": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__dynamicData", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___dynamicData_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__dynamicData", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___dynamicData_unique", + "uniqueType": undefined, + }, + "__encodedLengths": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__encodedLengths", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___encodedLengths_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__encodedLengths", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___encodedLengths_unique", + "uniqueType": undefined, + }, + "__isDeleted": SQLiteBoolean { + "autoIncrement": false, + "columnType": "SQLiteBoolean", + "config": { + "autoIncrement": false, + "columnType": "SQLiteBoolean", + "dataType": "boolean", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___isDeleted_unique", + "uniqueType": undefined, + }, + "dataType": "boolean", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___isDeleted_unique", + "uniqueType": undefined, + }, + "__key": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__key", + "notNull": true, + "primaryKey": true, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___key_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__key", + "notNull": true, + "primary": true, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___key_unique", + "uniqueType": undefined, + }, + "__lastUpdatedBlockNumber": SQLiteBigInt { + "columnType": "SQLiteBigInt", + "config": { + "columnType": "SQLiteBigInt", + "dataType": "bigint", + "default": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "dataType": "bigint", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___lastUpdatedBlockNumber_unique", + "uniqueType": undefined, + }, + "__staticData": SQLiteText { + "columnType": "SQLiteText", + "config": { + "columnType": "SQLiteText", + "dataType": "string", + "default": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__staticData", + "notNull": false, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___staticData_unique", + "uniqueType": undefined, + }, + "dataType": "string", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "length": undefined, + "name": "__staticData", + "notNull": false, + "primary": false, + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users___staticData_unique", + "uniqueType": undefined, + }, + "addrs": SQLiteCustomColumn { + "columnType": "SQLiteCustomColumn", + "config": { + "columnType": "SQLiteCustomColumn", + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "dataType": "custom", + "default": undefined, + "fieldConfig": undefined, + "hasDefault": false, + "isUnique": false, + "name": "addrs", + "notNull": true, + "primaryKey": false, + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_addrs_unique", + "uniqueType": undefined, + }, + "dataType": "custom", + "default": undefined, + "defaultFn": undefined, + "enumValues": undefined, + "hasDefault": false, + "isUnique": false, + "mapFrom": [Function], + "mapTo": [Function], + "name": "addrs", + "notNull": true, + "primary": false, + "sqlName": "text", + "table": [Circular], + "uniqueName": "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users_addrs_unique", + "uniqueType": undefined, + }, + }, + Symbol(drizzle:BaseName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:IsAlias): false, + Symbol(drizzle:ExtraConfigBuilder): undefined, + Symbol(drizzle:IsDrizzleTable): true, + Symbol(drizzle:SQLiteInlineForeignKeys): [], + } + `); + }); +}); diff --git a/packages/store-sync/src/sqlite/createSqliteTable.ts b/packages/store-sync/src/sqlite/buildTable.ts similarity index 70% rename from packages/store-sync/src/sqlite/createSqliteTable.ts rename to packages/store-sync/src/sqlite/buildTable.ts index e8e8667b7d..2b9b0efd5c 100644 --- a/packages/store-sync/src/sqlite/createSqliteTable.ts +++ b/packages/store-sync/src/sqlite/buildTable.ts @@ -1,17 +1,21 @@ -import { AnySQLiteColumnBuilder, SQLiteTableWithColumns, sqliteTable } from "drizzle-orm/sqlite-core"; -import { buildSqliteColumn } from "./buildSqliteColumn"; +import { SQLiteColumnBuilderBase, SQLiteTableWithColumns, sqliteTable } from "drizzle-orm/sqlite-core"; +import { buildColumn } from "./buildColumn"; import { Address } from "viem"; import { getTableName } from "./getTableName"; import { KeySchema, ValueSchema } from "@latticexyz/protocol-parser"; export const metaColumns = { - __key: buildSqliteColumn("__key", "bytes").notNull().primaryKey(), - __lastUpdatedBlockNumber: buildSqliteColumn("__lastUpdatedBlockNumber", "uint256").notNull(), + __key: buildColumn("__key", "bytes").primaryKey(), + __staticData: buildColumn("__staticData", "bytes"), + __encodedLengths: buildColumn("__encodedLengths", "bytes"), + __dynamicData: buildColumn("__dynamicData", "bytes"), + __lastUpdatedBlockNumber: buildColumn("__lastUpdatedBlockNumber", "uint256").notNull(), // TODO: last updated block hash? - __isDeleted: buildSqliteColumn("__isDeleted", "bool").notNull(), -} as const satisfies Record; + __isDeleted: buildColumn("__isDeleted", "bool").notNull(), +} as const satisfies Record; type SQLiteTableFromSchema = SQLiteTableWithColumns<{ + dialect: "sqlite"; name: string; schema: string | undefined; columns: { @@ -39,7 +43,7 @@ type CreateSqliteTableResult; -export function createSqliteTable({ +export function buildTable({ address, namespace, name, @@ -49,11 +53,11 @@ export function createSqliteTable [name, buildSqliteColumn(name, type).notNull()]) + Object.entries(keySchema).map(([name, type]) => [name, buildColumn(name, type).notNull()]) ); const valueColumns = Object.fromEntries( - Object.entries(valueSchema).map(([name, type]) => [name, buildSqliteColumn(name, type).notNull()]) + Object.entries(valueSchema).map(([name, type]) => [name, buildColumn(name, type).notNull()]) ); // TODO: unique constraint on key columns? diff --git a/packages/store-sync/src/sqlite/columnTypes.ts b/packages/store-sync/src/sqlite/columnTypes.ts index dc23a26f5c..3dd4c07e9f 100644 --- a/packages/store-sync/src/sqlite/columnTypes.ts +++ b/packages/store-sync/src/sqlite/columnTypes.ts @@ -1,9 +1,9 @@ -import { customType, SQLiteCustomColumnBuilder } from "drizzle-orm/sqlite-core"; -import { ColumnBuilderBaseConfig } from "drizzle-orm"; +import { customType } from "drizzle-orm/sqlite-core"; import superjson from "superjson"; import { Address, getAddress } from "viem"; -export const json = (name: string): SQLiteCustomColumnBuilder => +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export const json = (name: string) => customType<{ data: TData; driverData: string }>({ dataType() { return "text"; @@ -16,7 +16,8 @@ export const json = (name: string): SQLiteCustomColumnBuilder => +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export const address = (name: string) => customType<{ data: Address; driverData: string }>({ dataType() { return "text"; diff --git a/packages/store-sync/src/sqlite/createSqliteTable.test.ts b/packages/store-sync/src/sqlite/createSqliteTable.test.ts deleted file mode 100644 index 756055c09d..0000000000 --- a/packages/store-sync/src/sqlite/createSqliteTable.test.ts +++ /dev/null @@ -1,446 +0,0 @@ -import { describe, it, expect } from "vitest"; -import { createSqliteTable } from "./createSqliteTable"; - -describe("createSqliteTable", () => { - it("should create table from schema", async () => { - const table = createSqliteTable({ - address: "0xffffffffffffffffffffffffffffffffffffffff", - namespace: "test", - name: "users", - keySchema: { x: "uint32", y: "uint32" }, - valueSchema: { name: "string", addr: "address" }, - }); - - expect(table).toMatchInlineSnapshot(` - SQLiteTable { - "__isDeleted": SQLiteBoolean { - "autoIncrement": false, - "config": { - "autoIncrement": false, - "default": undefined, - "mode": "boolean", - "name": "__isDeleted", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "mode": "boolean", - "name": "__isDeleted", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "__key": SQLiteText { - "config": { - "default": undefined, - "enumValues": [], - "length": undefined, - "name": "__key", - "notNull": true, - "primaryKey": true, - }, - "default": undefined, - "enumValues": [], - "hasDefault": undefined, - "length": undefined, - "name": "__key", - "notNull": true, - "primary": true, - "table": [Circular], - }, - "__lastUpdatedBlockNumber": SQLiteBigInt { - "config": { - "default": undefined, - "name": "__lastUpdatedBlockNumber", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "name": "__lastUpdatedBlockNumber", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "addr": SQLiteCustomColumn { - "config": { - "customTypeParams": { - "dataType": [Function], - "fromDriver": [Function], - "toDriver": [Function], - }, - "default": undefined, - "fieldConfig": undefined, - "name": "addr", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "mapFrom": [Function], - "mapTo": [Function], - "name": "addr", - "notNull": true, - "primary": false, - "sqlName": "text", - "table": [Circular], - }, - "name": SQLiteText { - "config": { - "default": undefined, - "enumValues": [], - "length": undefined, - "name": "name", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "enumValues": [], - "hasDefault": undefined, - "length": undefined, - "name": "name", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "x": SQLiteInteger { - "autoIncrement": false, - "config": { - "autoIncrement": false, - "default": undefined, - "name": "x", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "name": "x", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "y": SQLiteInteger { - "autoIncrement": false, - "config": { - "autoIncrement": false, - "default": undefined, - "name": "y", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "name": "y", - "notNull": true, - "primary": false, - "table": [Circular], - }, - Symbol(drizzle:Name): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", - Symbol(drizzle:OriginalName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", - Symbol(drizzle:Schema): undefined, - Symbol(drizzle:Columns): { - "__isDeleted": SQLiteBoolean { - "autoIncrement": false, - "config": { - "autoIncrement": false, - "default": undefined, - "mode": "boolean", - "name": "__isDeleted", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "mode": "boolean", - "name": "__isDeleted", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "__key": SQLiteText { - "config": { - "default": undefined, - "enumValues": [], - "length": undefined, - "name": "__key", - "notNull": true, - "primaryKey": true, - }, - "default": undefined, - "enumValues": [], - "hasDefault": undefined, - "length": undefined, - "name": "__key", - "notNull": true, - "primary": true, - "table": [Circular], - }, - "__lastUpdatedBlockNumber": SQLiteBigInt { - "config": { - "default": undefined, - "name": "__lastUpdatedBlockNumber", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "name": "__lastUpdatedBlockNumber", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "addr": SQLiteCustomColumn { - "config": { - "customTypeParams": { - "dataType": [Function], - "fromDriver": [Function], - "toDriver": [Function], - }, - "default": undefined, - "fieldConfig": undefined, - "name": "addr", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "mapFrom": [Function], - "mapTo": [Function], - "name": "addr", - "notNull": true, - "primary": false, - "sqlName": "text", - "table": [Circular], - }, - "name": SQLiteText { - "config": { - "default": undefined, - "enumValues": [], - "length": undefined, - "name": "name", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "enumValues": [], - "hasDefault": undefined, - "length": undefined, - "name": "name", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "x": SQLiteInteger { - "autoIncrement": false, - "config": { - "autoIncrement": false, - "default": undefined, - "name": "x", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "name": "x", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "y": SQLiteInteger { - "autoIncrement": false, - "config": { - "autoIncrement": false, - "default": undefined, - "name": "y", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "name": "y", - "notNull": true, - "primary": false, - "table": [Circular], - }, - }, - Symbol(drizzle:BaseName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", - Symbol(drizzle:IsAlias): false, - Symbol(drizzle:ExtraConfigBuilder): undefined, - Symbol(drizzle:IsDrizzleTable): true, - Symbol(drizzle:SQLiteInlineForeignKeys): [], - } - `); - }); - - it("can create a singleton table", async () => { - const table = createSqliteTable({ - address: "0xffffffffffffffffffffffffffffffffffffffff", - namespace: "test", - name: "users", - keySchema: {}, - valueSchema: { addrs: "address[]" }, - }); - - expect(table).toMatchInlineSnapshot(` - SQLiteTable { - "__isDeleted": SQLiteBoolean { - "autoIncrement": false, - "config": { - "autoIncrement": false, - "default": undefined, - "mode": "boolean", - "name": "__isDeleted", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "mode": "boolean", - "name": "__isDeleted", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "__key": SQLiteText { - "config": { - "default": undefined, - "enumValues": [], - "length": undefined, - "name": "__key", - "notNull": true, - "primaryKey": true, - }, - "default": undefined, - "enumValues": [], - "hasDefault": undefined, - "length": undefined, - "name": "__key", - "notNull": true, - "primary": true, - "table": [Circular], - }, - "__lastUpdatedBlockNumber": SQLiteBigInt { - "config": { - "default": undefined, - "name": "__lastUpdatedBlockNumber", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "name": "__lastUpdatedBlockNumber", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "addrs": SQLiteCustomColumn { - "config": { - "customTypeParams": { - "dataType": [Function], - "fromDriver": [Function], - "toDriver": [Function], - }, - "default": undefined, - "fieldConfig": undefined, - "name": "addrs", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "mapFrom": [Function], - "mapTo": [Function], - "name": "addrs", - "notNull": true, - "primary": false, - "sqlName": "text", - "table": [Circular], - }, - Symbol(drizzle:Name): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", - Symbol(drizzle:OriginalName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", - Symbol(drizzle:Schema): undefined, - Symbol(drizzle:Columns): { - "__isDeleted": SQLiteBoolean { - "autoIncrement": false, - "config": { - "autoIncrement": false, - "default": undefined, - "mode": "boolean", - "name": "__isDeleted", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "mode": "boolean", - "name": "__isDeleted", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "__key": SQLiteText { - "config": { - "default": undefined, - "enumValues": [], - "length": undefined, - "name": "__key", - "notNull": true, - "primaryKey": true, - }, - "default": undefined, - "enumValues": [], - "hasDefault": undefined, - "length": undefined, - "name": "__key", - "notNull": true, - "primary": true, - "table": [Circular], - }, - "__lastUpdatedBlockNumber": SQLiteBigInt { - "config": { - "default": undefined, - "name": "__lastUpdatedBlockNumber", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "name": "__lastUpdatedBlockNumber", - "notNull": true, - "primary": false, - "table": [Circular], - }, - "addrs": SQLiteCustomColumn { - "config": { - "customTypeParams": { - "dataType": [Function], - "fromDriver": [Function], - "toDriver": [Function], - }, - "default": undefined, - "fieldConfig": undefined, - "name": "addrs", - "notNull": true, - "primaryKey": false, - }, - "default": undefined, - "hasDefault": undefined, - "mapFrom": [Function], - "mapTo": [Function], - "name": "addrs", - "notNull": true, - "primary": false, - "sqlName": "text", - "table": [Circular], - }, - }, - Symbol(drizzle:BaseName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", - Symbol(drizzle:IsAlias): false, - Symbol(drizzle:ExtraConfigBuilder): undefined, - Symbol(drizzle:IsDrizzleTable): true, - Symbol(drizzle:SQLiteInlineForeignKeys): [], - } - `); - }); -}); diff --git a/packages/store-sync/src/sqlite/getTables.ts b/packages/store-sync/src/sqlite/getTables.ts index 6d1a4f4d03..9a99afacbf 100644 --- a/packages/store-sync/src/sqlite/getTables.ts +++ b/packages/store-sync/src/sqlite/getTables.ts @@ -1,9 +1,9 @@ import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; import { inArray } from "drizzle-orm"; import { Table } from "../common"; -import { TableId } from "@latticexyz/common/deprecated"; import { getTableName } from "./getTableName"; import { mudStoreTables } from "./internalTables"; +import { tableIdToHex } from "@latticexyz/common"; export function getTables( db: BaseSQLiteDatabase<"sync", void>, @@ -19,7 +19,7 @@ export function getTables( .all(); return tables.map((table) => { - const tableId = new TableId(table.namespace, table.name).toHex(); + const tableId = tableIdToHex(table.namespace, table.name); return { id: getTableName(table.address, table.namespace, table.name), address: table.address, diff --git a/packages/store-sync/src/sqlite/index.ts b/packages/store-sync/src/sqlite/index.ts index bcfd3948ad..8e6b2acd2e 100644 --- a/packages/store-sync/src/sqlite/index.ts +++ b/packages/store-sync/src/sqlite/index.ts @@ -1,4 +1,4 @@ -export * from "./createSqliteTable"; +export * from "./buildTable"; export * from "./getTables"; export * from "./internalTables"; export * from "./schemaVersion"; diff --git a/packages/store-sync/src/sqlite/sqliteStorage.test.ts b/packages/store-sync/src/sqlite/sqliteStorage.test.ts index 414c104b25..2834fa73eb 100644 --- a/packages/store-sync/src/sqlite/sqliteStorage.test.ts +++ b/packages/store-sync/src/sqlite/sqliteStorage.test.ts @@ -3,13 +3,29 @@ import { sqliteStorage } from "./sqliteStorage"; import { getTables } from "./getTables"; import { chainState, mudStoreTables } from "./internalTables"; import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; -import { createSqliteTable } from "./createSqliteTable"; +import { buildTable } from "./buildTable"; import initSqlJs from "sql.js"; import { drizzle } from "drizzle-orm/sql-js"; -import { createPublicClient, http } from "viem"; +import { Hex, RpcLog, createPublicClient, decodeEventLog, formatLog, http } from "viem"; import { foundry } from "viem/chains"; -import { blockLogsToStorage } from "../blockLogsToStorage"; +import worldRpcLogs from "../../../../test-data/world-logs.json"; +import { storeEventsAbi } from "@latticexyz/store"; import { StoreEventsLog } from "../common"; +import { groupLogsByBlockNumber } from "@latticexyz/block-logs-stream"; +import { eq } from "drizzle-orm"; + +// TODO: make test-data a proper package and export this +const blocks = groupLogsByBlockNumber( + worldRpcLogs.map((log) => { + const { eventName, args } = decodeEventLog({ + abi: storeEventsAbi, + data: log.data as Hex, + topics: log.topics as [Hex, ...Hex[]], + strict: true, + }); + return formatLog(log as any as RpcLog, { args, eventName: eventName as string }) as StoreEventsLog; + }) +); describe("sqliteStorage", async () => { const SqlJs = await initSqlJs(); @@ -39,104 +55,74 @@ describe("sqliteStorage", async () => { expect(db.select().from(chainState).all()).toMatchInlineSnapshot("[]"); expect(db.select().from(mudStoreTables).all()).toMatchInlineSnapshot("[]"); - await blockLogsToStorage(storageAdapter)({ - blockNumber: 5448n, - logs: [ - { - address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", - topics: ["0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46"], - data: "0x000000000000000000000000000000005265736f7572636554797065000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e76656e746f72790000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - blockHash: "0x4ad3752c86f900332e0d2d8903480e7206747d233586574d16f006eebdb5138b", - blockNumber: 2n, - transactionHash: "0xaa54bf18053cce5d4d2906538a60cb1d9958cc3c10c34b5f9fdc92fe6a6abab4", - transactionIndex: 16, - logIndex: 54, - removed: false, - args: { - tableId: "0x000000000000000000000000000000005265736f757263655479706500000000", - keyTuple: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"], - schemaIndex: 0, - data: "0x02", - }, - eventName: "StoreSetField", - }, - { - address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", - topics: ["0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32"], - data: "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e76656e746f72790000000000000000000000000000000000000000000000000000000000000000000000000002800004010004000000000000000000000000000000000000000000000000000000001c030061030300000000000000000000000000000000000000000000000000000401000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000001600000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000056f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046974656d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6974656d56617269616e740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006616d6f756e740000000000000000000000000000000000000000000000000000", - blockHash: "0x4ad3752c86f900332e0d2d8903480e7206747d233586574d16f006eebdb5138b", - blockNumber: 2n, - transactionHash: "0xaa54bf18053cce5d4d2906538a60cb1d9958cc3c10c34b5f9fdc92fe6a6abab4", - transactionIndex: 16, - logIndex: 55, - removed: false, - args: { - tableId: "0x6d756473746f726500000000000000005461626c657300000000000000000000", - keyTuple: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"], - data: "0x0004010004000000000000000000000000000000000000000000000000000000001c030061030300000000000000000000000000000000000000000000000000000401000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000001600000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000056f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046974656d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6974656d56617269616e740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006616d6f756e740000000000000000000000000000000000000000000000000000", - }, - eventName: "StoreSetRecord", - }, - ] satisfies StoreEventsLog[], - }); + for (const block of blocks) { + await storageAdapter(block); + } expect(db.select().from(chainState).all()).toMatchInlineSnapshot(` [ { "chainId": 31337, "lastError": null, - "lastUpdatedBlockNumber": 5448n, + "lastUpdatedBlockNumber": 6n, "schemaVersion": 1, }, ] `); - expect(db.select().from(mudStoreTables).all()).toMatchInlineSnapshot(` + expect(db.select().from(mudStoreTables).where(eq(mudStoreTables.name, "NumberList")).all()).toMatchInlineSnapshot(` [ { "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", - "id": "0x5FbDB2315678afecb367f032d93F642f64180aa3____Inventory", - "keySchema": { - "item": "uint32", - "itemVariant": "uint32", - "owner": "address", - }, + "id": "0x5FbDB2315678afecb367f032d93F642f64180aa3____NumberList", + "keySchema": {}, "lastError": null, - "lastUpdatedBlockNumber": 5448n, - "name": "Inventory", + "lastUpdatedBlockNumber": 6n, + "name": "NumberList", "namespace": "", "schemaVersion": 1, - "tableId": "0x00000000000000000000000000000000496e76656e746f727900000000000000", + "tableId": "0x000000000000000000000000000000004e756d6265724c697374000000000000", "valueSchema": { - "amount": "uint32", + "value": "uint32[]", }, }, ] `); - const tables = getTables(db); + const tables = getTables(db).filter((table) => table.name === "NumberList"); expect(tables).toMatchInlineSnapshot(` [ { "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", - "id": "0x5FbDB2315678afecb367f032d93F642f64180aa3____Inventory", - "keySchema": { - "item": "uint32", - "itemVariant": "uint32", - "owner": "address", - }, - "lastUpdatedBlockNumber": 5448n, - "name": "Inventory", + "id": "0x5FbDB2315678afecb367f032d93F642f64180aa3____NumberList", + "keySchema": {}, + "lastUpdatedBlockNumber": 6n, + "name": "NumberList", "namespace": "", - "tableId": "0x00000000000000000000000000000000496e76656e746f727900000000000000", + "tableId": "0x000000000000000000000000000000004e756d6265724c697374000000000000", "valueSchema": { - "amount": "uint32", + "value": "uint32[]", }, }, ] `); - const sqliteTable = createSqliteTable(tables[0]); - expect(db.select().from(sqliteTable).all()).toMatchInlineSnapshot("[]"); + const sqlTable = buildTable(tables[0]); + expect(db.select().from(sqlTable).all()).toMatchInlineSnapshot(` + [ + { + "__dynamicData": "0x000001a400000045", + "__encodedLengths": "0x0000000000000000000000000000000000000000000000000800000000000008", + "__isDeleted": false, + "__key": "0x", + "__lastUpdatedBlockNumber": 6n, + "__staticData": null, + "value": [ + 420, + 69, + ], + }, + ] + `); }); }); diff --git a/packages/store-sync/src/sqlite/sqliteStorage.ts b/packages/store-sync/src/sqlite/sqliteStorage.ts index fb2073b11c..08ca78f547 100644 --- a/packages/store-sync/src/sqlite/sqliteStorage.ts +++ b/packages/store-sync/src/sqlite/sqliteStorage.ts @@ -1,10 +1,8 @@ -import { PublicClient, concatHex, encodeAbiParameters, getAddress } from "viem"; +import { Hex, PublicClient, concatHex, getAddress } from "viem"; import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; import { and, eq, sql } from "drizzle-orm"; import { sqliteTableToSql } from "./sqliteTableToSql"; -import { createSqliteTable } from "./createSqliteTable"; -import { schemaToDefaults } from "../schemaToDefaults"; -import { TableId } from "@latticexyz/common/deprecated"; +import { buildTable } from "./buildTable"; import { StoreConfig } from "@latticexyz/store"; import { debug } from "./debug"; import { getTableName } from "./getTableName"; @@ -12,6 +10,12 @@ import { chainState, mudStoreTables } from "./internalTables"; import { getTables } from "./getTables"; import { schemaVersion } from "./schemaVersion"; import { StorageAdapter } from "../common"; +import { isTableRegistrationLog } from "../isTableRegistrationLog"; +import { logToTable } from "../logToTable"; +import { hexToTableId, spliceHex, tableIdToHex } from "@latticexyz/common"; +import { decodeKey, decodeValueArgs } from "@latticexyz/protocol-parser"; + +// TODO: upgrade drizzle and use async sqlite interface for consistency export async function sqliteStorage({ database, @@ -20,170 +24,230 @@ export async function sqliteStorage({ database: BaseSQLiteDatabase<"sync", void>; publicClient: PublicClient; config?: TConfig; -}): Promise> { +}): Promise { const chainId = publicClient.chain?.id ?? (await publicClient.getChainId()); // TODO: should these run lazily before first `registerTables`? database.run(sql.raw(sqliteTableToSql(chainState))); database.run(sql.raw(sqliteTableToSql(mudStoreTables))); - return { - async registerTables({ blockNumber, tables }) { - await database.transaction(async (tx) => { - for (const table of tables) { - debug(`creating table ${table.namespace}:${table.name} for world ${chainId}:${table.address}`); + return async function sqliteStorageAdapter({ blockNumber, logs }) { + // Find table registration logs and create new tables + const newTables = logs.filter(isTableRegistrationLog).map(logToTable); + await database.transaction(async (tx) => { + for (const table of newTables) { + debug(`creating table ${table.namespace}:${table.name} for world ${chainId}:${table.address}`); + + const sqliteTable = buildTable({ + address: table.address, + namespace: table.namespace, + name: table.name, + keySchema: table.keySchema, + valueSchema: table.valueSchema, + }); - const sqliteTable = createSqliteTable({ + tx.run(sql.raw(sqliteTableToSql(sqliteTable))); + + tx.insert(mudStoreTables) + .values({ + schemaVersion, + id: getTableName(table.address, table.namespace, table.name), address: table.address, + tableId: tableIdToHex(table.namespace, table.name), namespace: table.namespace, name: table.name, keySchema: table.keySchema, valueSchema: table.valueSchema, - }); - - tx.run(sql.raw(sqliteTableToSql(sqliteTable))); + lastUpdatedBlockNumber: blockNumber, + }) + .onConflictDoNothing() + .run(); + } + }); - tx.insert(mudStoreTables) - .values({ - schemaVersion, - id: getTableName(table.address, table.namespace, table.name), - address: table.address, - tableId: new TableId(table.namespace, table.name).toHex(), - namespace: table.namespace, - name: table.name, - keySchema: table.keySchema, - valueSchema: table.valueSchema, - lastUpdatedBlockNumber: blockNumber, + const tables = getTables( + database, + Array.from( + new Set( + logs.map((log) => + JSON.stringify({ + address: getAddress(log.address), + ...hexToTableId(log.args.tableId), }) - .onConflictDoNothing() - .run(); - } - }); - }, - async getTables({ tables }) { - // TODO: fetch any missing schemas from RPC - // TODO: cache schemas in memory? - return getTables(database, tables); - }, - async storeOperations({ blockNumber, operations }) { - // This is currently parallelized per world (each world has its own database). - // This may need to change if we decide to put multiple worlds into one DB (e.g. a namespace per world, but all under one DB). - // If so, we'll probably want to wrap the entire block worth of operations in a transaction. + ) + ) + ).map((json) => JSON.parse(json)) + ); - const tables = getTables( - database, - Array.from( - new Set( - operations.map((operation) => - JSON.stringify({ - address: getAddress(operation.address), - namespace: operation.namespace, - name: operation.name, - }) + await database.transaction(async (tx) => { + for (const { address, namespace, name } of tables) { + tx.update(mudStoreTables) + .set({ lastUpdatedBlockNumber: blockNumber }) + .where( + and( + eq(mudStoreTables.address, address), + eq(mudStoreTables.namespace, namespace), + eq(mudStoreTables.name, name) ) ) - ).map((json) => JSON.parse(json)) - ); + .run(); + } - await database.transaction(async (tx) => { - for (const { address, namespace, name } of tables) { - tx.update(mudStoreTables) - .set({ lastUpdatedBlockNumber: blockNumber }) - .where( - and( - eq(mudStoreTables.address, address), - eq(mudStoreTables.namespace, namespace), - eq(mudStoreTables.name, name) - ) - ) - .run(); + for (const log of logs) { + const table = tables.find( + (table) => table.address === getAddress(log.address) && table.tableId === log.args.tableId + ); + if (!table) { + const tableId = hexToTableId(log.args.tableId); + debug(`table ${tableId.namespace}:${tableId.name} not found, skipping log`, log); + continue; } - for (const operation of operations) { - const table = tables.find( - (table) => - table.address === getAddress(operation.address) && - table.namespace === operation.namespace && - table.name === operation.name - ); - if (!table) { - debug(`table ${operation.namespace}:${operation.name} not found, skipping operation`, operation); - continue; - } + const sqlTable = buildTable(table); + const uniqueKey = concatHex(log.args.keyTuple as Hex[]); + const key = decodeKey(table.keySchema, log.args.keyTuple); - const sqliteTable = createSqliteTable(table); - const key = concatHex( - Object.entries(table.keySchema).map(([keyName, type]) => - encodeAbiParameters([{ type }], [operation.key[keyName]]) - ) - ); - - if (operation.type === "SetRecord") { - debug("SetRecord", operation); - tx.insert(sqliteTable) - .values({ - __key: key, + if (log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord") { + const value = decodeValueArgs(table.valueSchema, log.args); + debug("upserting record", { + namespace: table.namespace, + name: table.name, + key, + value, + }); + tx.insert(sqlTable) + .values({ + __key: uniqueKey, + __staticData: log.args.staticData, + __encodedLengths: log.args.encodedLengths, + __dynamicData: log.args.dynamicData, + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: false, + ...key, + ...value, + }) + .onConflictDoUpdate({ + target: sqlTable.__key, + set: { + __staticData: log.args.staticData, + __encodedLengths: log.args.encodedLengths, + __dynamicData: log.args.dynamicData, __lastUpdatedBlockNumber: blockNumber, __isDeleted: false, - ...operation.key, - ...operation.value, - }) - .onConflictDoUpdate({ - target: sqliteTable.__key, - set: { - __lastUpdatedBlockNumber: blockNumber, - __isDeleted: false, - ...operation.value, - }, - }) - .run(); - } else if (operation.type === "SetField") { - debug("SetField", operation); - tx.insert(sqliteTable) - .values({ - __key: key, + ...value, + }, + }) + .run(); + } else if (log.eventName === "StoreSpliceStaticData") { + // TODO: verify that this returns what we expect (doesn't error/undefined on no record) + const previousValue = (await tx.select().from(sqlTable).where(eq(sqlTable.__key, uniqueKey)).execute())[0]; + const previousStaticData = (previousValue?.__staticData as Hex) ?? "0x"; + const newStaticData = spliceHex(previousStaticData, log.args.start, log.args.deleteCount, log.args.data); + const newValue = decodeValueArgs(table.valueSchema, { + staticData: newStaticData, + encodedLengths: (previousValue?.__encodedLengths as Hex) ?? "0x", + dynamicData: (previousValue?.__dynamicData as Hex) ?? "0x", + }); + debug("upserting record via splice static", { + namespace: table.namespace, + name: table.name, + key, + previousStaticData, + newStaticData, + previousValue, + newValue, + }); + tx.insert(sqlTable) + .values({ + __key: uniqueKey, + __staticData: newStaticData, + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: false, + ...key, + ...newValue, + }) + .onConflictDoUpdate({ + target: sqlTable.__key, + set: { + __staticData: newStaticData, __lastUpdatedBlockNumber: blockNumber, __isDeleted: false, - ...operation.key, - ...schemaToDefaults(table.valueSchema), - [operation.fieldName]: operation.fieldValue, - }) - .onConflictDoUpdate({ - target: sqliteTable.__key, - set: { - __lastUpdatedBlockNumber: blockNumber, - __isDeleted: false, - [operation.fieldName]: operation.fieldValue, - }, - }) - .run(); - } else if (operation.type === "DeleteRecord") { - // TODO: should we upsert so we at least have a DB record of when a thing was created/deleted within the same block? - debug("DeleteRecord", operation); - tx.update(sqliteTable) - .set({ + ...newValue, + }, + }) + .run(); + } else if (log.eventName === "StoreSpliceDynamicData") { + const previousValue = (await tx.select().from(sqlTable).where(eq(sqlTable.__key, uniqueKey)).execute())[0]; + const previousDynamicData = (previousValue?.__dynamicData as Hex) ?? "0x"; + const newDynamicData = spliceHex(previousDynamicData, log.args.start, log.args.deleteCount, log.args.data); + const newValue = decodeValueArgs(table.valueSchema, { + staticData: (previousValue?.__staticData as Hex) ?? "0x", + // TODO: handle unchanged encoded lengths + encodedLengths: log.args.encodedLengths, + dynamicData: newDynamicData, + }); + debug("upserting record via splice dynamic", { + namespace: table.namespace, + name: table.name, + key, + previousDynamicData, + newDynamicData, + previousValue, + newValue, + }); + tx.insert(sqlTable) + .values({ + __key: uniqueKey, + // TODO: handle unchanged encoded lengths + __encodedLengths: log.args.encodedLengths, + __dynamicData: newDynamicData, + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: false, + ...key, + ...newValue, + }) + .onConflictDoUpdate({ + target: sqlTable.__key, + set: { + // TODO: handle unchanged encoded lengths + __encodedLengths: log.args.encodedLengths, + __dynamicData: newDynamicData, __lastUpdatedBlockNumber: blockNumber, - __isDeleted: true, - }) - .where(eq(sqliteTable.__key, key)) - .run(); - } + __isDeleted: false, + ...newValue, + }, + }) + .run(); + } else if (log.eventName === "StoreDeleteRecord") { + // TODO: should we upsert so we at least have a DB record of when a thing was created/deleted within the same block? + debug("deleting record", { + namespace: table.namespace, + name: table.name, + key, + }); + tx.update(sqlTable) + .set({ + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: true, + }) + .where(eq(sqlTable.__key, uniqueKey)) + .run(); } + } - tx.insert(chainState) - .values({ - schemaVersion, - chainId, + tx.insert(chainState) + .values({ + schemaVersion, + chainId, + lastUpdatedBlockNumber: blockNumber, + }) + .onConflictDoUpdate({ + target: [chainState.schemaVersion, chainState.chainId], + set: { lastUpdatedBlockNumber: blockNumber, - }) - .onConflictDoUpdate({ - target: [chainState.schemaVersion, chainState.chainId], - set: { - lastUpdatedBlockNumber: blockNumber, - }, - }) - .run(); - }); - }, - } as StorageAdapter; + }, + }) + .run(); + }); + }; } diff --git a/packages/store-sync/src/sqlite/syncToSqlite.ts b/packages/store-sync/src/sqlite/syncToSqlite.ts index 2da2185bf9..210b9677d0 100644 --- a/packages/store-sync/src/sqlite/syncToSqlite.ts +++ b/packages/store-sync/src/sqlite/syncToSqlite.ts @@ -14,14 +14,14 @@ type SyncToSqliteOptions = SyncOption startSync?: boolean; }; -type SyncToSqliteResult = SyncResult & { +type SyncToSqliteResult = SyncResult & { stopSync: () => void; }; /** * Creates an indexer to process and store blockchain events. * - * @param {CreateIndexerOptions} options See `CreateIndexerOptions`. + * @param {SyncToSqliteOptions} options See `SyncToSqliteOptions`. * @returns A function to unsubscribe from the block stream, effectively stopping the indexer. */ export async function syncToSqlite({ @@ -34,7 +34,7 @@ export async function syncToSqlite({ indexerUrl, initialState, startSync = true, -}: SyncToSqliteOptions): Promise> { +}: SyncToSqliteOptions): Promise { const storeSync = await createStoreSync({ storageAdapter: await sqliteStorage({ database, publicClient, config }), config, @@ -46,7 +46,7 @@ export async function syncToSqlite({ initialState, }); - const sub = startSync ? storeSync.blockStorageOperations$.subscribe() : null; + const sub = startSync ? storeSync.storedBlockLogs$.subscribe() : null; const stopSync = (): void => { sub?.unsubscribe(); }; diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 06772c450b..68427b3528 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -119,41 +119,71 @@ "name": "validate field layout", "gasUsed": 3944 }, + { + "file": "test/Gas.t.sol", + "test": "testCompareAbiEncodeVsCustom", + "name": "abi encode (static)", + "gasUsed": 133 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareAbiEncodeVsCustom", + "name": "abi encode (dynamic)", + "gasUsed": 849 + }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "abi encode", - "gasUsed": 949 + "gasUsed": 943 }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "abi decode", - "gasUsed": 1738 + "gasUsed": 1741 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareAbiEncodeVsCustom", + "name": "custom encode (static)", + "gasUsed": 191 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareAbiEncodeVsCustom", + "name": "custom encode (length)", + "gasUsed": 141 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareAbiEncodeVsCustom", + "name": "custom encode (dynamic)", + "gasUsed": 1152 }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "custom encode", - "gasUsed": 1394 + "gasUsed": 2065 }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "custom decode", - "gasUsed": 1976 + "gasUsed": 1981 }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "pass abi encoded bytes to external contract", - "gasUsed": 6550 + "gasUsed": 6562 }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "pass custom encoded bytes to external contract", - "gasUsed": 1444 + "gasUsed": 1451 }, { "file": "test/Gas.t.sol", @@ -309,7 +339,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register KeyEncoding table", - "gasUsed": 697905 + "gasUsed": 697932 }, { "file": "test/Mixed.t.sol", @@ -321,19 +351,19 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Mixed table", - "gasUsed": 560027 + "gasUsed": 560113 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 108640 + "gasUsed": 108795 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "get record from Mixed", - "gasUsed": 9640 + "gasUsed": 9639 }, { "file": "test/PackedCounter.t.sol", @@ -567,25 +597,25 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 22898 + "gasUsed": 23281 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 16928 + "gasUsed": 17317 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 24647 + "gasUsed": 25478 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 16678 + "gasUsed": 17514 }, { "file": "test/StoreCoreGas.t.sol", @@ -639,67 +669,67 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 61935 + "gasUsed": 62552 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 73748 + "gasUsed": 76175 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 25441 + "gasUsed": 25942 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 21483 + "gasUsed": 21493 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 61935 + "gasUsed": 62552 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 167808 + "gasUsed": 169944 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 28269 + "gasUsed": 29579 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 22901 + "gasUsed": 22878 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 14558 + "gasUsed": 15223 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 37206 + "gasUsed": 37997 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 620356 + "gasUsed": 620426 }, { "file": "test/StoreCoreGas.t.sol", @@ -723,7 +753,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 104856 + "gasUsed": 104895 }, { "file": "test/StoreCoreGas.t.sol", @@ -735,7 +765,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "compare: Set complex record with dynamic data using native solidity", - "gasUsed": 116842 + "gasUsed": 116845 }, { "file": "test/StoreCoreGas.t.sol", @@ -765,7 +795,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 33831 + "gasUsed": 34114 }, { "file": "test/StoreCoreGas.t.sol", @@ -777,7 +807,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 32479 + "gasUsed": 32761 }, { "file": "test/StoreCoreGas.t.sol", @@ -789,7 +819,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 55195 + "gasUsed": 55894 }, { "file": "test/StoreCoreGas.t.sol", @@ -801,7 +831,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 33313 + "gasUsed": 34134 }, { "file": "test/StoreCoreGas.t.sol", @@ -813,7 +843,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 34181 + "gasUsed": 34695 }, { "file": "test/StoreCoreGas.t.sol", @@ -825,7 +855,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 56684 + "gasUsed": 57199 }, { "file": "test/StoreCoreGas.t.sol", @@ -837,25 +867,25 @@ "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 14835 + "gasUsed": 16261 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 15865 + "gasUsed": 17082 }, { "file": "test/StoreHook.t.sol", "test": "testCallHook", "name": "call an enabled hook", - "gasUsed": 10157 + "gasUsed": 14598 }, { "file": "test/StoreHook.t.sol", "test": "testCallHook", "name": "call a disabled hook", - "gasUsed": 144 + "gasUsed": 133 }, { "file": "test/StoreHook.t.sol", @@ -891,7 +921,7 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 59331 + "gasUsed": 60015 }, { "file": "test/tables/Callbacks.t.sol", @@ -903,19 +933,19 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 39001 + "gasUsed": 39345 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 61323 + "gasUsed": 61997 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 61323 + "gasUsed": 61997 }, { "file": "test/tables/StoreHooks.t.sol", @@ -927,49 +957,49 @@ "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 19075 + "gasUsed": 19410 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 15453 + "gasUsed": 15844 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 17134 + "gasUsed": 17479 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 37483 + "gasUsed": 38603 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 10992 + "gasUsed": 10994 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 33544 + "gasUsed": 34250 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 84011 + "gasUsed": 84688 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 83923 + "gasUsed": 84600 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", @@ -999,13 +1029,13 @@ "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 25580 + "gasUsed": 26291 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 27157 + "gasUsed": 28565 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -1059,13 +1089,13 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 421491 + "gasUsed": 421554 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 36809 + "gasUsed": 37413 }, { "file": "test/Vector2.t.sol", diff --git a/packages/store/src/IStore.sol b/packages/store/src/IStore.sol index 68df303f9e..95bf0e301f 100644 --- a/packages/store/src/IStore.sol +++ b/packages/store/src/IStore.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0; import { IStoreErrors } from "./IStoreErrors.sol"; +import { PackedCounter } from "./PackedCounter.sol"; import { FieldLayout } from "./FieldLayout.sol"; import { Schema } from "./Schema.sol"; import { IStoreHook } from "./IStoreHook.sol"; @@ -24,7 +25,7 @@ interface IStoreRead { function getField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout ) external view returns (bytes memory data); @@ -32,7 +33,7 @@ interface IStoreRead { function getFieldLength( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout ) external view returns (uint256); @@ -40,7 +41,7 @@ interface IStoreRead { function getFieldSlice( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout, uint256 start, uint256 end @@ -48,15 +49,32 @@ interface IStoreRead { } interface IStoreWrite { - event StoreSetRecord(bytes32 tableId, bytes32[] keyTuple, bytes data); - event StoreSetField(bytes32 tableId, bytes32[] keyTuple, uint8 schemaIndex, bytes data); + event StoreSetRecord( + bytes32 tableId, + bytes32[] keyTuple, + bytes staticData, + bytes32 encodedLengths, + bytes dynamicData + ); + + event StoreSpliceStaticData(bytes32 tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data); + event StoreSpliceDynamicData( + bytes32 tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data, + bytes32 encodedLengths + ); event StoreDeleteRecord(bytes32 tableId, bytes32[] keyTuple); // Set full record (including full dynamic data) function setRecord( bytes32 tableId, bytes32[] calldata keyTuple, - bytes calldata data, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, FieldLayout fieldLayout ) external; @@ -64,7 +82,7 @@ interface IStoreWrite { function setField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes calldata data, FieldLayout fieldLayout ) external; @@ -73,7 +91,7 @@ interface IStoreWrite { function pushToField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes calldata dataToPush, FieldLayout fieldLayout ) external; @@ -82,7 +100,7 @@ interface IStoreWrite { function popFromField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, uint256 byteLengthToPop, FieldLayout fieldLayout ) external; @@ -91,7 +109,7 @@ interface IStoreWrite { function updateInField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, uint256 startByteIndex, bytes calldata dataToSet, FieldLayout fieldLayout @@ -102,13 +120,21 @@ interface IStoreWrite { } interface IStoreEphemeral { - event StoreEphemeralRecord(bytes32 tableId, bytes32[] keyTuple, bytes data); + event StoreEphemeralRecord( + bytes32 tableId, + bytes32[] keyTuple, + bytes staticData, + bytes32 encodedLengths, + bytes dynamicData + ); // Emit the ephemeral event without modifying storage function emitEphemeralRecord( bytes32 tableId, bytes32[] calldata keyTuple, - bytes calldata data, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, FieldLayout fieldLayout ) external; } diff --git a/packages/store/src/IStoreErrors.sol b/packages/store/src/IStoreErrors.sol index 8763723b5d..e5214d19cd 100644 --- a/packages/store/src/IStoreErrors.sol +++ b/packages/store/src/IStoreErrors.sol @@ -8,7 +8,8 @@ interface IStoreErrors { error StoreCore_NotImplemented(); error StoreCore_NotDynamicField(); - error StoreCore_InvalidDataLength(uint256 expected, uint256 received); + error StoreCore_InvalidStaticDataLength(uint256 expected, uint256 received); + error StoreCore_InvalidDynamicDataLength(uint256 expected, uint256 received); error StoreCore_InvalidKeyNamesLength(uint256 expected, uint256 received); error StoreCore_InvalidFieldNamesLength(uint256 expected, uint256 received); error StoreCore_InvalidValueSchemaLength(uint256 expected, uint256 received); diff --git a/packages/store/src/IStoreHook.sol b/packages/store/src/IStoreHook.sol index fa65ff4cff..c3132fcea7 100644 --- a/packages/store/src/IStoreHook.sol +++ b/packages/store/src/IStoreHook.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.0; import { FieldLayout } from "./FieldLayout.sol"; import { IERC165, ERC165_INTERFACE_ID } from "./IERC165.sol"; +import { PackedCounter } from "./PackedCounter.sol"; // ERC-165 Interface ID (see https://eips.ethereum.org/EIPS/eip-165) bytes4 constant STORE_HOOK_INTERFACE_ID = IStoreHook.onBeforeSetRecord.selector ^ @@ -17,21 +18,25 @@ interface IStoreHook is IERC165 { function onBeforeSetRecord( bytes32 tableId, bytes32[] memory keyTuple, - bytes memory data, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, FieldLayout fieldLayout ) external; function onAfterSetRecord( bytes32 tableId, bytes32[] memory keyTuple, - bytes memory data, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, FieldLayout fieldLayout ) external; function onBeforeSetField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes memory data, FieldLayout fieldLayout ) external; @@ -39,7 +44,7 @@ interface IStoreHook is IERC165 { function onAfterSetField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes memory data, FieldLayout fieldLayout ) external; diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index c2b81a57a8..6187beb974 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -17,10 +17,30 @@ import { StoreHookLib, StoreHookType } from "./StoreHook.sol"; library StoreCore { // note: the preimage of the tuple of keys used to index is part of the event, so it can be used by indexers - event StoreSetRecord(bytes32 tableId, bytes32[] keyTuple, bytes data); - event StoreSetField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes data); + event StoreSetRecord( + bytes32 tableId, + bytes32[] keyTuple, + bytes staticData, + bytes32 encodedLengths, + bytes dynamicData + ); + event StoreSpliceStaticData(bytes32 tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data); + event StoreSpliceDynamicData( + bytes32 tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data, + bytes32 encodedLengths + ); event StoreDeleteRecord(bytes32 tableId, bytes32[] keyTuple); - event StoreEphemeralRecord(bytes32 tableId, bytes32[] keyTuple, bytes data); + event StoreEphemeralRecord( + bytes32 tableId, + bytes32[] keyTuple, + bytes staticData, + bytes32 encodedLengths, + bytes dynamicData + ); /** * Intialize the store address to use in StoreSwitch. @@ -101,6 +121,7 @@ library StoreCore { ) internal { // Verify the field layout is valid fieldLayout.validate({ allowEmpty: false }); + // Verify the schema is valid keySchema.validate({ allowEmpty: true }); valueSchema.validate({ allowEmpty: false }); @@ -114,6 +135,7 @@ library StoreCore { if (fieldNames.length != fieldLayout.numFields()) { revert IStoreErrors.StoreCore_InvalidFieldNamesLength(fieldLayout.numFields(), fieldNames.length); } + // Verify the number of value schema types if (valueSchema.numFields() != fieldLayout.numFields()) { revert IStoreErrors.StoreCore_InvalidValueSchemaLength(fieldLayout.numFields(), valueSchema.numFields()); @@ -164,48 +186,64 @@ library StoreCore { /** * Set full data record for the given tableId and key tuple and field layout */ - function setRecord(bytes32 tableId, bytes32[] memory keyTuple, bytes memory data, FieldLayout fieldLayout) internal { - // verify the value has the correct length for the table (based on the table's field layout) + function setRecord( + bytes32 tableId, + bytes32[] memory keyTuple, + bytes memory staticData, + PackedCounter encodedLengths, + bytes memory dynamicData, + FieldLayout fieldLayout + ) internal { + // verify the value has the correct length for the tableId (based on the tableId's field layout) // to prevent invalid data from being stored // Verify static data length + dynamic data length matches the given data - (uint256 staticLength, PackedCounter dynamicLength) = StoreCoreInternal._validateDataLength(fieldLayout, data); + StoreCoreInternal._validateDataLength(fieldLayout, staticData, encodedLengths, dynamicData); // Emit event to notify indexers - emit StoreSetRecord(tableId, keyTuple, data); + emit StoreSetRecord(tableId, keyTuple, staticData, encodedLengths.unwrap(), dynamicData); // Call onBeforeSetRecord hooks (before actually modifying the state, so observers have access to the previous state if needed) bytes21[] memory hooks = StoreHooks.get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_RECORD))) { - IStoreHook(hook.getAddress()).onBeforeSetRecord(tableId, keyTuple, data, fieldLayout); + IStoreHook(hook.getAddress()).onBeforeSetRecord( + tableId, + keyTuple, + staticData, + encodedLengths, + dynamicData, + fieldLayout + ); } } // Store the static data at the static data location uint256 staticDataLocation = StoreCoreInternal._getStaticDataLocation(tableId, keyTuple); - uint256 memoryPointer = Memory.dataPointer(data); + uint256 memoryPointer = Memory.dataPointer(staticData); Storage.store({ storagePointer: staticDataLocation, offset: 0, memoryPointer: memoryPointer, - length: staticLength + length: staticData.length }); - memoryPointer += staticLength + 32; // move the memory pointer to the start of the dynamic data (skip the encoded dynamic length) // Set the dynamic data if there are dynamic fields if (fieldLayout.numDynamicFields() > 0) { // Store the dynamic data length at the dynamic data length location uint256 dynamicDataLengthLocation = StoreCoreInternal._getDynamicDataLengthLocation(tableId, keyTuple); - Storage.store({ storagePointer: dynamicDataLengthLocation, data: dynamicLength.unwrap() }); + Storage.store({ storagePointer: dynamicDataLengthLocation, data: encodedLengths.unwrap() }); + + // Move the memory pointer to the start of the dynamic data + memoryPointer = Memory.dataPointer(dynamicData); // For every dynamic element, slice off the dynamic data and store it at the dynamic location uint256 dynamicDataLocation; uint256 dynamicDataLength; for (uint8 i; i < fieldLayout.numDynamicFields(); ) { dynamicDataLocation = StoreCoreInternal._getDynamicDataLocation(tableId, keyTuple, i); - dynamicDataLength = dynamicLength.atIndex(i); + dynamicDataLength = encodedLengths.atIndex(i); Storage.store({ storagePointer: dynamicDataLocation, offset: 0, @@ -223,7 +261,14 @@ library StoreCore { for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.AFTER_SET_RECORD))) { - IStoreHook(hook.getAddress()).onAfterSetRecord(tableId, keyTuple, data, fieldLayout); + IStoreHook(hook.getAddress()).onAfterSetRecord( + tableId, + keyTuple, + staticData, + encodedLengths, + dynamicData, + fieldLayout + ); } } } @@ -234,33 +279,30 @@ library StoreCore { function setField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes memory data, FieldLayout fieldLayout ) internal { - // Emit event to notify indexers - emit StoreSetField(tableId, keyTuple, schemaIndex, data); - // Call onBeforeSetField hooks (before modifying the state) bytes21[] memory hooks = StoreHooks.get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { - IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, schemaIndex, data, fieldLayout); + IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, fieldIndex, data, fieldLayout); } } - if (schemaIndex < fieldLayout.numStaticFields()) { - StoreCoreInternal._setStaticField(tableId, keyTuple, fieldLayout, schemaIndex, data); + if (fieldIndex < fieldLayout.numStaticFields()) { + StoreCoreInternal._setStaticField(tableId, keyTuple, fieldLayout, fieldIndex, data); } else { - StoreCoreInternal._setDynamicField(tableId, keyTuple, fieldLayout, schemaIndex, data); + StoreCoreInternal._setDynamicField(tableId, keyTuple, fieldLayout, fieldIndex, data); } // Call onAfterSetField hooks (after modifying the state) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.AFTER_SET_FIELD))) { - IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, schemaIndex, data, fieldLayout); + IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, fieldIndex, data, fieldLayout); } } } @@ -306,39 +348,36 @@ library StoreCore { function pushToField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes memory dataToPush, FieldLayout fieldLayout ) internal { - if (schemaIndex < fieldLayout.numStaticFields()) { + if (fieldIndex < fieldLayout.numStaticFields()) { revert IStoreErrors.StoreCore_NotDynamicField(); } - // TODO add push-specific event and hook to avoid the storage read? (https://github.com/latticexyz/mud/issues/444) + // TODO add push-specific hook to avoid the storage read? (https://github.com/latticexyz/mud/issues/444) bytes memory fullData = abi.encodePacked( - StoreCoreInternal._getDynamicField(tableId, keyTuple, schemaIndex, fieldLayout), + StoreCoreInternal._getDynamicField(tableId, keyTuple, fieldIndex, fieldLayout), dataToPush ); - // Emit event to notify indexers - emit StoreSetField(tableId, keyTuple, schemaIndex, fullData); - // Call onBeforeSetField hooks (before modifying the state) bytes21[] memory hooks = StoreHooks.get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { - IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, schemaIndex, fullData, fieldLayout); + IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } - StoreCoreInternal._pushToDynamicField(tableId, keyTuple, fieldLayout, schemaIndex, dataToPush); + StoreCoreInternal._pushToDynamicField(tableId, keyTuple, fieldLayout, fieldIndex, dataToPush); // Call onAfterSetField hooks (after modifying the state) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.AFTER_SET_FIELD))) { - IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, schemaIndex, fullData, fieldLayout); + IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } } @@ -349,40 +388,37 @@ library StoreCore { function popFromField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, uint256 byteLengthToPop, FieldLayout fieldLayout ) internal { - if (schemaIndex < fieldLayout.numStaticFields()) { + if (fieldIndex < fieldLayout.numStaticFields()) { revert IStoreErrors.StoreCore_NotDynamicField(); } - // TODO add pop-specific event and hook to avoid the storage read? (https://github.com/latticexyz/mud/issues/444) + // TODO add pop-specific hook to avoid the storage read? (https://github.com/latticexyz/mud/issues/444) bytes memory fullData; { - bytes memory oldData = StoreCoreInternal._getDynamicField(tableId, keyTuple, schemaIndex, fieldLayout); + bytes memory oldData = StoreCoreInternal._getDynamicField(tableId, keyTuple, fieldIndex, fieldLayout); fullData = SliceLib.getSubslice(oldData, 0, oldData.length - byteLengthToPop).toBytes(); } - // Emit event to notify indexers - emit StoreSetField(tableId, keyTuple, schemaIndex, fullData); - // Call onBeforeSetField hooks (before modifying the state) bytes21[] memory hooks = StoreHooks.get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { - IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, schemaIndex, fullData, fieldLayout); + IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } - StoreCoreInternal._popFromDynamicField(tableId, keyTuple, fieldLayout, schemaIndex, byteLengthToPop); + StoreCoreInternal._popFromDynamicField(tableId, keyTuple, fieldLayout, fieldIndex, byteLengthToPop); // Call onAfterSetField hooks (after modifying the state) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.AFTER_SET_FIELD))) { - IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, schemaIndex, fullData, fieldLayout); + IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } } @@ -393,24 +429,25 @@ library StoreCore { function updateInField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, uint256 startByteIndex, bytes memory dataToSet, FieldLayout fieldLayout ) internal { - if (schemaIndex < fieldLayout.numStaticFields()) { + if (fieldIndex < fieldLayout.numStaticFields()) { revert IStoreErrors.StoreCore_NotDynamicField(); } + // index must be checked because it could be arbitrarily large // (but dataToSet.length can be unchecked - it won't overflow into another slot due to gas costs and hashed slots) if (startByteIndex > type(uint40).max) { revert IStoreErrors.StoreCore_DataIndexOverflow(type(uint40).max, startByteIndex); } - // TODO add setItem-specific event and hook to avoid the storage read? (https://github.com/latticexyz/mud/issues/444) + // TODO add setItem-specific hook to avoid the storage read? (https://github.com/latticexyz/mud/issues/444) bytes memory fullData; { - bytes memory oldData = StoreCoreInternal._getDynamicField(tableId, keyTuple, schemaIndex, fieldLayout); + bytes memory oldData = StoreCoreInternal._getDynamicField(tableId, keyTuple, fieldIndex, fieldLayout); fullData = abi.encodePacked( SliceLib.getSubslice(oldData, 0, startByteIndex).toBytes(), dataToSet, @@ -418,25 +455,22 @@ library StoreCore { ); } - // Emit event to notify indexers - emit StoreSetField(tableId, keyTuple, schemaIndex, fullData); - // Call onBeforeSetField hooks (before modifying the state) bytes21[] memory hooks = StoreHooks.get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { - IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, schemaIndex, fullData, fieldLayout); + IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } - StoreCoreInternal._setDynamicFieldItem(tableId, keyTuple, fieldLayout, schemaIndex, startByteIndex, dataToSet); + StoreCoreInternal._setDynamicFieldItem(tableId, keyTuple, fieldLayout, fieldIndex, startByteIndex, dataToSet); // Call onAfterSetField hooks (after modifying the state) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.AFTER_SET_FIELD))) { - IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, schemaIndex, fullData, fieldLayout); + IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } } @@ -453,14 +487,16 @@ library StoreCore { function emitEphemeralRecord( bytes32 tableId, bytes32[] memory keyTuple, - bytes memory data, + 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, data); + StoreCoreInternal._validateDataLength(fieldLayout, staticData, encodedLengths, dynamicData); // Emit event to notify indexers - emit StoreEphemeralRecord(tableId, keyTuple, data); + emit StoreEphemeralRecord(tableId, keyTuple, staticData, encodedLengths.unwrap(), dynamicData); } /************************************************************************ @@ -501,6 +537,7 @@ library StoreCore { // Early return if there are no dynamic fields if (dynamicDataLength.total() == 0) return data; + // Advance memoryPointer to the dynamic data section memoryPointer += staticLength; @@ -516,6 +553,7 @@ library StoreCore { uint256 dynamicDataLocation = StoreCoreInternal._getDynamicDataLocation(tableId, keyTuple, i); uint256 length = dynamicDataLength.atIndex(i); Storage.load({ storagePointer: dynamicDataLocation, length: length, offset: 0, memoryPointer: memoryPointer }); + // Advance memoryPointer by the length of this dynamic field memoryPointer += length; } @@ -530,13 +568,13 @@ library StoreCore { function getField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout ) internal view returns (bytes memory) { - if (schemaIndex < fieldLayout.numStaticFields()) { - return StoreCoreInternal._getStaticField(tableId, keyTuple, schemaIndex, fieldLayout); + if (fieldIndex < fieldLayout.numStaticFields()) { + return StoreCoreInternal._getStaticField(tableId, keyTuple, fieldIndex, fieldLayout); } else { - return StoreCoreInternal._getDynamicField(tableId, keyTuple, schemaIndex, fieldLayout); + return StoreCoreInternal._getDynamicField(tableId, keyTuple, fieldIndex, fieldLayout); } } @@ -546,15 +584,15 @@ library StoreCore { function getFieldLength( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout ) internal view returns (uint256) { uint8 numStaticFields = uint8(fieldLayout.numStaticFields()); - if (schemaIndex < numStaticFields) { - return fieldLayout.atIndex(schemaIndex); + if (fieldIndex < numStaticFields) { + return fieldLayout.atIndex(fieldIndex); } else { // Get the length and storage location of the dynamic field - uint8 dynamicFieldLayoutIndex = schemaIndex - numStaticFields; + uint8 dynamicFieldLayoutIndex = fieldIndex - numStaticFields; return StoreCoreInternal._loadEncodedDynamicDataLength(tableId, keyTuple).atIndex(dynamicFieldLayoutIndex); } } @@ -566,18 +604,18 @@ library StoreCore { function getFieldSlice( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout, uint256 start, uint256 end ) internal view returns (bytes memory) { uint8 numStaticFields = uint8(fieldLayout.numStaticFields()); - if (schemaIndex < fieldLayout.numStaticFields()) { + if (fieldIndex < fieldLayout.numStaticFields()) { revert IStoreErrors.StoreCore_NotDynamicField(); } // Get the length and storage location of the dynamic field - uint8 dynamicSchemaIndex = schemaIndex - numStaticFields; + uint8 dynamicSchemaIndex = fieldIndex - numStaticFields; uint256 location = StoreCoreInternal._getDynamicDataLocation(tableId, keyTuple, dynamicSchemaIndex); return Storage.load({ storagePointer: location, length: end - start, offset: start }); @@ -597,46 +635,76 @@ library StoreCoreInternal { bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout, - uint8 schemaIndex, + uint8 fieldIndex, bytes memory data ) internal { - // verify the value has the correct length for the field - uint256 staticByteLength = fieldLayout.atIndex(schemaIndex); - if (staticByteLength != data.length) { - revert IStoreErrors.StoreCore_InvalidDataLength(staticByteLength, data.length); - } - - // Store the provided value in storage uint256 location = _getStaticDataLocation(tableId, keyTuple); - uint256 offset = _getStaticDataOffset(fieldLayout, schemaIndex); + uint256 offset = _getStaticDataOffset(fieldLayout, fieldIndex); + Storage.store({ storagePointer: location, offset: offset, data: data }); + + // Emit event to notify indexers + emit StoreCore.StoreSpliceStaticData({ + tableId: tableId, + keyTuple: keyTuple, + start: uint48(offset), + deleteCount: uint40(fieldLayout.atIndex(fieldIndex)), + data: data + }); } function _setDynamicField( bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout, - uint8 schemaIndex, + uint8 fieldIndex, bytes memory data ) internal { - uint8 dynamicSchemaIndex = schemaIndex - uint8(fieldLayout.numStaticFields()); + uint8 dynamicSchemaIndex = fieldIndex - uint8(fieldLayout.numStaticFields()); - // Update the dynamic data length - _setDynamicDataLengthAtIndex(tableId, keyTuple, dynamicSchemaIndex, data.length); + // Load dynamic data length from storage + uint256 dynamicSchemaLengthSlot = _getDynamicDataLengthLocation(tableId, keyTuple); + PackedCounter encodedLengths = PackedCounter.wrap(Storage.load({ storagePointer: dynamicSchemaLengthSlot })); + + // Update the encoded length + uint256 oldFieldLength = encodedLengths.atIndex(dynamicSchemaIndex); + encodedLengths = encodedLengths.setAtIndex(dynamicSchemaIndex, data.length); + + // Set the new lengths + Storage.store({ storagePointer: dynamicSchemaLengthSlot, data: encodedLengths.unwrap() }); // Store the provided value in storage uint256 dynamicDataLocation = _getDynamicDataLocation(tableId, keyTuple, dynamicSchemaIndex); Storage.store({ storagePointer: dynamicDataLocation, offset: 0, data: data }); + + // Compute start index for the splice event + uint256 start; + unchecked { + // (safe because it's a few uint40 values, which can't overflow uint48) + for (uint8 i; i < dynamicSchemaIndex; i++) { + start += encodedLengths.atIndex(i); + } + } + + // Emit event to notify indexers + emit StoreCore.StoreSpliceDynamicData({ + tableId: tableId, + keyTuple: keyTuple, + start: uint48(start), + deleteCount: uint40(oldFieldLength), + data: data, + encodedLengths: encodedLengths.unwrap() + }); } function _pushToDynamicField( bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout, - uint8 schemaIndex, + uint8 fieldIndex, bytes memory dataToPush ) internal { - uint8 dynamicSchemaIndex = schemaIndex - uint8(fieldLayout.numStaticFields()); + uint8 dynamicSchemaIndex = fieldIndex - uint8(fieldLayout.numStaticFields()); // Load dynamic data length from storage uint256 dynamicDataLengthSlot = _getDynamicDataLengthLocation(tableId, keyTuple); @@ -651,16 +719,35 @@ library StoreCoreInternal { // Append `dataToPush` to the end of the data in storage _setPartialDynamicData(tableId, keyTuple, dynamicSchemaIndex, oldFieldLength, dataToPush); + + // Compute start index for the splice event + uint256 start = oldFieldLength; + unchecked { + // (safe because it's a few uint40 values, which can't overflow uint48) + for (uint8 i; i < dynamicSchemaIndex; i++) { + start += encodedLengths.atIndex(i); + } + } + + // Emit event to notify indexers + emit StoreCore.StoreSpliceDynamicData({ + tableId: tableId, + keyTuple: keyTuple, + start: uint48(start), + deleteCount: uint40(0), + data: dataToPush, + encodedLengths: encodedLengths.unwrap() + }); } function _popFromDynamicField( bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout, - uint8 schemaIndex, + uint8 fieldIndex, uint256 byteLengthToPop ) internal { - uint8 dynamicSchemaIndex = schemaIndex - uint8(fieldLayout.numStaticFields()); + uint8 dynamicSchemaIndex = fieldIndex - uint8(fieldLayout.numStaticFields()); // Load dynamic data length from storage uint256 dynamicDataLengthSlot = _getDynamicDataLengthLocation(tableId, keyTuple); @@ -674,6 +761,27 @@ library StoreCoreInternal { Storage.store({ storagePointer: dynamicDataLengthSlot, data: encodedLengths.unwrap() }); // Data can be left unchanged, push/set do not assume storage to be 0s + + // Compute start index for the splice event + uint256 start; + unchecked { + // (safe because it's a few uint40 values, which can't overflow uint48) + start = oldFieldLength; + for (uint8 i; i < dynamicSchemaIndex; i++) { + start += encodedLengths.atIndex(i); + } + start -= byteLengthToPop; + } + + // Emit event to notify indexers + emit StoreCore.StoreSpliceDynamicData({ + tableId: tableId, + keyTuple: keyTuple, + start: uint48(start), + deleteCount: uint40(byteLengthToPop), + data: new bytes(0), + encodedLengths: encodedLengths.unwrap() + }); } // startOffset is measured in bytes @@ -681,14 +789,38 @@ library StoreCoreInternal { bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout, - uint8 schemaIndex, + uint8 fieldIndex, uint256 startByteIndex, bytes memory dataToSet ) internal { - uint8 dynamicSchemaIndex = schemaIndex - uint8(fieldLayout.numStaticFields()); + uint8 dynamicSchemaIndex = fieldIndex - uint8(fieldLayout.numStaticFields()); + + // Load dynamic data length from storage + uint256 dynamicSchemaLengthSlot = _getDynamicDataLengthLocation(tableId, keyTuple); + PackedCounter encodedLengths = PackedCounter.wrap(Storage.load({ storagePointer: dynamicSchemaLengthSlot })); // Set `dataToSet` at the given index _setPartialDynamicData(tableId, keyTuple, dynamicSchemaIndex, startByteIndex, dataToSet); + + // Compute start index for the splice event + uint256 start; + unchecked { + // (safe because it's a few uint40 values, which can't overflow uint48) + start = startByteIndex; + for (uint8 i; i < dynamicSchemaIndex; i++) { + start += encodedLengths.atIndex(i); + } + } + + // Emit event to notify indexers + emit StoreCore.StoreSpliceDynamicData({ + tableId: tableId, + keyTuple: keyTuple, + start: uint48(start), + deleteCount: uint40(dataToSet.length), + data: dataToSet, + encodedLengths: encodedLengths.unwrap() + }); } /************************************************************************ @@ -719,16 +851,15 @@ library StoreCoreInternal { function _getStaticField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout ) internal view returns (bytes memory) { // Get the length, storage location and offset of the static field - uint256 staticByteLength = fieldLayout.atIndex(schemaIndex); + uint256 staticByteLength = fieldLayout.atIndex(fieldIndex); uint256 location = _getStaticDataLocation(tableId, keyTuple); - uint256 offset = _getStaticDataOffset(fieldLayout, schemaIndex); + uint256 offset = _getStaticDataOffset(fieldLayout, fieldIndex); // Load the data from storage - return Storage.load({ storagePointer: location, length: staticByteLength, offset: offset }); } @@ -738,11 +869,11 @@ library StoreCoreInternal { function _getDynamicField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout ) internal view returns (bytes memory) { // Get the length and storage location of the dynamic field - uint8 dynamicSchemaIndex = schemaIndex - uint8(fieldLayout.numStaticFields()); + uint8 dynamicSchemaIndex = fieldIndex - uint8(fieldLayout.numStaticFields()); uint256 location = _getDynamicDataLocation(tableId, keyTuple, dynamicSchemaIndex); uint256 dataLength = _loadEncodedDynamicDataLength(tableId, keyTuple).atIndex(dynamicSchemaIndex); @@ -761,19 +892,15 @@ library StoreCoreInternal { */ function _validateDataLength( FieldLayout fieldLayout, - bytes memory data - ) internal pure returns (uint256 staticLength, PackedCounter dynamicLength) { - staticLength = fieldLayout.staticDataLength(); - uint256 expectedLength = staticLength; - dynamicLength; - if (fieldLayout.numDynamicFields() > 0) { - // Dynamic length is encoded at the start of the dynamic length blob - dynamicLength = PackedCounter.wrap(Bytes.slice32(data, staticLength)); - expectedLength += 32 + dynamicLength.total(); // encoded length + data + bytes memory staticData, + PackedCounter encodedLengths, + bytes memory dynamicData + ) internal pure { + if (fieldLayout.staticDataLength() != staticData.length) { + revert IStoreErrors.StoreCore_InvalidStaticDataLength(fieldLayout.staticDataLength(), staticData.length); } - - if (expectedLength != data.length) { - revert IStoreErrors.StoreCore_InvalidDataLength(expectedLength, data.length); + if (encodedLengths.total() != dynamicData.length) { + revert IStoreErrors.StoreCore_InvalidDynamicDataLength(encodedLengths.total(), dynamicData.length); } } @@ -791,9 +918,9 @@ library StoreCoreInternal { /** * Get storage offset for the given value field layout and (static length) index */ - function _getStaticDataOffset(FieldLayout fieldLayout, uint8 schemaIndex) internal pure returns (uint256) { + function _getStaticDataOffset(FieldLayout fieldLayout, uint8 fieldIndex) internal pure returns (uint256) { uint256 offset = 0; - for (uint256 i; i < schemaIndex; i++) { + for (uint256 i; i < fieldIndex; i++) { offset += fieldLayout.atIndex(i); } return offset; @@ -809,9 +936,9 @@ library StoreCoreInternal { function _getDynamicDataLocation( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex + uint8 fieldIndex ) internal pure returns (uint256) { - return uint256(keccak256(abi.encode(SLOT, tableId, keyTuple, schemaIndex))); + return uint256(keccak256(abi.encode(SLOT, tableId, keyTuple, fieldIndex))); } /** @@ -839,7 +966,7 @@ library StoreCoreInternal { function _setDynamicDataLengthAtIndex( bytes32 tableId, bytes32[] memory keyTuple, - uint8 dynamicSchemaIndex, // schemaIndex - numStaticFields + uint8 dynamicSchemaIndex, // fieldIndex - numStaticFields uint256 newLengthAtIndex ) internal { // Load dynamic data length from storage @@ -866,6 +993,7 @@ library StoreCoreInternal { uint256 dynamicDataLocation = _getDynamicDataLocation(tableId, keyTuple, dynamicSchemaIndex); // start index is in bytes, whereas storage slots are in 32-byte words dynamicDataLocation += startByteIndex / 32; + // partial storage slot offset (there is no inherent offset, as each dynamic field starts at its own storage slot) uint256 offset = startByteIndex % 32; Storage.store({ storagePointer: dynamicDataLocation, offset: offset, data: partialData }); diff --git a/packages/store/src/StoreRead.sol b/packages/store/src/StoreRead.sol index ced24eb297..92125f5bd0 100644 --- a/packages/store/src/StoreRead.sol +++ b/packages/store/src/StoreRead.sol @@ -32,29 +32,29 @@ contract StoreRead is IStoreRead { function getField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout ) public view virtual returns (bytes memory data) { - data = StoreCore.getField(tableId, keyTuple, schemaIndex, fieldLayout); + data = StoreCore.getField(tableId, keyTuple, fieldIndex, fieldLayout); } function getFieldLength( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout ) public view virtual returns (uint256) { - return StoreCore.getFieldLength(tableId, keyTuple, schemaIndex, fieldLayout); + return StoreCore.getFieldLength(tableId, keyTuple, fieldIndex, fieldLayout); } function getFieldSlice( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, FieldLayout fieldLayout, uint256 start, uint256 end ) public view virtual returns (bytes memory) { - return StoreCore.getFieldSlice(tableId, keyTuple, schemaIndex, fieldLayout, start, end); + return StoreCore.getFieldSlice(tableId, keyTuple, fieldIndex, fieldLayout, start, end); } } diff --git a/packages/store/src/StoreSwitch.sol b/packages/store/src/StoreSwitch.sol index 86aa1e311d..ed3e243b0e 100644 --- a/packages/store/src/StoreSwitch.sol +++ b/packages/store/src/StoreSwitch.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0; import { IStore } from "./IStore.sol"; +import { PackedCounter } from "../src/PackedCounter.sol"; import { IStoreHook } from "./IStoreHook.sol"; import { StoreCore } from "./StoreCore.sol"; import { Schema } from "./Schema.sol"; @@ -107,12 +108,19 @@ library StoreSwitch { } } - function setRecord(bytes32 tableId, bytes32[] memory keyTuple, bytes memory data, FieldLayout fieldLayout) internal { + function setRecord( + bytes32 tableId, + bytes32[] memory keyTuple, + bytes memory staticData, + PackedCounter encodedLengths, + bytes memory dynamicData, + FieldLayout fieldLayout + ) internal { address _storeAddress = getStoreAddress(); if (_storeAddress == address(this)) { - StoreCore.setRecord(tableId, keyTuple, data, fieldLayout); + StoreCore.setRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); } else { - IStore(_storeAddress).setRecord(tableId, keyTuple, data, fieldLayout); + IStore(_storeAddress).setRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); } } @@ -189,14 +197,23 @@ library StoreSwitch { function emitEphemeralRecord( bytes32 tableId, bytes32[] memory keyTuple, - bytes memory data, + bytes memory staticData, + PackedCounter encodedLengths, + bytes memory dynamicData, FieldLayout fieldLayout ) internal { address _storeAddress = getStoreAddress(); if (_storeAddress == address(this)) { - StoreCore.emitEphemeralRecord(tableId, keyTuple, data, fieldLayout); + StoreCore.emitEphemeralRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); } else { - IStore(_storeAddress).emitEphemeralRecord(tableId, keyTuple, data, fieldLayout); + IStore(_storeAddress).emitEphemeralRecord( + tableId, + keyTuple, + staticData, + encodedLengths, + dynamicData, + fieldLayout + ); } } diff --git a/packages/store/src/codegen/tables/Callbacks.sol b/packages/store/src/codegen/tables/Callbacks.sol index 0126d86c18..5a370f8a20 100644 --- a/packages/store/src/codegen/tables/Callbacks.sol +++ b/packages/store/src/codegen/tables/Callbacks.sol @@ -230,15 +230,26 @@ library Callbacks { } } - /** Tightly pack full data using this table's field layout */ - function encode(bytes24[] memory value) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + /** 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 unchecked { _encodedLengths = PackedCounterLib.pack(value.length * 24); } + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(bytes24[] memory value) internal pure returns (bytes memory) { + return abi.encodePacked(EncodeArray.encode((value))); + } + + /** Tightly pack full data using this table's field layout */ + function encode(bytes24[] memory value) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(value); + bytes memory _dynamicData = encodeDynamic(value); - return abi.encodePacked(_encodedLengths.unwrap(), EncodeArray.encode((value))); + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/store/src/codegen/tables/Hooks.sol b/packages/store/src/codegen/tables/Hooks.sol index 242d5c9730..4d12e0babb 100644 --- a/packages/store/src/codegen/tables/Hooks.sol +++ b/packages/store/src/codegen/tables/Hooks.sol @@ -227,15 +227,26 @@ library Hooks { } } - /** Tightly pack full data using this table's field layout */ - function encode(bytes21[] memory value) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + /** 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 unchecked { _encodedLengths = PackedCounterLib.pack(value.length * 21); } + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(bytes21[] memory value) internal pure returns (bytes memory) { + return abi.encodePacked(EncodeArray.encode((value))); + } + + /** Tightly pack full data using this table's field layout */ + function encode(bytes21[] memory value) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(value); + bytes memory _dynamicData = encodeDynamic(value); - return abi.encodePacked(_encodedLengths.unwrap(), EncodeArray.encode((value))); + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/store/src/codegen/tables/KeyEncoding.sol b/packages/store/src/codegen/tables/KeyEncoding.sol index f2344cf382..f8db386345 100644 --- a/packages/store/src/codegen/tables/KeyEncoding.sol +++ b/packages/store/src/codegen/tables/KeyEncoding.sol @@ -166,9 +166,19 @@ library KeyEncoding { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); } + /** 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) { - return abi.encodePacked(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/store/src/codegen/tables/Mixed.sol b/packages/store/src/codegen/tables/Mixed.sol index 22f664c8e1..9be293952b 100644 --- a/packages/store/src/codegen/tables/Mixed.sol +++ b/packages/store/src/codegen/tables/Mixed.sol @@ -475,22 +475,28 @@ library Mixed { /** Set the full data using individual values */ function set(bytes32 key, uint32 u32, uint128 u128, uint32[] memory a32, string memory s) internal { - bytes memory _data = encode(u32, u128, a32, s); + bytes memory _staticData = encodeStatic(u32, u128); + + PackedCounter _encodedLengths = encodeLengths(a32, s); + bytes memory _dynamicData = encodeDynamic(a32, s); bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 key, uint32 u32, uint128 u128, uint32[] memory a32, string memory s) internal { - bytes memory _data = encode(u32, u128, a32, s); + bytes memory _staticData = encodeStatic(u32, u128); + + PackedCounter _encodedLengths = encodeLengths(a32, s); + bytes memory _dynamicData = encodeDynamic(a32, s); bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using the data struct */ @@ -533,15 +539,32 @@ library Mixed { } } - /** Tightly pack full data using this table's field layout */ - function encode(uint32 u32, uint128 u128, uint32[] memory a32, string memory s) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + /** 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); + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeLengths(uint32[] memory a32, string memory s) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits unchecked { _encodedLengths = PackedCounterLib.pack(a32.length * 4, bytes(s).length); } + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(uint32[] memory a32, string memory s) internal pure returns (bytes memory) { + return abi.encodePacked(EncodeArray.encode((a32)), bytes((s))); + } + + /** Tightly pack full data using this table's field layout */ + function encode(uint32 u32, uint128 u128, uint32[] memory a32, string memory s) internal pure returns (bytes memory) { + bytes memory _staticData = encodeStatic(u32, u128); + + PackedCounter _encodedLengths = encodeLengths(a32, s); + bytes memory _dynamicData = encodeDynamic(a32, s); - return abi.encodePacked(u32, u128, _encodedLengths.unwrap(), EncodeArray.encode((a32)), bytes((s))); + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/store/src/codegen/tables/StoreHooks.sol b/packages/store/src/codegen/tables/StoreHooks.sol index 9b84a3549e..fe82a2a292 100644 --- a/packages/store/src/codegen/tables/StoreHooks.sol +++ b/packages/store/src/codegen/tables/StoreHooks.sol @@ -230,15 +230,26 @@ library StoreHooks { } } - /** Tightly pack full data using this table's field layout */ - function encode(bytes21[] memory value) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + /** 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 unchecked { _encodedLengths = PackedCounterLib.pack(value.length * 21); } + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(bytes21[] memory value) internal pure returns (bytes memory) { + return abi.encodePacked(EncodeArray.encode((value))); + } + + /** Tightly pack full data using this table's field layout */ + function encode(bytes21[] memory value) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(value); + bytes memory _dynamicData = encodeDynamic(value); - return abi.encodePacked(_encodedLengths.unwrap(), EncodeArray.encode((value))); + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/store/src/codegen/tables/Tables.sol b/packages/store/src/codegen/tables/Tables.sol index fc82b0dedb..520bbd4497 100644 --- a/packages/store/src/codegen/tables/Tables.sol +++ b/packages/store/src/codegen/tables/Tables.sol @@ -534,12 +534,15 @@ library Tables { bytes memory abiEncodedKeyNames, bytes memory abiEncodedFieldNames ) internal { - bytes memory _data = encode(fieldLayout, keySchema, valueSchema, abiEncodedKeyNames, abiEncodedFieldNames); + bytes memory _staticData = encodeStatic(fieldLayout, keySchema, valueSchema); + + PackedCounter _encodedLengths = encodeLengths(abiEncodedKeyNames, abiEncodedFieldNames); + bytes memory _dynamicData = encodeDynamic(abiEncodedKeyNames, abiEncodedFieldNames); bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ @@ -552,12 +555,15 @@ library Tables { bytes memory abiEncodedKeyNames, bytes memory abiEncodedFieldNames ) internal { - bytes memory _data = encode(fieldLayout, keySchema, valueSchema, abiEncodedKeyNames, abiEncodedFieldNames); + bytes memory _staticData = encodeStatic(fieldLayout, keySchema, valueSchema); + + PackedCounter _encodedLengths = encodeLengths(abiEncodedKeyNames, abiEncodedFieldNames); + bytes memory _dynamicData = encodeDynamic(abiEncodedKeyNames, abiEncodedFieldNames); bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using the data struct */ @@ -617,29 +623,48 @@ library Tables { } } - /** Tightly pack full data using this table's field layout */ - function encode( + /** Tightly pack static data using this table's schema */ + function encodeStatic( bytes32 fieldLayout, bytes32 keySchema, - bytes32 valueSchema, + bytes32 valueSchema + ) internal pure returns (bytes memory) { + return abi.encodePacked(fieldLayout, keySchema, valueSchema); + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeLengths( bytes memory abiEncodedKeyNames, bytes memory abiEncodedFieldNames - ) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + ) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits unchecked { _encodedLengths = PackedCounterLib.pack(bytes(abiEncodedKeyNames).length, bytes(abiEncodedFieldNames).length); } + } - return - abi.encodePacked( - fieldLayout, - keySchema, - valueSchema, - _encodedLengths.unwrap(), - bytes((abiEncodedKeyNames)), - bytes((abiEncodedFieldNames)) - ); + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic( + bytes memory abiEncodedKeyNames, + bytes memory abiEncodedFieldNames + ) internal pure returns (bytes memory) { + return abi.encodePacked(bytes((abiEncodedKeyNames)), bytes((abiEncodedFieldNames))); + } + + /** Tightly pack full data using this table's field layout */ + function encode( + bytes32 fieldLayout, + bytes32 keySchema, + bytes32 valueSchema, + bytes memory abiEncodedKeyNames, + bytes memory abiEncodedFieldNames + ) internal pure returns (bytes memory) { + bytes memory _staticData = encodeStatic(fieldLayout, keySchema, valueSchema); + + PackedCounter _encodedLengths = encodeLengths(abiEncodedKeyNames, abiEncodedFieldNames); + bytes memory _dynamicData = encodeDynamic(abiEncodedKeyNames, abiEncodedFieldNames); + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/store/src/codegen/tables/Vector2.sol b/packages/store/src/codegen/tables/Vector2.sol index 82a58d420b..f71080845a 100644 --- a/packages/store/src/codegen/tables/Vector2.sol +++ b/packages/store/src/codegen/tables/Vector2.sol @@ -171,22 +171,28 @@ library Vector2 { /** Set the full data using individual values */ function set(bytes32 key, uint32 x, uint32 y) internal { - bytes memory _data = encode(x, y); + bytes memory _staticData = encodeStatic(x, y); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 key, uint32 x, uint32 y) internal { - bytes memory _data = encode(x, y); + bytes memory _staticData = encodeStatic(x, y); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using the data struct */ @@ -206,9 +212,19 @@ library Vector2 { _table.y = (uint32(Bytes.slice4(_blob, 4))); } + /** 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); + } + /** Tightly pack full data using this table's field layout */ function encode(uint32 x, uint32 y) internal pure returns (bytes memory) { - return abi.encodePacked(x, y); + bytes memory _staticData = encodeStatic(x, y); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/store/test/EchoSubscriber.sol b/packages/store/test/EchoSubscriber.sol index 505502dcde..e416d1753c 100644 --- a/packages/store/test/EchoSubscriber.sol +++ b/packages/store/test/EchoSubscriber.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; +import { PackedCounter } from "../src/PackedCounter.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; import { StoreHook } from "../src/StoreHook.sol"; @@ -10,39 +11,43 @@ contract EchoSubscriber is StoreHook { function onBeforeSetRecord( bytes32 tableId, bytes32[] memory keyTuple, - bytes memory data, + bytes memory staticData, + PackedCounter encodedLengths, + bytes memory dynamicData, FieldLayout fieldLayout ) public { - emit HookCalled(abi.encode(tableId, keyTuple, data, fieldLayout)); + emit HookCalled(abi.encode(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout)); } function onAfterSetRecord( bytes32 tableId, bytes32[] memory keyTuple, - bytes memory data, + bytes memory staticData, + PackedCounter encodedLengths, + bytes memory dynamicData, FieldLayout fieldLayout ) public { - emit HookCalled(abi.encode(tableId, keyTuple, data, fieldLayout)); + emit HookCalled(abi.encode(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout)); } function onBeforeSetField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes memory data, FieldLayout fieldLayout ) public { - emit HookCalled(abi.encode(tableId, keyTuple, schemaIndex, data, fieldLayout)); + emit HookCalled(abi.encode(tableId, keyTuple, fieldIndex, data, fieldLayout)); } function onAfterSetField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes memory data, FieldLayout fieldLayout ) public { - emit HookCalled(abi.encode(tableId, keyTuple, schemaIndex, data, fieldLayout)); + emit HookCalled(abi.encode(tableId, keyTuple, fieldIndex, data, fieldLayout)); } function onBeforeDeleteRecord(bytes32 tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) public { diff --git a/packages/store/test/Gas.t.sol b/packages/store/test/Gas.t.sol index 884b019ebd..ea0a6299e9 100644 --- a/packages/store/test/Gas.t.sol +++ b/packages/store/test/Gas.t.sol @@ -6,6 +6,7 @@ import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { Bytes } from "../src/Bytes.sol"; import { SliceLib } from "../src/Slice.sol"; import { Storage } from "../src/Storage.sol"; +import { PackedCounter } from "../src/PackedCounter.sol"; import { Mixed, MixedData } from "../src/codegen/Tables.sol"; contract SomeContract { @@ -21,6 +22,14 @@ contract GasTest is Test, GasReporter { mixed.a32[1] = 2; mixed.a32[2] = 3; + startGasReport("abi encode (static)"); + bytes memory abiEncodedStatic = abi.encode(mixed.u32, mixed.u128); + endGasReport(); + + startGasReport("abi encode (dynamic)"); + bytes memory abiEncodedDynamic = abi.encode(mixed.a32, mixed.s); + endGasReport(); + startGasReport("abi encode"); bytes memory abiEncoded = abi.encode(mixed); endGasReport(); @@ -29,6 +38,19 @@ contract GasTest is Test, GasReporter { MixedData memory abiDecoded = abi.decode(abiEncoded, (MixedData)); endGasReport(); + startGasReport("custom encode (static)"); + bytes memory customEncodedStatic = Mixed.encodeStatic(mixed.u32, mixed.u128); + endGasReport(); + + startGasReport("custom encode (length)"); + PackedCounter packedCounter = Mixed.encodeLengths(mixed.a32, mixed.s); + endGasReport(); + PackedCounter.unwrap(packedCounter); + + startGasReport("custom encode (dynamic)"); + bytes memory customEncodedDynamic = Mixed.encodeDynamic(mixed.a32, mixed.s); + endGasReport(); + startGasReport("custom encode"); bytes memory customEncoded = Mixed.encode(mixed.u32, mixed.u128, mixed.a32, mixed.s); endGasReport(); @@ -38,6 +60,16 @@ contract GasTest is Test, GasReporter { endGasReport(); console.log("Length comparison: abi encode %s, custom %s", abiEncoded.length, customEncoded.length); + console.log( + "Length comparison (static): abi encode %s, custom %s", + abiEncodedStatic.length, + customEncodedStatic.length + ); + console.log( + "Length comparison (dynamic): abi encode %s, custom %s", + abiEncodedDynamic.length, + customEncodedDynamic.length + ); startGasReport("pass abi encoded bytes to external contract"); someContract.doSomethingWithBytes(abiEncoded); diff --git a/packages/store/test/MirrorSubscriber.sol b/packages/store/test/MirrorSubscriber.sol index 34d6179682..38681feb23 100644 --- a/packages/store/test/MirrorSubscriber.sol +++ b/packages/store/test/MirrorSubscriber.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.0; import { IStore } from "../src/IStore.sol"; import { StoreHook } from "../src/StoreHook.sol"; +import { PackedCounter } from "../src/PackedCounter.sol"; import { StoreSwitch } from "../src/StoreSwitch.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; import { Schema } from "../src/Schema.sol"; @@ -27,17 +28,21 @@ contract MirrorSubscriber is StoreHook { function onBeforeSetRecord( bytes32 tableId, bytes32[] memory keyTuple, - bytes memory data, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, FieldLayout fieldLayout ) public { - if (tableId != tableId) revert("invalid tableId"); - StoreSwitch.setRecord(indexerTableId, keyTuple, data, fieldLayout); + if (tableId != _tableId) revert("invalid table"); + StoreSwitch.setRecord(indexerTableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); } function onAfterSetRecord( bytes32 tableId, bytes32[] memory keyTuple, - bytes memory data, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, FieldLayout fieldLayout ) public { // NOOP @@ -46,12 +51,12 @@ contract MirrorSubscriber is StoreHook { function onBeforeSetField( bytes32 tableId, bytes32[] memory keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes memory data, FieldLayout fieldLayout ) public { if (tableId != tableId) revert("invalid tableId"); - StoreSwitch.setField(indexerTableId, keyTuple, schemaIndex, data, fieldLayout); + StoreSwitch.setField(indexerTableId, keyTuple, fieldIndex, data, fieldLayout); } function onAfterSetField(bytes32, bytes32[] memory, uint8, bytes memory, FieldLayout) public { diff --git a/packages/store/test/PackedCounter.t.sol b/packages/store/test/PackedCounter.t.sol index 5da1cfcf2e..18b8bb14e9 100644 --- a/packages/store/test/PackedCounter.t.sol +++ b/packages/store/test/PackedCounter.t.sol @@ -102,4 +102,9 @@ contract PackedCounterTest is Test, GasReporter { endGasReport(); assertEq(packedCounter.total(), 1 * 32 + 2 * 20 + 3 * 1 + 4 * 16); } + + function testHexEncoding() public { + PackedCounter packedCounter = PackedCounterLib.pack(160, 544); + assertEq(packedCounter.unwrap(), hex"000000000000000000000000000000000000022000000000a0000000000002c0"); + } } diff --git a/packages/store/test/RevertSubscriber.sol b/packages/store/test/RevertSubscriber.sol index 2d157d9850..7c2ae092f7 100644 --- a/packages/store/test/RevertSubscriber.sol +++ b/packages/store/test/RevertSubscriber.sol @@ -1,15 +1,30 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import { FieldLayout } from "../src/FieldLayout.sol"; import { StoreHook } from "../src/StoreHook.sol"; +import { FieldLayout } from "../src/FieldLayout.sol"; +import { PackedCounter } from "../src/PackedCounter.sol"; contract RevertSubscriber is StoreHook { - function onBeforeSetRecord(bytes32, bytes32[] memory, bytes memory, FieldLayout) public pure { + function onBeforeSetRecord( + bytes32, + bytes32[] memory, + bytes memory, + PackedCounter, + bytes memory, + FieldLayout + ) public pure { revert("onBeforeSetRecord"); } - function onAfterSetRecord(bytes32, bytes32[] memory, bytes memory, FieldLayout) public pure { + function onAfterSetRecord( + bytes32, + bytes32[] memory, + bytes memory, + PackedCounter, + bytes memory, + FieldLayout + ) public pure { revert("onAfterSetRecord"); } diff --git a/packages/store/test/StoreCore.t.sol b/packages/store/test/StoreCore.t.sol index 6f502597f2..fc1f25134e 100644 --- a/packages/store/test/StoreCore.t.sol +++ b/packages/store/test/StoreCore.t.sol @@ -64,13 +64,9 @@ contract StoreCoreTest is Test, StoreMock { emit StoreSetRecord( TablesTableId, keyTuple, - Tables.encode( - fieldLayout.unwrap(), - keySchema.unwrap(), - valueSchema.unwrap(), - abi.encode(keyNames), - abi.encode(fieldNames) - ) + Tables.encodeStatic(fieldLayout.unwrap(), keySchema.unwrap(), valueSchema.unwrap()), + Tables.encodeLengths(abi.encode(keyNames), abi.encode(fieldNames)).unwrap(), + Tables.encodeDynamic(abi.encode(keyNames), abi.encode(fieldNames)) ); IStore(this).registerTable(tableId, fieldLayout, keySchema, valueSchema, keyNames, fieldNames); @@ -227,21 +223,21 @@ contract StoreCoreTest is Test, StoreMock { IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](4)); // Set data - bytes memory data = abi.encodePacked(bytes1(0x01), bytes2(0x0203), bytes1(0x04), bytes2(0x0506)); + bytes memory staticData = abi.encodePacked(bytes1(0x01), bytes2(0x0203), bytes1(0x04), bytes2(0x0506)); bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = "some key"; // Expect a StoreSetRecord event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetRecord(tableId, keyTuple, data); + emit StoreSetRecord(tableId, keyTuple, staticData, bytes32(0), new bytes(0)); - IStore(this).setRecord(tableId, keyTuple, data, fieldLayout); + IStore(this).setRecord(tableId, keyTuple, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout); // Get data bytes memory loadedData = IStore(this).getRecord(tableId, keyTuple, fieldLayout); - assertTrue(Bytes.equals(data, loadedData)); + assertTrue(Bytes.equals(staticData, loadedData)); } function testFailSetAndGetStaticData() public { @@ -257,24 +253,26 @@ contract StoreCoreTest is Test, StoreMock { IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](4)); // Set data - bytes memory data = abi.encodePacked(bytes1(0x01), bytes2(0x0203), bytes1(0x04)); + bytes memory staticData = abi.encodePacked(bytes1(0x01), bytes2(0x0203), bytes1(0x04)); bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = "some key"; // This should fail because the data is not 6 bytes long - IStore(this).setRecord(tableId, keyTuple, data, fieldLayout); + IStore(this).setRecord(tableId, keyTuple, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout); } function testSetAndGetStaticDataSpanningWords() public { // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 32, 0); - Schema valueSchema = SchemaEncodeHelper.encode(SchemaType.UINT128, SchemaType.UINT256); - bytes32 tableId = keccak256("some.tableId"); - IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](2)); + bytes32 tableId = keccak256("some.table"); + { + Schema valueSchema = SchemaEncodeHelper.encode(SchemaType.UINT128, SchemaType.UINT256); + IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](2)); + } // Set data - bytes memory data = abi.encodePacked( + bytes memory staticData = abi.encodePacked( bytes16(0x0102030405060708090a0b0c0d0e0f10), bytes32(0x1112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30) ); @@ -284,14 +282,14 @@ contract StoreCoreTest is Test, StoreMock { // Expect a StoreSetRecord event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetRecord(tableId, keyTuple, data); + emit StoreSetRecord(tableId, keyTuple, staticData, bytes32(0), new bytes(0)); - IStore(this).setRecord(tableId, keyTuple, data, fieldLayout); + IStore(this).setRecord(tableId, keyTuple, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout); // Get data bytes memory loadedData = IStore(this).getRecord(tableId, keyTuple, fieldLayout); - assertTrue(Bytes.equals(data, loadedData)); + assertTrue(Bytes.equals(staticData, loadedData)); } function testSetAndGetDynamicData() public { @@ -299,12 +297,14 @@ contract StoreCoreTest is Test, StoreMock { // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 2); - Schema valueSchema = SchemaEncodeHelper.encode( - SchemaType.UINT128, - SchemaType.UINT32_ARRAY, - SchemaType.UINT32_ARRAY - ); - IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](3)); + { + Schema valueSchema = SchemaEncodeHelper.encode( + SchemaType.UINT128, + SchemaType.UINT32_ARRAY, + SchemaType.UINT32_ARRAY + ); + IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](3)); + } bytes16 firstDataBytes = bytes16(0x0102030405060708090a0b0c0d0e0f10); @@ -331,6 +331,8 @@ contract StoreCoreTest is Test, StoreMock { } // Concat data + bytes memory staticData = abi.encodePacked(firstDataBytes); + bytes memory dynamicData = abi.encodePacked(secondDataBytes, thirdDataBytes); bytes memory data = abi.encodePacked( firstDataBytes, encodedDynamicLength.unwrap(), @@ -344,10 +346,10 @@ contract StoreCoreTest is Test, StoreMock { // Expect a StoreSetRecord event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetRecord(tableId, keyTuple, data); + emit StoreSetRecord(tableId, keyTuple, staticData, encodedDynamicLength.unwrap(), dynamicData); // Set data - IStore(this).setRecord(tableId, keyTuple, data, fieldLayout); + IStore(this).setRecord(tableId, keyTuple, staticData, encodedDynamicLength, dynamicData, fieldLayout); // Get data bytes memory loadedData = IStore(this).getRecord(tableId, keyTuple, fieldLayout); @@ -374,13 +376,15 @@ contract StoreCoreTest is Test, StoreMock { // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 32, 2); - Schema valueSchema = SchemaEncodeHelper.encode( - SchemaType.UINT128, - SchemaType.UINT256, - SchemaType.UINT32_ARRAY, - SchemaType.UINT32_ARRAY - ); - IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](4)); + { + Schema valueSchema = SchemaEncodeHelper.encode( + SchemaType.UINT128, + SchemaType.UINT256, + SchemaType.UINT32_ARRAY, + SchemaType.UINT32_ARRAY + ); + IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](4)); + } bytes16 firstDataBytes = bytes16(0x0102030405060708090a0b0c0d0e0f10); @@ -390,9 +394,9 @@ contract StoreCoreTest is Test, StoreMock { bytes memory firstDataPacked = abi.encodePacked(firstDataBytes); - // Expect a StoreSetField event to be emitted + // Expect a StoreSpliceStaticData event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(tableId, keyTuple, 0, firstDataPacked); + emit StoreSpliceStaticData(tableId, keyTuple, 0, uint40(firstDataPacked.length), firstDataPacked); // Set first field IStore(this).setField(tableId, keyTuple, 0, firstDataPacked, fieldLayout); @@ -416,9 +420,15 @@ contract StoreCoreTest is Test, StoreMock { bytes memory secondDataPacked = abi.encodePacked(secondDataBytes); - // Expect a StoreSetField event to be emitted + // Expect a StoreSpliceRecord event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(tableId, keyTuple, 1, secondDataPacked); + emit StoreSpliceStaticData( + tableId, + keyTuple, + uint48(firstDataPacked.length), + uint40(secondDataPacked.length), + secondDataPacked + ); IStore(this).setField(tableId, keyTuple, 1, secondDataPacked, fieldLayout); @@ -463,9 +473,16 @@ contract StoreCoreTest is Test, StoreMock { fourthDataBytes = EncodeArray.encode(fourthData); } - // Expect a StoreSetField event to be emitted + // Expect a StoreSpliceRecord event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(tableId, keyTuple, 2, thirdDataBytes); + emit StoreSpliceDynamicData( + tableId, + keyTuple, + uint48(0), + 0, + thirdDataBytes, + PackedCounterLib.pack(thirdDataBytes.length, 0).unwrap() + ); // Set third field IStore(this).setField(tableId, keyTuple, 2, thirdDataBytes, fieldLayout); @@ -485,9 +502,16 @@ contract StoreCoreTest is Test, StoreMock { assertEq(bytes16(IStore(this).getField(tableId, keyTuple, 0, fieldLayout)), bytes16(firstDataBytes)); assertEq(bytes32(IStore(this).getField(tableId, keyTuple, 1, fieldLayout)), bytes32(secondDataBytes)); - // Expect a StoreSetField event to be emitted + // Expect a StoreSpliceRecord event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(tableId, keyTuple, 3, fourthDataBytes); + emit StoreSpliceDynamicData( + tableId, + keyTuple, + uint48(thirdDataBytes.length), + 0, + fourthDataBytes, + PackedCounterLib.pack(thirdDataBytes.length, fourthDataBytes.length).unwrap() + ); // Set fourth field IStore(this).setField(tableId, keyTuple, 3, fourthDataBytes, fieldLayout); @@ -507,6 +531,30 @@ contract StoreCoreTest is Test, StoreMock { abi.encodePacked(firstDataBytes, secondDataBytes, encodedLengths.unwrap(), thirdDataBytes, fourthDataBytes) ) ); + + // Set fourth field again, changing it to be equal to third field + // (non-zero deleteCount must be emitted when the array exists) + + // Expect a StoreSpliceRecord event to be emitted + vm.expectEmit(true, true, true, true); + emit StoreSpliceDynamicData( + tableId, + keyTuple, + uint48(thirdDataBytes.length), + uint40(fourthDataBytes.length), + thirdDataBytes, + PackedCounterLib.pack(thirdDataBytes.length, thirdDataBytes.length).unwrap() + ); + + // Set fourth field + IStore(this).setField(tableId, keyTuple, 3, thirdDataBytes, fieldLayout); + + // Get fourth field + loadedData = IStore(this).getField(tableId, keyTuple, 3, fieldLayout); + + // Verify loaded data is correct + assertEq(loadedData.length, thirdDataBytes.length); + assertEq(keccak256(loadedData), keccak256(thirdDataBytes)); } function testDeleteData() public { @@ -514,12 +562,14 @@ contract StoreCoreTest is Test, StoreMock { // Register table FieldLayout fieldLayout = FieldLayoutEncodeHelper.encode(16, 2); - Schema valueSchema = SchemaEncodeHelper.encode( - SchemaType.UINT128, - SchemaType.UINT32_ARRAY, - SchemaType.UINT32_ARRAY - ); - IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](3)); + { + Schema valueSchema = SchemaEncodeHelper.encode( + SchemaType.UINT128, + SchemaType.UINT32_ARRAY, + SchemaType.UINT32_ARRAY + ); + IStore(this).registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](3)); + } bytes16 firstDataBytes = bytes16(0x0102030405060708090a0b0c0d0e0f10); @@ -546,6 +596,8 @@ contract StoreCoreTest is Test, StoreMock { } // Concat data + bytes memory staticData = abi.encodePacked(firstDataBytes); + bytes memory dynamicData = abi.encodePacked(secondDataBytes, thirdDataBytes); bytes memory data = abi.encodePacked( firstDataBytes, encodedDynamicLength.unwrap(), @@ -558,7 +610,7 @@ contract StoreCoreTest is Test, StoreMock { keyTuple[0] = bytes32("some key"); // Set data - IStore(this).setRecord(tableId, keyTuple, data, fieldLayout); + IStore(this).setRecord(tableId, keyTuple, staticData, encodedDynamicLength, dynamicData, fieldLayout); // Get data bytes memory loadedData = IStore(this).getRecord(tableId, keyTuple, fieldLayout); @@ -647,9 +699,16 @@ contract StoreCoreTest is Test, StoreMock { } data.newSecondDataBytes = abi.encodePacked(data.secondDataBytes, data.secondDataToPush); - // Expect a StoreSetField event to be emitted + // Expect a StoreSpliceDynamicData event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(data.tableId, data.keyTuple, 1, data.newSecondDataBytes); + emit StoreSpliceDynamicData( + data.tableId, + data.keyTuple, + uint48(data.secondDataBytes.length), + 0, + data.secondDataToPush, + PackedCounterLib.pack(data.newSecondDataBytes.length, data.thirdDataBytes.length).unwrap() + ); // Push to second field IStore(this).pushToField(data.tableId, data.keyTuple, 1, data.secondDataToPush, fieldLayout); @@ -683,9 +742,16 @@ contract StoreCoreTest is Test, StoreMock { } data.newThirdDataBytes = abi.encodePacked(data.thirdDataBytes, data.thirdDataToPush); - // Expect a StoreSetField event to be emitted + // Expect a StoreSpliceRecord event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(data.tableId, data.keyTuple, 2, data.newThirdDataBytes); + emit StoreSpliceDynamicData( + data.tableId, + data.keyTuple, + uint48(data.newSecondDataBytes.length + data.thirdDataBytes.length), + 0, + data.thirdDataToPush, + PackedCounterLib.pack(data.newSecondDataBytes.length, data.newThirdDataBytes.length).unwrap() + ); // Push to third field IStore(this).pushToField(data.tableId, data.keyTuple, 2, data.thirdDataToPush, fieldLayout); @@ -786,9 +852,16 @@ contract StoreCoreTest is Test, StoreMock { data.newSecondDataBytes = abi.encodePacked(data.secondData[0], _secondDataForUpdate[0]); } - // Expect a StoreSetField event to be emitted + // Expect a StoreSpliceRecord event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(data.tableId, data.keyTuple, 1, data.newSecondDataBytes); + emit StoreSpliceDynamicData( + data.tableId, + data.keyTuple, + uint48(4 * 1), + 4 * 1, + data.secondDataForUpdate, + PackedCounterLib.pack(data.newSecondDataBytes.length, data.thirdDataBytes.length).unwrap() + ); // Update index 1 in second field (4 = byte length of uint32) IStore(this).updateInField(data.tableId, data.keyTuple, 1, 4 * 1, data.secondDataForUpdate, fieldLayout); @@ -824,9 +897,16 @@ contract StoreCoreTest is Test, StoreMock { ); } - // Expect a StoreSetField event to be emitted + // Expect a StoreSpliceRecord event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(data.tableId, data.keyTuple, 2, data.newThirdDataBytes); + emit StoreSpliceDynamicData( + data.tableId, + data.keyTuple, + uint48(data.newSecondDataBytes.length + 8 * 1), + 8 * 4, + data.thirdDataForUpdate, + PackedCounterLib.pack(data.newSecondDataBytes.length, data.newThirdDataBytes.length).unwrap() + ); // Update indexes 1,2,3,4 in third field (8 = byte length of uint64) IStore(this).updateInField(data.tableId, data.keyTuple, 2, 8 * 1, data.thirdDataForUpdate, fieldLayout); @@ -910,21 +990,21 @@ contract StoreCoreTest is Test, StoreMock { }) ); - bytes memory data = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); + bytes memory staticData = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); - IStore(this).setRecord(tableId, keyTuple, data, fieldLayout); + IStore(this).setRecord(tableId, keyTuple, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout); // Get data from indexed table - the indexer should have mirrored the data there bytes memory indexedData = IStore(this).getRecord(indexerTableId, keyTuple, fieldLayout); - assertEq(keccak256(data), keccak256(indexedData)); + assertEq(keccak256(staticData), keccak256(indexedData)); - data = abi.encodePacked(bytes16(0x1112131415161718191a1b1c1d1e1f20)); + staticData = abi.encodePacked(bytes16(0x1112131415161718191a1b1c1d1e1f20)); - IStore(this).setField(tableId, keyTuple, 0, data, fieldLayout); + IStore(this).setField(tableId, keyTuple, 0, staticData, fieldLayout); // Get data from indexed table - the indexer should have mirrored the data there indexedData = IStore(this).getRecord(indexerTableId, keyTuple, fieldLayout); - assertEq(keccak256(data), keccak256(indexedData)); + assertEq(keccak256(staticData), keccak256(indexedData)); IStore(this).deleteRecord(tableId, keyTuple, fieldLayout); @@ -978,7 +1058,7 @@ contract StoreCoreTest is Test, StoreMock { // Expect a revert when the RevertSubscriber's onBeforeSetRecord hook is called vm.expectRevert(bytes("onBeforeSetRecord")); - IStore(this).setRecord(tableId, keyTuple, data, fieldLayout); + IStore(this).setRecord(tableId, keyTuple, data, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout); // Expect a revert when the RevertSubscriber's onBeforeSetField hook is called vm.expectRevert(bytes("onBeforeSetField")); @@ -993,13 +1073,13 @@ contract StoreCoreTest is Test, StoreMock { // Expect a HookCalled event to be emitted when the EchoSubscriber's onBeforeSetRecord hook is called vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, keyTuple, data, fieldLayout)); + emit HookCalled(abi.encode(tableId, keyTuple, data, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout)); // Expect a HookCalled event to be emitted when the EchoSubscriber's onAfterSetRecord hook is called vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, keyTuple, data, fieldLayout)); + emit HookCalled(abi.encode(tableId, keyTuple, data, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout)); - IStore(this).setRecord(tableId, keyTuple, data, fieldLayout); + IStore(this).setRecord(tableId, keyTuple, data, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout); // Expect a HookCalled event to be emitted when the EchoSubscriber's onBeforeSetField hook is called vm.expectEmit(true, true, true, true); @@ -1059,11 +1139,11 @@ contract StoreCoreTest is Test, StoreMock { arrayData[0] = 0x01020304; bytes memory arrayDataBytes = EncodeArray.encode(arrayData); PackedCounter encodedArrayDataLength = PackedCounterLib.pack(uint40(arrayDataBytes.length)); - bytes memory dynamicData = abi.encodePacked(encodedArrayDataLength.unwrap(), arrayDataBytes); + bytes memory dynamicData = arrayDataBytes; bytes memory staticData = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); - bytes memory data = abi.encodePacked(staticData, dynamicData); + bytes memory data = abi.encodePacked(staticData, encodedArrayDataLength, dynamicData); - IStore(this).setRecord(tableId, keyTuple, data, fieldLayout); + IStore(this).setRecord(tableId, keyTuple, staticData, encodedArrayDataLength, dynamicData, fieldLayout); // Get data from indexed table - the indexer should have mirrored the data there bytes memory indexedData = IStore(this).getRecord(indexerTableId, keyTuple, fieldLayout); @@ -1072,8 +1152,8 @@ contract StoreCoreTest is Test, StoreMock { // Update dynamic data arrayData[0] = 0x11121314; arrayDataBytes = EncodeArray.encode(arrayData); - dynamicData = abi.encodePacked(encodedArrayDataLength.unwrap(), arrayDataBytes); - data = abi.encodePacked(staticData, dynamicData); + dynamicData = arrayDataBytes; + data = abi.encodePacked(staticData, encodedArrayDataLength, dynamicData); IStore(this).setField(tableId, keyTuple, 1, arrayDataBytes, fieldLayout); diff --git a/packages/store/test/StoreCoreDynamic.t.sol b/packages/store/test/StoreCoreDynamic.t.sol index 28c25130a0..d5979239c3 100644 --- a/packages/store/test/StoreCoreDynamic.t.sol +++ b/packages/store/test/StoreCoreDynamic.t.sol @@ -7,6 +7,7 @@ import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol" import { StoreCore } from "../src/StoreCore.sol"; import { SliceLib } from "../src/Slice.sol"; import { EncodeArray } from "../src/tightcoder/EncodeArray.sol"; +import { PackedCounterLib } from "../src/PackedCounter.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; import { Schema } from "../src/Schema.sol"; import { StoreMock } from "../test/StoreMock.sol"; @@ -29,11 +30,11 @@ contract StoreCoreDynamicTest is Test, GasReporter, StoreMock { function popFromField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, uint256 byteLengthToPop, FieldLayout fieldLayout ) public override { - StoreCore.popFromField(tableId, keyTuple, schemaIndex, byteLengthToPop, fieldLayout); + StoreCore.popFromField(tableId, keyTuple, fieldIndex, byteLengthToPop, fieldLayout); } function setUp() public { @@ -90,9 +91,16 @@ contract StoreCoreDynamicTest is Test, GasReporter, StoreMock { assertEq(SliceLib.fromBytes(dataBytes).decodeArray_uint32().length, 2); assertEq(SliceLib.fromBytes(newDataBytes).decodeArray_uint32().length, 2 - 1); - // Expect a StoreSetField event to be emitted + // Expect a StoreSpliceRecord event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(_tableId, _keyTuple, 1, newDataBytes); + emit StoreSpliceDynamicData( + _tableId, + _keyTuple, + uint48(secondDataBytes.length - byteLengthToPop), + uint40(byteLengthToPop), + new bytes(0), + PackedCounterLib.pack(newDataBytes.length, thirdDataBytes.length).unwrap() + ); // Pop from second field startGasReport("pop from field (cold, 1 slot, 1 uint32 item)"); @@ -129,9 +137,16 @@ contract StoreCoreDynamicTest is Test, GasReporter, StoreMock { assertEq(SliceLib.fromBytes(dataBytes).decodeArray_uint32().length, 10); assertEq(SliceLib.fromBytes(newDataBytes).decodeArray_uint32().length, 10 - 10); - // Expect a StoreSetField event to be emitted after pop + // Expect a StoreSpliceRecord event to be emitted after pop vm.expectEmit(true, true, true, true); - emit StoreSetField(_tableId, _keyTuple, 2, dataBytes); + emit StoreSpliceDynamicData( + _tableId, + _keyTuple, + uint48(secondDataBytes.length + thirdDataBytes.length - byteLengthToPop), + uint40(byteLengthToPop), + new bytes(0), + PackedCounterLib.pack(secondDataBytes.length, newDataBytes.length).unwrap() + ); // Pop from the field startGasReport("pop from field (cold, 2 slots, 10 uint32 items)"); diff --git a/packages/store/test/StoreCoreGas.t.sol b/packages/store/test/StoreCoreGas.t.sol index badbc33472..5c30514ccd 100644 --- a/packages/store/test/StoreCoreGas.t.sol +++ b/packages/store/test/StoreCoreGas.t.sol @@ -139,12 +139,13 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { StoreCore.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](4)); // Set data - bytes memory data = abi.encodePacked(bytes1(0x01), bytes2(0x0203), bytes1(0x04), bytes2(0x0506)); + bytes memory staticData = abi.encodePacked(bytes1(0x01), bytes2(0x0203), bytes1(0x04), bytes2(0x0506)); + bytes memory dynamicData = new bytes(0); bytes32[] memory keyTuple = new bytes32[](1); - keyTuple[0] = "some key"; + keyTuple[0] = keccak256("some.key"); startGasReport("set static record (1 slot)"); - StoreCore.setRecord(tableId, keyTuple, data, fieldLayout); + StoreCore.setRecord(tableId, keyTuple, staticData, PackedCounter.wrap(bytes32(0)), dynamicData, fieldLayout); endGasReport(); // Get data @@ -161,16 +162,17 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { StoreCore.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](2)); // Set data - bytes memory data = abi.encodePacked( + bytes memory staticData = abi.encodePacked( bytes16(0x0102030405060708090a0b0c0d0e0f10), bytes32(0x1112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30) ); + bytes memory dynamicData = new bytes(0); bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = "some key"; startGasReport("set static record (2 slots)"); - StoreCore.setRecord(tableId, keyTuple, data, fieldLayout); + StoreCore.setRecord(tableId, keyTuple, staticData, PackedCounter.wrap(bytes32(0)), dynamicData, fieldLayout); endGasReport(); // Get data @@ -216,12 +218,8 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { ); // Concat data - bytes memory data = abi.encodePacked( - firstDataBytes, - encodedDynamicLength.unwrap(), - secondDataBytes, - thirdDataBytes - ); + bytes memory staticData = abi.encodePacked(firstDataBytes); + bytes memory dynamicData = abi.encodePacked(secondDataBytes, thirdDataBytes); // Create keyTuple bytes32[] memory keyTuple = new bytes32[](1); @@ -229,7 +227,7 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { // Set data startGasReport("set complex record with dynamic data (4 slots)"); - StoreCore.setRecord(tableId, keyTuple, data, fieldLayout); + StoreCore.setRecord(tableId, keyTuple, staticData, encodedDynamicLength, dynamicData, fieldLayout); endGasReport(); // Get data @@ -382,19 +380,15 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { ); // Concat data - bytes memory data = abi.encodePacked( - firstDataBytes, - encodedDynamicLength.unwrap(), - secondDataBytes, - thirdDataBytes - ); + bytes memory staticData = abi.encodePacked(firstDataBytes); + bytes memory dynamicData = abi.encodePacked(secondDataBytes, thirdDataBytes); // Create keyTuple bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = "some key"; // Set data - StoreCore.setRecord(tableId, keyTuple, data, fieldLayout); + StoreCore.setRecord(tableId, keyTuple, staticData, encodedDynamicLength, dynamicData, fieldLayout); // Delete data startGasReport("delete record (complex data, 3 slots)"); @@ -632,16 +626,17 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { ); endGasReport(); - bytes memory data = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); + bytes memory staticData = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); + bytes memory dynamicData = new bytes(0); startGasReport("set record on table with subscriber"); - StoreCore.setRecord(tableId, keyTuple, data, fieldLayout); + StoreCore.setRecord(tableId, keyTuple, staticData, PackedCounter.wrap(bytes32(0)), dynamicData, fieldLayout); endGasReport(); - data = abi.encodePacked(bytes16(0x1112131415161718191a1b1c1d1e1f20)); + staticData = abi.encodePacked(bytes16(0x1112131415161718191a1b1c1d1e1f20)); startGasReport("set static field on table with subscriber"); - StoreCore.setField(tableId, keyTuple, 0, data, fieldLayout); + StoreCore.setField(tableId, keyTuple, 0, staticData, fieldLayout); endGasReport(); startGasReport("delete record on table with subscriber"); @@ -688,19 +683,19 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { arrayData[0] = 0x01020304; bytes memory arrayDataBytes = EncodeArray.encode(arrayData); PackedCounter encodedArrayDataLength = PackedCounterLib.pack(uint40(arrayDataBytes.length)); - bytes memory dynamicData = abi.encodePacked(encodedArrayDataLength.unwrap(), arrayDataBytes); + bytes memory dynamicData = arrayDataBytes; bytes memory staticData = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); - bytes memory data = abi.encodePacked(staticData, dynamicData); + bytes memory data = abi.encodePacked(staticData, encodedArrayDataLength, dynamicData); startGasReport("set (dynamic) record on table with subscriber"); - StoreCore.setRecord(tableId, keyTuple, data, fieldLayout); + StoreCore.setRecord(tableId, keyTuple, staticData, encodedArrayDataLength, dynamicData, fieldLayout); endGasReport(); // Update dynamic data arrayData[0] = 0x11121314; arrayDataBytes = EncodeArray.encode(arrayData); - dynamicData = abi.encodePacked(encodedArrayDataLength.unwrap(), arrayDataBytes); - data = abi.encodePacked(staticData, dynamicData); + dynamicData = arrayDataBytes; + data = abi.encodePacked(staticData, encodedArrayDataLength, dynamicData); startGasReport("set (dynamic) field on table with subscriber"); StoreCore.setField(tableId, keyTuple, 1, arrayDataBytes, fieldLayout); diff --git a/packages/store/test/StoreHook.t.sol b/packages/store/test/StoreHook.t.sol index 56950bd351..311dcbc90a 100644 --- a/packages/store/test/StoreHook.t.sol +++ b/packages/store/test/StoreHook.t.sol @@ -11,6 +11,7 @@ import { Hook } from "../src/Hook.sol"; import { StoreHookType } from "../src/StoreHook.sol"; import { StoreHookLib } from "../src/StoreHook.sol"; import { IStoreHook } from "../src/IStore.sol"; +import { PackedCounter } from "../src/PackedCounter.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; contract StoreHookTest is Test, GasReporter { @@ -21,7 +22,10 @@ contract StoreHookTest is Test, GasReporter { RevertSubscriber private revertSubscriber = new RevertSubscriber(); bytes32 private tableId = "table"; bytes32[] private key = new bytes32[](1); - bytes private data = "data"; + bytes private staticData = abi.encodePacked(bytes32(0)); + PackedCounter private encodedLengths = PackedCounter.wrap(bytes32(0)); + bytes private dynamicData = new bytes(0); + uint8 private fieldIndex = 1; FieldLayout private fieldLayout = FieldLayout.wrap(0); function testEncodeBitmap() public { @@ -278,11 +282,21 @@ contract StoreHookTest is Test, GasReporter { }) ); + // TODO temporary variable until https://github.com/foundry-rs/foundry/issues/5811 is fixed + bytes memory emptyDynamicData = new bytes(0); + vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, key, data, fieldLayout)); + emit HookCalled(abi.encode(tableId, key, staticData, encodedLengths, emptyDynamicData, fieldLayout)); startGasReport("call an enabled hook"); if (storeHook.isEnabled(uint8(StoreHookType.BEFORE_SET_RECORD))) { - IStoreHook(storeHook.getAddress()).onBeforeSetRecord(tableId, key, data, fieldLayout); + IStoreHook(storeHook.getAddress()).onBeforeSetRecord( + tableId, + key, + staticData, + encodedLengths, + dynamicData, + fieldLayout + ); } endGasReport(); @@ -301,7 +315,14 @@ contract StoreHookTest is Test, GasReporter { // Expect the to not be called - otherwise the test will fail with a revert startGasReport("call a disabled hook"); if (revertHook.isEnabled(uint8(StoreHookType.BEFORE_SET_RECORD))) { - IStoreHook(revertHook.getAddress()).onBeforeSetRecord(tableId, key, data, fieldLayout); + IStoreHook(revertHook.getAddress()).onBeforeSetRecord( + tableId, + key, + staticData, + encodedLengths, + dynamicData, + fieldLayout + ); } endGasReport(); } diff --git a/packages/store/test/StoreMock.sol b/packages/store/test/StoreMock.sol index 96e23f6664..9b515b4af5 100644 --- a/packages/store/test/StoreMock.sol +++ b/packages/store/test/StoreMock.sol @@ -2,8 +2,9 @@ pragma solidity >=0.8.0; import { IStore, IStoreHook } from "../src/IStore.sol"; -import { Schema } from "../src/Schema.sol"; +import { PackedCounter } from "../src/PackedCounter.sol"; import { StoreCore } from "../src/StoreCore.sol"; +import { Schema } from "../src/Schema.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; import { StoreRead } from "../src/StoreRead.sol"; @@ -20,55 +21,57 @@ contract StoreMock is IStore, StoreRead { function setRecord( bytes32 tableId, bytes32[] calldata keyTuple, - bytes calldata data, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, FieldLayout fieldLayout - ) public virtual { - StoreCore.setRecord(tableId, keyTuple, data, fieldLayout); + ) public { + StoreCore.setRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); } // Set partial data at schema index function setField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes calldata data, FieldLayout fieldLayout ) public virtual { - StoreCore.setField(tableId, keyTuple, schemaIndex, data, fieldLayout); + StoreCore.setField(tableId, keyTuple, fieldIndex, data, fieldLayout); } // Push encoded items to the dynamic field at schema index function pushToField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes calldata dataToPush, FieldLayout fieldLayout ) public virtual { - StoreCore.pushToField(tableId, keyTuple, schemaIndex, dataToPush, fieldLayout); + StoreCore.pushToField(tableId, keyTuple, fieldIndex, dataToPush, fieldLayout); } // Pop byte length from the dynamic field at schema index function popFromField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, uint256 byteLengthToPop, FieldLayout fieldLayout ) public virtual { - StoreCore.popFromField(tableId, keyTuple, schemaIndex, byteLengthToPop, fieldLayout); + StoreCore.popFromField(tableId, keyTuple, fieldIndex, byteLengthToPop, fieldLayout); } // Change encoded items within the dynamic field at schema index function updateInField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, uint256 startByteIndex, bytes calldata dataToSet, FieldLayout fieldLayout ) public virtual { - StoreCore.updateInField(tableId, keyTuple, schemaIndex, startByteIndex, dataToSet, fieldLayout); + StoreCore.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); } // Set full record (including full dynamic data) @@ -80,10 +83,12 @@ contract StoreMock is IStore, StoreRead { function emitEphemeralRecord( bytes32 tableId, bytes32[] calldata keyTuple, - bytes calldata data, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, FieldLayout fieldLayout - ) public virtual { - StoreCore.emitEphemeralRecord(tableId, keyTuple, data, fieldLayout); + ) public { + StoreCore.emitEphemeralRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); } function registerTable( diff --git a/packages/store/ts/codegen/ephemeral.ts b/packages/store/ts/codegen/ephemeral.ts index c7fbc9ba4f..96182f65fb 100644 --- a/packages/store/ts/codegen/ephemeral.ts +++ b/packages/store/ts/codegen/ephemeral.ts @@ -1,5 +1,6 @@ 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; @@ -15,11 +16,11 @@ export function renderEphemeralMethods(options: RenderTableOptions) { _typedKeyArgs, renderArguments(options.fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`)), ])}) internal { - bytes memory _data = encode(${renderArguments(options.fields.map(({ name }) => name))}); + ${renderRecordData(options)} ${_keyTupleDefinition} - ${_store}.emitEphemeralRecord(_tableId, _keyTuple, _data, getFieldLayout()); + ${_store}.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } ` ); diff --git a/packages/store/ts/codegen/record.ts b/packages/store/ts/codegen/record.ts index f334a01247..b13dfd25d7 100644 --- a/packages/store/ts/codegen/record.ts +++ b/packages/store/ts/codegen/record.ts @@ -38,11 +38,11 @@ export function renderRecordMethods(options: RenderTableOptions) { _typedKeyArgs, renderArguments(options.fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`)), ])}) internal { - bytes memory _data = encode(${renderArguments(options.fields.map(({ name }) => name))}); + ${renderRecordData(options)} ${_keyTupleDefinition} - ${_store}.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + ${_store}.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } ` ); @@ -74,6 +74,31 @@ export function renderRecordMethods(options: RenderTableOptions) { return result; } +export function renderRecordData(options: RenderTableOptions) { + let result = ""; + if (options.staticFields.length > 0) { + result += ` + bytes memory _staticData = encodeStatic(${renderArguments(options.staticFields.map(({ name }) => name))}); + `; + } else { + result += `bytes memory _staticData;`; + } + + if (options.dynamicFields.length > 0) { + result += ` + PackedCounter _encodedLengths = encodeLengths(${renderArguments(options.dynamicFields.map(({ name }) => name))}); + bytes memory _dynamicData = encodeDynamic(${renderArguments(options.dynamicFields.map(({ name }) => name))}); + `; + } else { + result += ` + PackedCounter _encodedLengths; + bytes memory _dynamicData; + `; + } + + return result; +} + // Renders the `decode` function that parses a bytes blob into the table data function renderDecodeFunction({ structName, fields, staticFields, dynamicFields }: RenderTableOptions) { // either set struct properties, or just variables @@ -94,63 +119,63 @@ function renderDecodeFunction({ structName, fields, staticFields, dynamicFields const totalStaticLength = staticFields.reduce((acc, { staticByteLength }) => acc + staticByteLength, 0); // decode static (optionally) and dynamic data return ` - /** - * Decode the tightly packed blob using this table's field layout. - * Undefined behaviour for invalid blobs. - */ - function decode(bytes memory _blob) internal pure returns (${renderedDecodedRecord}) { - // ${totalStaticLength} is the total byte length of static data - PackedCounter _encodedLengths = PackedCounter.wrap(Bytes.slice32(_blob, ${totalStaticLength})); - - ${renderList( - staticFields, - (field, index) => ` - ${fieldNamePrefix}${field.name} = ${renderDecodeValueType(field, staticOffsets[index])}; - ` - )} - // Store trims the blob if dynamic fields are all empty - if (_blob.length > ${totalStaticLength}) { + /** + * Decode the tightly packed blob using this table's field layout. + * Undefined behaviour for invalid blobs. + */ + function decode(bytes memory _blob) internal pure returns (${renderedDecodedRecord}) { + // ${totalStaticLength} is the total byte length of static data + PackedCounter _encodedLengths = PackedCounter.wrap(Bytes.slice32(_blob, ${totalStaticLength})); + ${renderList( - dynamicFields, - // unchecked is only dangerous if _encodedLengths (and _blob) is invalid, - // but it's assumed to be valid, and this function is meant to be mostly used internally - (field, index) => { - if (index === 0) { - return ` - // skip static data length + dynamic lengths word - uint256 _start = ${totalStaticLength + 32}; - uint256 _end; - unchecked { - _end = ${totalStaticLength + 32} + _encodedLengths.atIndex(${index}); - } - ${fieldNamePrefix}${field.name} = ${renderDecodeDynamicFieldPartial(field)}; - `; - } else { - return ` - _start = _end; - unchecked { - _end += _encodedLengths.atIndex(${index}); + staticFields, + (field, index) => ` + ${fieldNamePrefix}${field.name} = ${renderDecodeValueType(field, staticOffsets[index])}; + ` + )} + // Store trims the blob if dynamic fields are all empty + if (_blob.length > ${totalStaticLength}) { + ${renderList( + dynamicFields, + // unchecked is only dangerous if _encodedLengths (and _blob) is invalid, + // but it's assumed to be valid, and this function is meant to be mostly used internally + (field, index) => { + if (index === 0) { + return ` + // skip static data length + dynamic lengths word + uint256 _start = ${totalStaticLength + 32}; + uint256 _end; + unchecked { + _end = ${totalStaticLength + 32} + _encodedLengths.atIndex(${index}); + } + ${fieldNamePrefix}${field.name} = ${renderDecodeDynamicFieldPartial(field)}; + `; + } else { + return ` + _start = _end; + unchecked { + _end += _encodedLengths.atIndex(${index}); + } + ${fieldNamePrefix}${field.name} = ${renderDecodeDynamicFieldPartial(field)}; + `; } - ${fieldNamePrefix}${field.name} = ${renderDecodeDynamicFieldPartial(field)}; - `; } - } - )} + )} + } } - } - `; + `; } else { // decode only static data return ` - /** Decode the tightly packed blob using this table's field layout */ - function decode(bytes memory _blob) internal pure returns (${renderedDecodedRecord}) { - ${renderList( - staticFields, - (field, index) => ` - ${fieldNamePrefix}${field.name} = ${renderDecodeValueType(field, staticOffsets[index])}; - ` - )} - } + /** Decode the tightly packed blob using this table's field layout */ + function decode(bytes memory _blob) internal pure returns (${renderedDecodedRecord}) { + ${renderList( + staticFields, + (field, index) => ` + ${fieldNamePrefix}${field.name} = ${renderDecodeValueType(field, staticOffsets[index])}; + ` + )} + } `; } } diff --git a/packages/store/ts/codegen/renderTable.ts b/packages/store/ts/codegen/renderTable.ts index 8181133cfb..72816bf28f 100644 --- a/packages/store/ts/codegen/renderTable.ts +++ b/packages/store/ts/codegen/renderTable.ts @@ -8,10 +8,11 @@ import { renderWithStore, renderTypeHelpers, RenderDynamicField, + RenderStaticField, } from "@latticexyz/common/codegen"; import { renderEphemeralMethods } from "./ephemeral"; import { renderEncodeFieldSingle, renderFieldMethods } from "./field"; -import { renderRecordMethods } from "./record"; +import { renderRecordData, renderRecordMethods } from "./record"; import { RenderTableOptions } from "./types"; export function renderTable(options: RenderTableOptions) { @@ -113,11 +114,11 @@ export function renderTable(options: RenderTableOptions) { ${renderWithStore( storeArgument, (_typedStore, _store, _commentSuffix) => ` - /** Register the table with its config${_commentSuffix} */ - function register(${renderArguments([_typedStore, _typedTableId])}) internal { - ${_store}.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); - } - ` + /** Register the table with its config${_commentSuffix} */ + function register(${renderArguments([_typedStore, _typedTableId])}) internal { + ${_store}.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + ` )} ${withFieldMethods ? renderFieldMethods(options) : ""} @@ -126,20 +127,19 @@ export function renderTable(options: RenderTableOptions) { ${withEphemeralMethods ? renderEphemeralMethods(options) : ""} + ${renderEncodeStatic(staticFields)} + + ${renderEncodedLengths(dynamicFields)} + + ${renderEncodeDynamic(dynamicFields)} + /** Tightly pack full data using this table's field layout */ function encode(${renderArguments( options.fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`) )}) internal pure returns (bytes memory) { - ${renderEncodedLengths(dynamicFields)} - return abi.encodePacked(${renderArguments([ - renderArguments(staticFields.map(({ name }) => name)), - ...(dynamicFields.length === 0 - ? [] - : [ - "_encodedLengths.unwrap()", - renderArguments(dynamicFields.map((field) => renderEncodeFieldSingle(field))), - ]), - ])}); + ${renderRecordData(options)} + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ @@ -168,26 +168,54 @@ export function renderTable(options: RenderTableOptions) { `; } +function renderEncodeStatic(staticFields: RenderStaticField[]) { + if (staticFields.length === 0) return ""; + + return ` + /** Tightly pack static data using this table's schema */ + function encodeStatic(${renderArguments( + staticFields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`) + )}) internal pure returns (bytes memory) { + return abi.encodePacked(${renderArguments(staticFields.map(({ name }) => name))}); + } + `; +} + function renderEncodedLengths(dynamicFields: RenderDynamicField[]) { - if (dynamicFields.length > 0) { - return ` - PackedCounter _encodedLengths; - // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits - unchecked { - _encodedLengths = PackedCounterLib.pack( - ${renderArguments( - dynamicFields.map(({ name, arrayElement }) => { - if (arrayElement) { - return `${name}.length * ${arrayElement.staticByteLength}`; - } else { - return `bytes(${name}).length`; - } - }) - )} - ); + if (dynamicFields.length === 0) return ""; + + return ` + /** Tightly pack dynamic data using this table's schema */ + function encodeLengths(${renderArguments( + dynamicFields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`) + )}) internal pure returns (PackedCounter _encodedLengths) { + // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits + unchecked { + _encodedLengths = PackedCounterLib.pack( + ${renderArguments( + dynamicFields.map(({ name, arrayElement }) => { + if (arrayElement) { + return `${name}.length * ${arrayElement.staticByteLength}`; + } else { + return `bytes(${name}).length`; + } + }) + )} + ); + } + } + `; +} + +function renderEncodeDynamic(dynamicFields: RenderDynamicField[]) { + if (dynamicFields.length === 0) return ""; + + return ` + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(${renderArguments( + dynamicFields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`) + )}) internal pure returns (bytes memory) { + return abi.encodePacked(${renderArguments(dynamicFields.map((field) => renderEncodeFieldSingle(field)))}); } - `; - } else { - return ""; - } + `; } diff --git a/packages/store/ts/storeEvents.ts b/packages/store/ts/storeEvents.ts index 77b308b8e2..4148e5cd68 100644 --- a/packages/store/ts/storeEvents.ts +++ b/packages/store/ts/storeEvents.ts @@ -1,6 +1,7 @@ export const storeEvents = [ + "event StoreSetRecord(bytes32 tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData)", + "event StoreSpliceStaticData(bytes32 tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data)", + "event StoreSpliceDynamicData(bytes32 tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data, bytes32 encodedLengths)", + "event StoreEphemeralRecord(bytes32 tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData)", "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)", ] as const; diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 30962ed0d7..64b6bfac8c 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -39,73 +39,73 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1519335 + "gasUsed": 1521715 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1519335 + "gasUsed": 1521715 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 183388 + "gasUsed": 187187 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1519335 + "gasUsed": 1521715 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1519335 + "gasUsed": 1521715 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 28498 + "gasUsed": 30396 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 251457 + "gasUsed": 256692 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1519335 + "gasUsed": 1521715 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 27221 + "gasUsed": 29117 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 132823 + "gasUsed": 134551 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 728346 + "gasUsed": 730803 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "Get list of keys with a given value", - "gasUsed": 7508 + "gasUsed": 7584 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,163 +117,163 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 728346 + "gasUsed": 730803 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 157348 + "gasUsed": 159933 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 728346 + "gasUsed": 730803 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 126291 + "gasUsed": 129535 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 49099 + "gasUsed": 49133 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 728346 + "gasUsed": 730803 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 163792 + "gasUsed": 164678 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 128551 + "gasUsed": 129437 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 141196 + "gasUsed": 141735 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 69053 + "gasUsed": 69540 }, { "file": "test/query.t.sol", "test": "testCombinedHasNotQuery", "name": "CombinedHasNotQuery", - "gasUsed": 184150 + "gasUsed": 184268 }, { "file": "test/query.t.sol", "test": "testCombinedHasQuery", "name": "CombinedHasQuery", - "gasUsed": 121994 + "gasUsed": 122085 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 117772 + "gasUsed": 117986 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueQuery", "name": "CombinedHasValueQuery", - "gasUsed": 19164 + "gasUsed": 19461 }, { "file": "test/query.t.sol", "test": "testHasQuery", "name": "HasQuery", - "gasUsed": 27950 + "gasUsed": 27973 }, { "file": "test/query.t.sol", "test": "testHasQuery1000Keys", "name": "HasQuery with 1000 keys", - "gasUsed": 7068010 + "gasUsed": 7118904 }, { "file": "test/query.t.sol", "test": "testHasQuery100Keys", "name": "HasQuery with 100 keys", - "gasUsed": 672230 + "gasUsed": 672769 }, { "file": "test/query.t.sol", "test": "testHasValueQuery", "name": "HasValueQuery", - "gasUsed": 9259 + "gasUsed": 9401 }, { "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 62652 + "gasUsed": 63136 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 133325 + "gasUsed": 133856 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 49383 + "gasUsed": 49405 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 127681 + "gasUsed": 128205 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 38474 + "gasUsed": 38496 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 787645 + "gasUsed": 790963 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 67456 + "gasUsed": 67727 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 771167 + "gasUsed": 774507 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 67456 + "gasUsed": 67727 }, { "file": "test/World.t.sol", @@ -285,96 +285,96 @@ "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 59044 + "gasUsed": 59312 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "call a system via an unlimited delegation", - "gasUsed": 19950 + "gasUsed": 19972 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 13886 + "gasUsed": 13885 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 93261 + "gasUsed": 93919 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 75414 + "gasUsed": 75955 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 68663 + "gasUsed": 69204 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 96008 + "gasUsed": 96549 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 146378 + "gasUsed": 147155 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 90581 + "gasUsed": 91122 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 685344 + "gasUsed": 686517 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 41899 + "gasUsed": 42174 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 41344 + "gasUsed": 41619 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 32940 + "gasUsed": 32933 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 19729 + "gasUsed": 20046 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 35373 + "gasUsed": 36456 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 22578 + "gasUsed": 23661 } ] diff --git a/packages/world/src/World.sol b/packages/world/src/World.sol index 1c80c16249..f813a96f46 100644 --- a/packages/world/src/World.sol +++ b/packages/world/src/World.sol @@ -6,6 +6,8 @@ import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { IStoreData } from "@latticexyz/store/src/IStore.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Schema } from "@latticexyz/store/src/Schema.sol"; +import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; import { System } from "./System.sol"; @@ -98,14 +100,16 @@ contract World is StoreRead, IStoreData, IWorldKernel { function setRecord( bytes32 tableId, bytes32[] calldata keyTuple, - bytes calldata data, + 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.setRecord(tableId, keyTuple, data, fieldLayout); + StoreCore.setRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData, fieldLayout); } /** @@ -115,7 +119,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { function setField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes calldata data, FieldLayout fieldLayout ) public virtual { @@ -123,7 +127,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { AccessControl.requireAccess(tableId, msg.sender); // Set the field - StoreCore.setField(tableId, keyTuple, schemaIndex, data, fieldLayout); + StoreCore.setField(tableId, keyTuple, fieldIndex, data, fieldLayout); } /** @@ -133,7 +137,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { function pushToField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, bytes calldata dataToPush, FieldLayout fieldLayout ) public virtual { @@ -141,7 +145,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { AccessControl.requireAccess(tableId, msg.sender); // Push to the field - StoreCore.pushToField(tableId, keyTuple, schemaIndex, dataToPush, fieldLayout); + StoreCore.pushToField(tableId, keyTuple, fieldIndex, dataToPush, fieldLayout); } /** @@ -151,7 +155,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { function popFromField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, uint256 byteLengthToPop, FieldLayout fieldLayout ) public virtual { @@ -159,7 +163,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { AccessControl.requireAccess(tableId, msg.sender); // Push to the field - StoreCore.popFromField(tableId, keyTuple, schemaIndex, byteLengthToPop, fieldLayout); + StoreCore.popFromField(tableId, keyTuple, fieldIndex, byteLengthToPop, fieldLayout); } /** @@ -169,7 +173,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { function updateInField( bytes32 tableId, bytes32[] calldata keyTuple, - uint8 schemaIndex, + uint8 fieldIndex, uint256 startByteIndex, bytes calldata dataToSet, FieldLayout fieldLayout @@ -178,7 +182,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { AccessControl.requireAccess(tableId, msg.sender); // Update data in the field - StoreCore.updateInField(tableId, keyTuple, schemaIndex, startByteIndex, dataToSet, fieldLayout); + StoreCore.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); } /** diff --git a/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol b/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol index 5a41ebf30b..35f2309d8c 100644 --- a/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol +++ b/packages/world/src/modules/core/implementations/EphemeralRecordSystem.sol @@ -2,12 +2,12 @@ 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 { IModule } from "../../../interfaces/IModule.sol"; import { System } from "../../../System.sol"; import { ResourceSelector } from "../../../ResourceSelector.sol"; import { AccessControl } from "../../../AccessControl.sol"; -import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; contract EphemeralRecordSystem is IStoreEphemeral, System { using ResourceSelector for bytes32; @@ -19,13 +19,15 @@ contract EphemeralRecordSystem is IStoreEphemeral, System { function emitEphemeralRecord( bytes32 resourceSelector, bytes32[] calldata keyTuple, - bytes calldata data, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, FieldLayout fieldLayout ) public virtual { // Require access to the namespace or name AccessControl.requireAccess(resourceSelector, msg.sender); // Set the record - StoreCore.emitEphemeralRecord(resourceSelector, keyTuple, data, fieldLayout); + StoreCore.emitEphemeralRecord(resourceSelector, 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 76f03b4f3c..417d4b2751 100644 --- a/packages/world/src/modules/core/tables/Balances.sol +++ b/packages/world/src/modules/core/tables/Balances.sol @@ -109,9 +109,19 @@ library Balances { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), getFieldLayout()); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint256 balance) internal pure returns (bytes memory) { + return abi.encodePacked(balance); + } + /** Tightly pack full data using this table's field layout */ function encode(uint256 balance) internal pure returns (bytes memory) { - return abi.encodePacked(balance); + bytes memory _staticData = encodeStatic(balance); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/modules/core/tables/FunctionSelectors.sol b/packages/world/src/modules/core/tables/FunctionSelectors.sol index e3023b3273..152672637c 100644 --- a/packages/world/src/modules/core/tables/FunctionSelectors.sol +++ b/packages/world/src/modules/core/tables/FunctionSelectors.sol @@ -177,12 +177,15 @@ library FunctionSelectors { /** Set the full data using individual values */ function set(bytes4 functionSelector, bytes32 resourceSelector, bytes4 systemFunctionSelector) internal { - bytes memory _data = encode(resourceSelector, systemFunctionSelector); + bytes memory _staticData = encodeStatic(resourceSelector, systemFunctionSelector); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ @@ -192,12 +195,15 @@ library FunctionSelectors { bytes32 resourceSelector, bytes4 systemFunctionSelector ) internal { - bytes memory _data = encode(resourceSelector, systemFunctionSelector); + bytes memory _staticData = encodeStatic(resourceSelector, systemFunctionSelector); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Decode the tightly packed blob using this table's field layout */ @@ -207,9 +213,19 @@ library FunctionSelectors { systemFunctionSelector = (Bytes.slice4(_blob, 32)); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(bytes32 resourceSelector, bytes4 systemFunctionSelector) internal pure returns (bytes memory) { + return abi.encodePacked(resourceSelector, systemFunctionSelector); + } + /** Tightly pack full data using this table's field layout */ function encode(bytes32 resourceSelector, bytes4 systemFunctionSelector) internal pure returns (bytes memory) { - return abi.encodePacked(resourceSelector, systemFunctionSelector); + bytes memory _staticData = encodeStatic(resourceSelector, systemFunctionSelector); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/modules/core/tables/ResourceType.sol b/packages/world/src/modules/core/tables/ResourceType.sol index 45ba98b6fb..ef1ce9ce3d 100644 --- a/packages/world/src/modules/core/tables/ResourceType.sol +++ b/packages/world/src/modules/core/tables/ResourceType.sol @@ -112,9 +112,19 @@ library ResourceType { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), getFieldLayout()); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(Resource resourceType) internal pure returns (bytes memory) { + return abi.encodePacked(resourceType); + } + /** Tightly pack full data using this table's field layout */ function encode(Resource resourceType) internal pure returns (bytes memory) { - return abi.encodePacked(resourceType); + bytes memory _staticData = encodeStatic(resourceType); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/modules/core/tables/SystemHooks.sol b/packages/world/src/modules/core/tables/SystemHooks.sol index 0bb1d03e8a..d0503ff496 100644 --- a/packages/world/src/modules/core/tables/SystemHooks.sol +++ b/packages/world/src/modules/core/tables/SystemHooks.sol @@ -230,15 +230,26 @@ library SystemHooks { } } - /** Tightly pack full data using this table's field layout */ - function encode(bytes21[] memory value) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + /** 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 unchecked { _encodedLengths = PackedCounterLib.pack(value.length * 21); } + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(bytes21[] memory value) internal pure returns (bytes memory) { + return abi.encodePacked(EncodeArray.encode((value))); + } + + /** Tightly pack full data using this table's field layout */ + function encode(bytes21[] memory value) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(value); + bytes memory _dynamicData = encodeDynamic(value); - return abi.encodePacked(_encodedLengths.unwrap(), EncodeArray.encode((value))); + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/modules/core/tables/SystemRegistry.sol b/packages/world/src/modules/core/tables/SystemRegistry.sol index 1bae5fb67b..fa5e247567 100644 --- a/packages/world/src/modules/core/tables/SystemRegistry.sol +++ b/packages/world/src/modules/core/tables/SystemRegistry.sol @@ -109,9 +109,19 @@ library SystemRegistry { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), getFieldLayout()); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(bytes32 resourceSelector) internal pure returns (bytes memory) { + return abi.encodePacked(resourceSelector); + } + /** Tightly pack full data using this table's field layout */ function encode(bytes32 resourceSelector) internal pure returns (bytes memory) { - return abi.encodePacked(resourceSelector); + bytes memory _staticData = encodeStatic(resourceSelector); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/modules/core/tables/Systems.sol b/packages/world/src/modules/core/tables/Systems.sol index fa6622d37e..52a9c0ad04 100644 --- a/packages/world/src/modules/core/tables/Systems.sol +++ b/packages/world/src/modules/core/tables/Systems.sol @@ -166,22 +166,28 @@ library Systems { /** Set the full data using individual values */ function set(bytes32 resourceSelector, address system, bool publicAccess) internal { - bytes memory _data = encode(system, publicAccess); + bytes memory _staticData = encodeStatic(system, publicAccess); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 resourceSelector, address system, bool publicAccess) internal { - bytes memory _data = encode(system, publicAccess); + bytes memory _staticData = encodeStatic(system, publicAccess); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Decode the tightly packed blob using this table's field layout */ @@ -191,9 +197,19 @@ library Systems { publicAccess = (_toBool(uint8(Bytes.slice1(_blob, 20)))); } + /** 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); + } + /** Tightly pack full data using this table's field layout */ function encode(address system, bool publicAccess) internal pure returns (bytes memory) { - return abi.encodePacked(system, publicAccess); + bytes memory _staticData = encodeStatic(system, publicAccess); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/modules/keysintable/KeysInTableHook.sol b/packages/world/src/modules/keysintable/KeysInTableHook.sol index 03622ade95..4a9c518988 100644 --- a/packages/world/src/modules/keysintable/KeysInTableHook.sol +++ b/packages/world/src/modules/keysintable/KeysInTableHook.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; +import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; import { StoreHook } from "@latticexyz/store/src/StoreHook.sol"; @@ -40,11 +41,25 @@ contract KeysInTableHook is StoreHook { } } - function onBeforeSetRecord(bytes32 tableId, bytes32[] memory keyTuple, bytes memory, FieldLayout) public { + function onBeforeSetRecord( + bytes32 tableId, + bytes32[] memory keyTuple, + bytes memory, + PackedCounter, + bytes memory, + FieldLayout + ) public { handleSet(tableId, keyTuple); } - function onAfterSetRecord(bytes32 tableId, bytes32[] memory keyTuple, bytes memory, FieldLayout) public { + function onAfterSetRecord( + bytes32 tableId, + bytes32[] memory keyTuple, + bytes memory, + PackedCounter, + bytes memory, + FieldLayout + ) public { // NOOP } diff --git a/packages/world/src/modules/keysintable/query.sol b/packages/world/src/modules/keysintable/query.sol index 90946bc2c0..53769a113e 100644 --- a/packages/world/src/modules/keysintable/query.sol +++ b/packages/world/src/modules/keysintable/query.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0; import { IStore } from "@latticexyz/store/src/IStore.sol"; +import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { getKeysInTable } from "./getKeysInTable.sol"; import { getKeysWithValue } from "../keyswithvalue/getKeysWithValue.sol"; @@ -45,7 +46,13 @@ function passesQueryFragment(bytes32[] memory keyTuple, QueryFragment memory fra if (fragment.queryType == QueryType.HasValue) { // Key must have the given value - return ArrayLib.includes(valuesToTuples(getKeysWithValue(fragment.tableId, fragment.value)), keyTuple); + return + ArrayLib.includes( + valuesToTuples( + getKeysWithValue(fragment.tableId, fragment.value, PackedCounter.wrap(bytes32(0)), new bytes(0)) + ), + keyTuple + ); } if (fragment.queryType == QueryType.Not) { @@ -55,7 +62,13 @@ function passesQueryFragment(bytes32[] memory keyTuple, QueryFragment memory fra if (fragment.queryType == QueryType.NotValue) { // Key must not have the given value - return !ArrayLib.includes(valuesToTuples(getKeysWithValue(fragment.tableId, fragment.value)), keyTuple); + return + !ArrayLib.includes( + valuesToTuples( + getKeysWithValue(fragment.tableId, fragment.value, PackedCounter.wrap(bytes32(0)), new bytes(0)) + ), + keyTuple + ); } return false; @@ -78,7 +91,13 @@ function passesQueryFragment( if (fragment.queryType == QueryType.HasValue) { // Key must be have the given value - return ArrayLib.includes(valuesToTuples(getKeysWithValue(store, fragment.tableId, fragment.value)), keyTuple); + return + ArrayLib.includes( + valuesToTuples( + getKeysWithValue(store, fragment.tableId, fragment.value, PackedCounter.wrap(bytes32(0)), new bytes(0)) + ), + keyTuple + ); } if (fragment.queryType == QueryType.Not) { @@ -88,7 +107,13 @@ function passesQueryFragment( if (fragment.queryType == QueryType.NotValue) { // Key must not have the given value - return !ArrayLib.includes(valuesToTuples(getKeysWithValue(store, fragment.tableId, fragment.value)), keyTuple); + return + !ArrayLib.includes( + valuesToTuples( + getKeysWithValue(store, fragment.tableId, fragment.value, PackedCounter.wrap(bytes32(0)), new bytes(0)) + ), + keyTuple + ); } return false; @@ -108,7 +133,9 @@ function query(QueryFragment[] memory fragments) view returns (bytes32[][] memor // Create the first interim result keyTuples = fragments[0].queryType == QueryType.Has ? getKeysInTable(fragments[0].tableId) - : valuesToTuples(getKeysWithValue(fragments[0].tableId, fragments[0].value)); + : valuesToTuples( + getKeysWithValue(fragments[0].tableId, fragments[0].value, PackedCounter.wrap(bytes32(0)), new bytes(0)) + ); for (uint256 i = 1; i < fragments.length; i++) { bytes32[][] memory result = new bytes32[][](0); @@ -143,7 +170,9 @@ function query(IStore store, QueryFragment[] memory fragments) view returns (byt // Create the first interim result keyTuples = fragments[0].queryType == QueryType.Has ? getKeysInTable(store, fragments[0].tableId) - : valuesToTuples(getKeysWithValue(store, fragments[0].tableId, fragments[0].value)); + : valuesToTuples( + getKeysWithValue(store, fragments[0].tableId, fragments[0].value, PackedCounter.wrap(bytes32(0)), new bytes(0)) + ); for (uint256 i = 1; i < fragments.length; i++) { bytes32[][] memory result = new bytes32[][](0); diff --git a/packages/world/src/modules/keysintable/tables/KeysInTable.sol b/packages/world/src/modules/keysintable/tables/KeysInTable.sol index fe4a0ef4f6..ba91e6d7ae 100644 --- a/packages/world/src/modules/keysintable/tables/KeysInTable.sol +++ b/packages/world/src/modules/keysintable/tables/KeysInTable.sol @@ -897,12 +897,14 @@ library KeysInTable { bytes32[] memory keys3, bytes32[] memory keys4 ) internal { - bytes memory _data = encode(keys0, keys1, keys2, keys3, keys4); + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(keys0, keys1, keys2, keys3, keys4); + bytes memory _dynamicData = encodeDynamic(keys0, keys1, keys2, keys3, keys4); bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ @@ -915,12 +917,14 @@ library KeysInTable { bytes32[] memory keys3, bytes32[] memory keys4 ) internal { - bytes memory _data = encode(keys0, keys1, keys2, keys3, keys4); + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(keys0, keys1, keys2, keys3, keys4); + bytes memory _dynamicData = encodeDynamic(keys0, keys1, keys2, keys3, keys4); bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using the data struct */ @@ -977,15 +981,14 @@ library KeysInTable { } } - /** Tightly pack full data using this table's field layout */ - function encode( + /** Tightly pack dynamic data using this table's schema */ + function encodeLengths( bytes32[] memory keys0, bytes32[] memory keys1, bytes32[] memory keys2, bytes32[] memory keys3, bytes32[] memory keys4 - ) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + ) internal pure returns (PackedCounter _encodedLengths) { // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits unchecked { _encodedLengths = PackedCounterLib.pack( @@ -996,10 +999,18 @@ library KeysInTable { keys4.length * 32 ); } + } + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic( + bytes32[] memory keys0, + bytes32[] memory keys1, + bytes32[] memory keys2, + bytes32[] memory keys3, + bytes32[] memory keys4 + ) internal pure returns (bytes memory) { return abi.encodePacked( - _encodedLengths.unwrap(), EncodeArray.encode((keys0)), EncodeArray.encode((keys1)), EncodeArray.encode((keys2)), @@ -1008,6 +1019,21 @@ library KeysInTable { ); } + /** Tightly pack full data using this table's field layout */ + function encode( + bytes32[] memory keys0, + bytes32[] memory keys1, + bytes32[] memory keys2, + bytes32[] memory keys3, + bytes32[] memory keys4 + ) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(keys0, keys1, keys2, keys3, keys4); + bytes memory _dynamicData = encodeDynamic(keys0, keys1, keys2, keys3, keys4); + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + } + /** Encode keys as a bytes32 array using this table's field layout */ function encodeKeyTuple(bytes32 sourceTable) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](1); diff --git a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol index b29e54cab8..ac68814aa7 100644 --- a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol +++ b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol @@ -178,24 +178,30 @@ library UsedKeysIndex { /** Set the full data using individual values */ function set(bytes32 sourceTable, bytes32 keysHash, bool has, uint40 index) internal { - bytes memory _data = encode(has, index); + bytes memory _staticData = encodeStatic(has, index); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 sourceTable, bytes32 keysHash, bool has, uint40 index) internal { - bytes memory _data = encode(has, index); + bytes memory _staticData = encodeStatic(has, index); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](2); _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Decode the tightly packed blob using this table's field layout */ @@ -205,9 +211,19 @@ library UsedKeysIndex { index = (uint40(Bytes.slice5(_blob, 1))); } + /** 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) { - return abi.encodePacked(has, index); + bytes memory _staticData = encodeStatic(has, index); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/modules/keyswithvalue/KeysWithValueHook.sol b/packages/world/src/modules/keyswithvalue/KeysWithValueHook.sol index f0326407cd..3c3c822c0f 100644 --- a/packages/world/src/modules/keyswithvalue/KeysWithValueHook.sol +++ b/packages/world/src/modules/keyswithvalue/KeysWithValueHook.sol @@ -5,6 +5,7 @@ import { StoreHook } from "@latticexyz/store/src/StoreHook.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; +import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; import { ResourceSelector } from "../../ResourceSelector.sol"; @@ -32,7 +33,9 @@ contract KeysWithValueHook is StoreHook { function onBeforeSetRecord( bytes32 sourceTableId, bytes32[] memory keyTuple, - bytes memory data, + bytes memory staticData, + PackedCounter encodedLengths, + bytes memory dynamicData, FieldLayout fieldLayout ) public { bytes32 targetTableId = getTargetTableSelector(MODULE_NAMESPACE, sourceTableId); @@ -44,13 +47,21 @@ contract KeysWithValueHook is StoreHook { _removeKeyFromList(targetTableId, keyTuple[0], previousValue); // Push the key to the list of keys with the new value + bytes memory data; + if (dynamicData.length > 0) { + data = abi.encodePacked(staticData, encodedLengths, dynamicData); + } else { + data = staticData; + } KeysWithValue.push(targetTableId, keccak256(data), keyTuple[0]); } function onAfterSetRecord( bytes32 sourceTableId, bytes32[] memory keyTuple, - bytes memory data, + bytes memory staticData, + PackedCounter encodedLengths, + bytes memory dynamicData, FieldLayout fieldLayout ) public { // NOOP diff --git a/packages/world/src/modules/keyswithvalue/getKeysWithValue.sol b/packages/world/src/modules/keyswithvalue/getKeysWithValue.sol index f5e8605c63..e47fba0d10 100644 --- a/packages/world/src/modules/keyswithvalue/getKeysWithValue.sol +++ b/packages/world/src/modules/keyswithvalue/getKeysWithValue.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0; import { IStore } from "@latticexyz/store/src/IStore.sol"; +import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { MODULE_NAMESPACE } from "./constants.sol"; import { KeysWithValue } from "./tables/KeysWithValue.sol"; @@ -13,11 +14,22 @@ import { getTargetTableSelector } from "../utils/getTargetTableSelector.sol"; * Note: this util can only be called within the context of a Store (e.g. from a System or Module). * For usage outside of a Store, use the overload that takes an explicit store argument. */ -function getKeysWithValue(bytes32 tableId, bytes memory value) view returns (bytes32[] memory keysWithValue) { +function getKeysWithValue( + bytes32 tableId, + bytes memory staticData, + PackedCounter encodedLengths, + bytes memory dynamicData +) view returns (bytes32[] memory keysWithValue) { // Get the corresponding reverse mapping table bytes32 keysWithValueTableId = getTargetTableSelector(MODULE_NAMESPACE, tableId); // Get the keys with the given value + bytes memory value; + if (dynamicData.length > 0) { + value = abi.encodePacked(staticData, encodedLengths, dynamicData); + } else { + value = staticData; + } keysWithValue = KeysWithValue.get(keysWithValueTableId, keccak256(value)); } @@ -27,11 +39,19 @@ function getKeysWithValue(bytes32 tableId, bytes memory value) view returns (byt function getKeysWithValue( IStore store, bytes32 tableId, - bytes memory value + bytes memory staticData, + PackedCounter encodedLengths, + bytes memory dynamicData ) view returns (bytes32[] memory keysWithValue) { // Get the corresponding reverse mapping table bytes32 keysWithValueTableId = getTargetTableSelector(MODULE_NAMESPACE, tableId); // Get the keys with the given value + bytes memory value; + if (dynamicData.length > 0) { + value = abi.encodePacked(staticData, encodedLengths, dynamicData); + } else { + value = staticData; + } keysWithValue = KeysWithValue.get(store, keysWithValueTableId, keccak256(value)); } diff --git a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol index 2ae73a6568..a13236775a 100644 --- a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol +++ b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol @@ -231,15 +231,26 @@ library KeysWithValue { } } - /** Tightly pack full data using this table's field layout */ - function encode(bytes32[] memory keysWithValue) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + /** 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 unchecked { _encodedLengths = PackedCounterLib.pack(keysWithValue.length * 32); } + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(bytes32[] memory keysWithValue) internal pure returns (bytes memory) { + return abi.encodePacked(EncodeArray.encode((keysWithValue))); + } + + /** Tightly pack full data using this table's field layout */ + function encode(bytes32[] memory keysWithValue) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(keysWithValue); + bytes memory _dynamicData = encodeDynamic(keysWithValue); - return abi.encodePacked(_encodedLengths.unwrap(), EncodeArray.encode((keysWithValue))); + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol index a2f0f2519b..070d868fe0 100644 --- a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol @@ -151,9 +151,19 @@ library CallboundDelegations { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), getFieldLayout()); } + /** 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) { - return abi.encodePacked(availableCalls); + bytes memory _staticData = encodeStatic(availableCalls); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol index 27a2552404..3e7a015869 100644 --- a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol @@ -115,9 +115,19 @@ library TimeboundDelegations { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((maxTimestamp)), getFieldLayout()); } + /** 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) { - return abi.encodePacked(maxTimestamp); + bytes memory _staticData = encodeStatic(maxTimestamp); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol index 092bde6646..1b2238a638 100644 --- a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol +++ b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol @@ -100,9 +100,19 @@ library UniqueEntity { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint256 value) internal pure returns (bytes memory) { + return abi.encodePacked(value); + } + /** Tightly pack full data using this table's field layout */ function encode(uint256 value) internal pure returns (bytes memory) { - return abi.encodePacked(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/tables/Delegations.sol b/packages/world/src/tables/Delegations.sol index 5889c445bd..22420ee76b 100644 --- a/packages/world/src/tables/Delegations.sol +++ b/packages/world/src/tables/Delegations.sol @@ -119,9 +119,19 @@ library Delegations { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((delegationControlId)), getFieldLayout()); } + /** 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) { - return abi.encodePacked(delegationControlId); + bytes memory _staticData = encodeStatic(delegationControlId); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/tables/InstalledModules.sol b/packages/world/src/tables/InstalledModules.sol index a0bbbc61b7..9f7b45859c 100644 --- a/packages/world/src/tables/InstalledModules.sol +++ b/packages/world/src/tables/InstalledModules.sol @@ -115,9 +115,19 @@ library InstalledModules { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((moduleAddress)), getFieldLayout()); } + /** 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) { - return abi.encodePacked(moduleAddress); + bytes memory _staticData = encodeStatic(moduleAddress); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/tables/NamespaceOwner.sol b/packages/world/src/tables/NamespaceOwner.sol index 54033da9dd..85d58a4921 100644 --- a/packages/world/src/tables/NamespaceOwner.sol +++ b/packages/world/src/tables/NamespaceOwner.sol @@ -109,9 +109,19 @@ library NamespaceOwner { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), getFieldLayout()); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(address owner) internal pure returns (bytes memory) { + return abi.encodePacked(owner); + } + /** Tightly pack full data using this table's field layout */ function encode(address owner) internal pure returns (bytes memory) { - return abi.encodePacked(owner); + bytes memory _staticData = encodeStatic(owner); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/src/tables/ResourceAccess.sol b/packages/world/src/tables/ResourceAccess.sol index f53abae8e7..51a3dba36d 100644 --- a/packages/world/src/tables/ResourceAccess.sol +++ b/packages/world/src/tables/ResourceAccess.sol @@ -115,9 +115,19 @@ library ResourceAccess { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), getFieldLayout()); } + /** 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) { - return abi.encodePacked(access); + bytes memory _staticData = encodeStatic(access); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/test/KeysInTableModule.t.sol b/packages/world/test/KeysInTableModule.t.sol index e25f7b5427..7789e33740 100644 --- a/packages/world/test/KeysInTableModule.t.sol +++ b/packages/world/test/KeysInTableModule.t.sol @@ -7,6 +7,7 @@ import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { FieldLayoutEncodeHelper } from "@latticexyz/store/test/FieldLayoutEncodeHelper.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; +import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { SchemaEncodeHelper } from "@latticexyz/store/test/SchemaEncodeHelper.sol"; import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; @@ -103,7 +104,14 @@ contract KeysInTableModuleTest is Test, GasReporter { bytes32[] memory keyTuple = new bytes32[](0); - world.setRecord(singletonTableId, keyTuple, abi.encodePacked(val1), tableFieldLayout); + world.setRecord( + singletonTableId, + keyTuple, + abi.encodePacked(val1), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); // Get the list of keys in this target table bytes32[][] memory keysInTable = getKeysInTable(world, singletonTableId); @@ -120,7 +128,14 @@ contract KeysInTableModuleTest is Test, GasReporter { keyTuple[1] = "two"; keyTuple[2] = "three"; - world.setRecord(compositeTableId, keyTuple, abi.encodePacked(val1), tableFieldLayout); + world.setRecord( + compositeTableId, + keyTuple, + abi.encodePacked(val1), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); // Get the list of keys in this target table bytes32[][] memory keysInTable = getKeysInTable(world, compositeTableId); @@ -145,7 +160,14 @@ contract KeysInTableModuleTest is Test, GasReporter { _installKeysInTableModule(); // Set a value in the source table startGasReport("set a record on a table with keysInTableModule installed"); - world.setRecord(tableId, keyTuple1, abi.encodePacked(value), tableFieldLayout); + world.setRecord( + tableId, + keyTuple1, + abi.encodePacked(value), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); endGasReport(); // Get the list of keys in this target table @@ -164,7 +186,14 @@ contract KeysInTableModuleTest is Test, GasReporter { // Set a value in the source table startGasReport("set a record on a table with keysInTableModule installed (first)"); - world.setRecord(tableId, keyTuple, abi.encodePacked(value1), tableFieldLayout); + world.setRecord( + tableId, + keyTuple, + abi.encodePacked(value1), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); endGasReport(); // Get the list of keys in the first target table @@ -192,7 +221,14 @@ contract KeysInTableModuleTest is Test, GasReporter { // Set a value in the source table startGasReport("set a record on a table with keysInTableModule installed (second)"); - world.setRecord(sourceTableId2, keyTuple, abi.encodePacked(value2), tableFieldLayout); + world.setRecord( + sourceTableId2, + keyTuple, + abi.encodePacked(value2), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); endGasReport(); // Get the list of keys in the second target table @@ -212,7 +248,14 @@ contract KeysInTableModuleTest is Test, GasReporter { _installKeysInTableModule(); // Set a value in the source table - world.setRecord(tableId, keyTuple1, abi.encodePacked(value1), tableFieldLayout); + world.setRecord( + tableId, + keyTuple1, + abi.encodePacked(value1), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); // Get the list of keys in the target table bytes32[][] memory keysInTable = getKeysInTable(world, tableId); @@ -222,7 +265,14 @@ contract KeysInTableModuleTest is Test, GasReporter { assertEq(keysInTable[0][0], key1, "2"); // Set another key with the same value - world.setRecord(tableId, keyTuple2, abi.encodePacked(value1), tableFieldLayout); + world.setRecord( + tableId, + keyTuple2, + abi.encodePacked(value1), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); // Get the list of keys in the target table keysInTable = getKeysInTable(world, tableId); @@ -234,7 +284,14 @@ contract KeysInTableModuleTest is Test, GasReporter { // Change the value of the first key startGasReport("change a record on a table with keysInTableModule installed"); - world.setRecord(tableId, keyTuple1, abi.encodePacked(value2), tableFieldLayout); + world.setRecord( + tableId, + keyTuple1, + abi.encodePacked(value2), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); endGasReport(); // Get the list of keys in the target table @@ -277,7 +334,14 @@ contract KeysInTableModuleTest is Test, GasReporter { keyTupleB[2] = "charlie"; // Set a value in the source table - world.setRecord(compositeTableId, keyTupleA, abi.encodePacked(value1), tableFieldLayout); + world.setRecord( + compositeTableId, + keyTupleA, + abi.encodePacked(value1), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); // Get the list of keys in the target table bytes32[][] memory keysInTable = getKeysInTable(world, compositeTableId); @@ -289,7 +353,14 @@ contract KeysInTableModuleTest is Test, GasReporter { } // Set another key with the same value - world.setRecord(compositeTableId, keyTupleB, abi.encodePacked(value1), tableFieldLayout); + world.setRecord( + compositeTableId, + keyTupleB, + abi.encodePacked(value1), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); // Get the list of keys in the target table keysInTable = getKeysInTable(world, compositeTableId); @@ -305,7 +376,14 @@ contract KeysInTableModuleTest is Test, GasReporter { // Change the value of the first key startGasReport("change a composite record on a table with keysInTableModule installed"); - world.setRecord(compositeTableId, keyTupleA, abi.encodePacked(value2), tableFieldLayout); + world.setRecord( + compositeTableId, + keyTupleA, + abi.encodePacked(value2), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); endGasReport(); // Get the list of keys in the target table @@ -367,7 +445,14 @@ contract KeysInTableModuleTest is Test, GasReporter { _installKeysInTableModule(); // Set a value in the source table - world.setRecord(tableId, keyTuple1, abi.encodePacked(value1), tableFieldLayout); + world.setRecord( + tableId, + keyTuple1, + abi.encodePacked(value1), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); startGasReport("Get list of keys in a given table"); bytes32[][] memory keysInTable = getKeysInTable(world, tableId); @@ -378,7 +463,14 @@ contract KeysInTableModuleTest is Test, GasReporter { assertEq(keysInTable[0][0], key1); // Set another key with a different value - world.setRecord(tableId, keyTuple2, abi.encodePacked(value2), tableFieldLayout); + world.setRecord( + tableId, + keyTuple2, + abi.encodePacked(value2), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); // Get the list of keys in the target table keysInTable = getKeysInTable(world, tableId); @@ -393,9 +485,30 @@ contract KeysInTableModuleTest is Test, GasReporter { _installKeysInTableModule(); // Add 3 values - world.setRecord(tableId, keyTuple1, abi.encodePacked(value), tableFieldLayout); - world.setRecord(tableId, keyTuple2, abi.encodePacked(value), tableFieldLayout); - world.setRecord(tableId, keyTuple3, abi.encodePacked(value), tableFieldLayout); + world.setRecord( + tableId, + keyTuple1, + abi.encodePacked(value), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); + world.setRecord( + tableId, + keyTuple2, + abi.encodePacked(value), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); + world.setRecord( + tableId, + keyTuple3, + abi.encodePacked(value), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + tableFieldLayout + ); // Remove 2, starting from the middle // This tests that KeysInTable correctly tracks swaps indexes diff --git a/packages/world/test/KeysWithValueModule.t.sol b/packages/world/test/KeysWithValueModule.t.sol index 50307d969b..fa8e8e83d5 100644 --- a/packages/world/test/KeysWithValueModule.t.sol +++ b/packages/world/test/KeysWithValueModule.t.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import { Test } from "forge-std/Test.sol"; +import { Test, console } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { Schema } from "@latticexyz/store/src/Schema.sol"; +import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { SchemaEncodeHelper } from "@latticexyz/store/test/SchemaEncodeHelper.sol"; import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; @@ -26,20 +27,20 @@ import { getTargetTableSelector } from "../src/modules/utils/getTargetTableSelec contract KeysWithValueModuleTest is Test, GasReporter { using ResourceSelector for bytes32; IBaseWorld world; - KeysWithValueModule keysWithValueModule = new KeysWithValueModule(); // Modules can be deployed once and installed multiple times + KeysWithValueModule private keysWithValueModule = new KeysWithValueModule(); // Modules can be deployed once and installed multiple times - bytes16 namespace = ROOT_NAMESPACE; - bytes16 sourceName = bytes16("source"); - bytes32 key1 = keccak256("test"); - bytes32[] keyTuple1; - bytes32 key2 = keccak256("test2"); - bytes32[] keyTuple2; + bytes16 private namespace = ROOT_NAMESPACE; + bytes16 private sourceName = bytes16("source"); + bytes32 private key1 = keccak256("test"); + bytes32[] private keyTuple1; + bytes32 private key2 = keccak256("test2"); + bytes32[] private keyTuple2; - FieldLayout sourceTableFieldLayout; - Schema sourceTableSchema; - Schema sourceTableKeySchema; - bytes32 sourceTableId; - bytes32 targetTableId; + FieldLayout private sourceTableFieldLayout; + Schema private sourceTableSchema; + Schema private sourceTableKeySchema; + bytes32 private sourceTableId; + bytes32 private targetTableId; function setUp() public { sourceTableFieldLayout = FieldLayoutEncodeHelper.encode(32, 0); @@ -80,11 +81,18 @@ contract KeysWithValueModuleTest is Test, GasReporter { uint256 value = 1; startGasReport("set a record on a table with KeysWithValueModule installed"); - world.setRecord(sourceTableId, keyTuple1, abi.encodePacked(value), sourceTableFieldLayout); + world.setRecord( + sourceTableId, + keyTuple1, + abi.encodePacked(value), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + sourceTableFieldLayout + ); endGasReport(); // Get the list of entities with this value from the target table - bytes32[] memory keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encode(value))); + bytes32[] memory keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encodePacked(value))); // Assert that the list is correct assertEq(keysWithValue.length, 1); @@ -97,20 +105,34 @@ contract KeysWithValueModuleTest is Test, GasReporter { // Set a value in the source table uint256 value1 = 1; - world.setRecord(sourceTableId, keyTuple1, abi.encodePacked(value1), sourceTableFieldLayout); + world.setRecord( + sourceTableId, + keyTuple1, + abi.encodePacked(value1), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + sourceTableFieldLayout + ); // Get the list of entities with value1 from the target table - bytes32[] memory keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encode(value1))); + bytes32[] memory keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encodePacked(value1))); // Assert that the list is correct assertEq(keysWithValue.length, 1, "1"); assertEq(keysWithValue[0], key1, "2"); // Set a another key with the same value - world.setRecord(sourceTableId, keyTuple2, abi.encodePacked(value1), sourceTableFieldLayout); + world.setRecord( + sourceTableId, + keyTuple2, + abi.encodePacked(value1), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + sourceTableFieldLayout + ); // Get the list of entities with value2 from the target table - keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encode(value1))); + keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encodePacked(value1))); // Assert that the list is correct assertEq(keysWithValue.length, 2); @@ -121,18 +143,25 @@ contract KeysWithValueModuleTest is Test, GasReporter { uint256 value2 = 2; startGasReport("change a record on a table with KeysWithValueModule installed"); - world.setRecord(sourceTableId, keyTuple1, abi.encodePacked(value2), sourceTableFieldLayout); + world.setRecord( + sourceTableId, + keyTuple1, + abi.encodePacked(value2), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + sourceTableFieldLayout + ); endGasReport(); // Get the list of entities with value1 from the target table - keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encode(value1))); + keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encodePacked(value1))); // Assert that the list is correct assertEq(keysWithValue.length, 1, "5"); assertEq(keysWithValue[0], key2, "6"); // Get the list of entities with value2 from the target table - keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encode(value2))); + keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encodePacked(value2))); // Assert that the list is correct assertEq(keysWithValue.length, 1, "7"); @@ -144,7 +173,7 @@ contract KeysWithValueModuleTest is Test, GasReporter { endGasReport(); // Get the list of entities with value2 from the target table - keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encode(value2))); + keysWithValue = KeysWithValue.get(world, targetTableId, keccak256(abi.encodePacked(value2))); // Assert that the list is correct assertEq(keysWithValue.length, 0, "9"); @@ -212,10 +241,23 @@ contract KeysWithValueModuleTest is Test, GasReporter { _installKeysWithValueModule(); // Set a value in the source table - world.setRecord(sourceTableId, keyTuple1, abi.encodePacked(value), sourceTableFieldLayout); + world.setRecord( + sourceTableId, + keyTuple1, + abi.encodePacked(value), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + sourceTableFieldLayout + ); startGasReport("Get list of keys with a given value"); - bytes32[] memory keysWithValue = getKeysWithValue(world, sourceTableId, abi.encode(value)); + bytes32[] memory keysWithValue = getKeysWithValue( + world, + sourceTableId, + abi.encodePacked(value), + PackedCounter.wrap(bytes32(0)), + new bytes(0) + ); endGasReport(); // Assert that the list is correct @@ -223,10 +265,23 @@ contract KeysWithValueModuleTest is Test, GasReporter { assertEq(keysWithValue[0], key1); // Set a another key with the same value - world.setRecord(sourceTableId, keyTuple2, abi.encodePacked(value), sourceTableFieldLayout); + world.setRecord( + sourceTableId, + keyTuple2, + abi.encodePacked(value), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + sourceTableFieldLayout + ); // Get the list of keys with value from the target table - keysWithValue = getKeysWithValue(world, sourceTableId, abi.encode(value)); + keysWithValue = getKeysWithValue( + world, + sourceTableId, + abi.encodePacked(value), + PackedCounter.wrap(bytes32(0)), + new bytes(0) + ); // Assert that the list is correct assertEq(keysWithValue.length, 2); diff --git a/packages/world/test/World.t.sol b/packages/world/test/World.t.sol index 1d168ead9a..9d651d3ef2 100644 --- a/packages/world/test/World.t.sol +++ b/packages/world/test/World.t.sol @@ -12,6 +12,7 @@ import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { FieldLayout, FieldLayoutLib } from "@latticexyz/store/src/FieldLayout.sol"; import { FieldLayoutEncodeHelper } from "@latticexyz/store/test/FieldLayoutEncodeHelper.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; +import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { SchemaEncodeHelper } from "@latticexyz/store/test/SchemaEncodeHelper.sol"; import { Tables, TablesTableId } from "@latticexyz/store/src/codegen/Tables.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; @@ -91,9 +92,23 @@ contract WorldTestSystem is System { FieldLayout fieldLayout = StoreSwitch.getFieldLayout(tableId); if (StoreSwitch.getStoreAddress() == address(this)) { - StoreCore.setRecord(tableId, keyTuple, abi.encodePacked(data), fieldLayout); + StoreCore.setRecord( + tableId, + keyTuple, + abi.encodePacked(data), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + fieldLayout + ); } else { - IBaseWorld(msg.sender).setRecord(tableId, keyTuple, abi.encodePacked(data), fieldLayout); + IBaseWorld(msg.sender).setRecord( + tableId, + keyTuple, + abi.encodePacked(data), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + fieldLayout + ); } } @@ -621,7 +636,14 @@ contract WorldTest is Test, GasReporter { world.registerTable(tableId, fieldLayout, defaultKeySchema, valueSchema, new string[](1), new string[](1)); // Write data to the table and expect it to be written - world.setRecord(tableId, singletonKey, abi.encodePacked(true), fieldLayout); + world.setRecord( + tableId, + singletonKey, + abi.encodePacked(true), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + fieldLayout + ); assertTrue(Bool.get(world, tableId)); startGasReport("Delete record"); @@ -632,7 +654,15 @@ contract WorldTest is Test, GasReporter { assertFalse(Bool.get(world, tableId)); // Write data to the table and expect it to be written - world.setRecord(tableId, singletonKey, abi.encodePacked(true), fieldLayout); + world.setRecord( + tableId, + singletonKey, + abi.encodePacked(true), + PackedCounter.wrap(bytes32(0)), + new bytes(0), + fieldLayout + ); + assertTrue(Bool.get(world, tableId)); assertTrue(Bool.get(world, tableId)); // Expect an error when trying to delete from an address that doesn't have access @@ -822,25 +852,29 @@ contract WorldTest is Test, GasReporter { ); // Prepare data to write to the table - bytes memory value = abi.encodePacked(true); + bytes memory staticData = abi.encodePacked(true); // Expect the hook to be notified when a record is written (once before and once after the record is written) vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, singletonKey, value, fieldLayout)); + emit HookCalled( + abi.encode(tableId, singletonKey, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout) + ); vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, singletonKey, value, fieldLayout)); + emit HookCalled( + abi.encode(tableId, singletonKey, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout) + ); - world.setRecord(tableId, singletonKey, value, fieldLayout); + world.setRecord(tableId, singletonKey, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout); // Expect the hook to be notified when a field is written (once before and once after the field is written) vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, singletonKey, uint8(0), value, fieldLayout)); + emit HookCalled(abi.encode(tableId, singletonKey, uint8(0), staticData, fieldLayout)); vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, singletonKey, uint8(0), value, fieldLayout)); + emit HookCalled(abi.encode(tableId, singletonKey, uint8(0), staticData, fieldLayout)); - world.setField(tableId, singletonKey, 0, value, fieldLayout); + world.setField(tableId, singletonKey, 0, staticData, fieldLayout); // Expect the hook to be notified when a record is deleted (once before and once after the field is written) vm.expectEmit(true, true, true, true); @@ -907,15 +941,15 @@ contract WorldTest is Test, GasReporter { ); // Prepare data to write to the table - bytes memory value = abi.encodePacked(true); + bytes memory staticData = abi.encodePacked(true); // Expect a revert when the RevertSubscriber's onBeforeSetRecord hook is called vm.expectRevert(bytes("onBeforeSetRecord")); - world.setRecord(tableId, singletonKey, value, fieldLayout); + world.setRecord(tableId, singletonKey, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout); // Expect a revert when the RevertSubscriber's onBeforeSetField hook is called vm.expectRevert(bytes("onBeforeSetField")); - world.setField(tableId, singletonKey, 0, value, fieldLayout); + world.setField(tableId, singletonKey, 0, staticData, fieldLayout); // Expect a revert when the RevertSubscriber's onBeforeDeleteRecord hook is called vm.expectRevert(bytes("onBeforeDeleteRecord")); @@ -926,21 +960,25 @@ contract WorldTest is Test, GasReporter { // Expect the hook to be notified when a record is written (once before and once after the record is written) vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, singletonKey, value, fieldLayout)); + emit HookCalled( + abi.encode(tableId, singletonKey, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout) + ); vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, singletonKey, value, fieldLayout)); + emit HookCalled( + abi.encode(tableId, singletonKey, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout) + ); - world.setRecord(tableId, singletonKey, value, fieldLayout); + world.setRecord(tableId, singletonKey, staticData, PackedCounter.wrap(bytes32(0)), new bytes(0), fieldLayout); // Expect the hook to be notified when a field is written (once before and once after the field is written) vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, singletonKey, uint8(0), value, fieldLayout)); + emit HookCalled(abi.encode(tableId, singletonKey, uint8(0), staticData, fieldLayout)); vm.expectEmit(true, true, true, true); - emit HookCalled(abi.encode(tableId, singletonKey, uint8(0), value, fieldLayout)); + emit HookCalled(abi.encode(tableId, singletonKey, uint8(0), staticData, fieldLayout)); - world.setField(tableId, singletonKey, 0, value, fieldLayout); + world.setField(tableId, singletonKey, 0, staticData, fieldLayout); // Expect the hook to be notified when a record is deleted (once before and once after the field is written) vm.expectEmit(true, true, true, true); diff --git a/packages/world/test/query.t.sol b/packages/world/test/query.t.sol index 0d7b3b63f8..27f8621b9a 100644 --- a/packages/world/test/query.t.sol +++ b/packages/world/test/query.t.sol @@ -8,6 +8,7 @@ import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; import { FieldLayoutEncodeHelper } from "@latticexyz/store/test/FieldLayoutEncodeHelper.sol"; import { Schema } from "@latticexyz/store/src/Schema.sol"; import { SchemaEncodeHelper } from "@latticexyz/store/test/SchemaEncodeHelper.sol"; +import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; import { World } from "../src/World.sol"; @@ -22,29 +23,29 @@ import { query, QueryFragment, QueryType } from "../src/modules/keysintable/quer contract QueryTest is Test, GasReporter { using ResourceSelector for bytes32; - IBaseWorld world; - KeysInTableModule keysInTableModule = new KeysInTableModule(); // Modules can be deployed once and installed multiple times - KeysWithValueModule keysWithValueModule = new KeysWithValueModule(); - - bytes16 namespace = ROOT_NAMESPACE; - bytes16 name1 = bytes16("source1"); - bytes16 name2 = bytes16("source2"); - bytes16 name3 = bytes16("source3"); - - FieldLayout tableFieldLayout; - Schema tableKeySchema; - Schema tableValueSchema; - bytes32 table1 = ResourceSelector.from(namespace, name1); - bytes32 table2 = ResourceSelector.from(namespace, name2); - bytes32 table3 = ResourceSelector.from(namespace, name3); - - uint256 value = 1; - bytes32[] key1 = new bytes32[](1); - bytes32[] key2 = new bytes32[](1); - bytes32[] key3 = new bytes32[](1); - bytes32[] key4 = new bytes32[](1); - QueryFragment[] fragmentsHasHas; - QueryFragment[] fragmentsHasNot; + IBaseWorld private world; + KeysInTableModule private keysInTableModule = new KeysInTableModule(); // Modules can be deployed once and installed multiple times + KeysWithValueModule private keysWithValueModule = new KeysWithValueModule(); + + bytes16 private namespace = ROOT_NAMESPACE; + bytes16 private name1 = bytes16("source1"); + bytes16 private name2 = bytes16("source2"); + bytes16 private name3 = bytes16("source3"); + + FieldLayout private tableFieldLayout; + Schema private tableKeySchema; + Schema private tableValueSchema; + bytes32 private table1 = ResourceSelector.from(namespace, name1); + bytes32 private table2 = ResourceSelector.from(namespace, name2); + bytes32 private table3 = ResourceSelector.from(namespace, name3); + + uint256 private value = 1; + bytes32[] private key1 = new bytes32[](1); + bytes32[] private key2 = new bytes32[](1); + bytes32[] private key3 = new bytes32[](1); + bytes32[] private key4 = new bytes32[](1); + QueryFragment[] private fragmentsHasHas; + QueryFragment[] private fragmentsHasNot; function setUp() public { tableFieldLayout = FieldLayoutEncodeHelper.encode(32, 0); @@ -90,9 +91,9 @@ contract QueryTest is Test, GasReporter { function testHasQuery() public { _installKeysInTableModule(); - world.setRecord(table1, key1, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key2, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key1, abi.encode(0), tableFieldLayout); + world.setRecord(table1, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key2, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key1, abi.encode(0), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all keys in table1 QueryFragment[] memory fragments = new QueryFragment[](1); @@ -111,9 +112,9 @@ contract QueryTest is Test, GasReporter { _installKeysInTableModule(); _installKeysWithValueModule(); - world.setRecord(table1, key1, abi.encode(2), tableFieldLayout); - world.setRecord(table1, key2, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key3, abi.encode(1), tableFieldLayout); + world.setRecord(table1, key1, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key2, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all keys in table1 with value 1 QueryFragment[] memory fragments = new QueryFragment[](1); fragments[0] = QueryFragment(QueryType.HasValue, table1, abi.encode(1)); @@ -129,12 +130,12 @@ contract QueryTest is Test, GasReporter { function testCombinedHasQuery() public { _installKeysInTableModule(); - world.setRecord(table1, key1, abi.encode(2), tableFieldLayout); - world.setRecord(table1, key2, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key2, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table3, key1, abi.encode(1), tableFieldLayout); + world.setRecord(table1, key1, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key2, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key2, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table3, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all entities that have table1 and table2 QueryFragment[] memory fragments = new QueryFragment[](2); @@ -153,12 +154,12 @@ contract QueryTest is Test, GasReporter { _installKeysInTableModule(); _installKeysWithValueModule(); - world.setRecord(table1, key1, abi.encode(2), tableFieldLayout); - world.setRecord(table1, key2, abi.encode(2), tableFieldLayout); - world.setRecord(table1, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key2, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table3, key1, abi.encode(1), tableFieldLayout); + world.setRecord(table1, key1, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key2, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key2, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table3, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all entities that have table1 and table2 QueryFragment[] memory fragments = new QueryFragment[](2); @@ -176,13 +177,13 @@ contract QueryTest is Test, GasReporter { _installKeysInTableModule(); _installKeysWithValueModule(); - world.setRecord(table1, key1, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key2, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key1, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key2, abi.encode(2), tableFieldLayout); - world.setRecord(table2, key3, abi.encode(2), tableFieldLayout); - world.setRecord(table2, key4, abi.encode(2), tableFieldLayout); + world.setRecord(table1, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key2, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key2, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key3, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key4, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all entities that have table1 and table2 QueryFragment[] memory fragments = new QueryFragment[](2); @@ -200,13 +201,13 @@ contract QueryTest is Test, GasReporter { function testCombinedHasNotQuery() public { _installKeysInTableModule(); - world.setRecord(table1, key1, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key2, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key1, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key2, abi.encode(2), tableFieldLayout); - world.setRecord(table2, key3, abi.encode(2), tableFieldLayout); - world.setRecord(table2, key4, abi.encode(2), tableFieldLayout); + world.setRecord(table1, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key2, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key2, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key3, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key4, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all entities that have table1 and table2 QueryFragment[] memory fragments = new QueryFragment[](2); @@ -224,13 +225,13 @@ contract QueryTest is Test, GasReporter { _installKeysInTableModule(); _installKeysWithValueModule(); - world.setRecord(table1, key1, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key2, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key1, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key2, abi.encode(2), tableFieldLayout); - world.setRecord(table2, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key4, abi.encode(1), tableFieldLayout); + world.setRecord(table1, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key2, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key2, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key4, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all entities that have table1 and table2 QueryFragment[] memory fragments = new QueryFragment[](2); @@ -248,16 +249,16 @@ contract QueryTest is Test, GasReporter { _installKeysInTableModule(); _installKeysWithValueModule(); - world.setRecord(table1, key1, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key2, abi.encode(1), tableFieldLayout); - world.setRecord(table1, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key1, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key2, abi.encode(2), tableFieldLayout); - world.setRecord(table2, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table2, key4, abi.encode(1), tableFieldLayout); - world.setRecord(table3, key2, abi.encode(1), tableFieldLayout); - world.setRecord(table3, key3, abi.encode(1), tableFieldLayout); - world.setRecord(table3, key4, abi.encode(1), tableFieldLayout); + world.setRecord(table1, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key2, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key1, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key2, abi.encode(2), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table2, key4, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table3, key2, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table3, key3, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table3, key4, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all entities that have table2 and not table1 QueryFragment[] memory fragments = new QueryFragment[](3); @@ -276,9 +277,9 @@ contract QueryTest is Test, GasReporter { _installKeysInTableModule(); _installKeysWithValueModule(); - world.setRecord(table1, key1, abi.encode(4), tableFieldLayout); - world.setRecord(table1, key2, abi.encode(5), tableFieldLayout); - world.setRecord(table1, key3, abi.encode(6), tableFieldLayout); + world.setRecord(table1, key1, abi.encode(4), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key2, abi.encode(5), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); + world.setRecord(table1, key3, abi.encode(6), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all entities with table1 except value 6 QueryFragment[] memory fragments = new QueryFragment[](2); @@ -299,9 +300,9 @@ contract QueryTest is Test, GasReporter { for (uint256 i; i < 100; i++) { bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = bytes32(i); - world.setRecord(table1, keyTuple, abi.encode(1), tableFieldLayout); + world.setRecord(table1, keyTuple, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); } - world.setRecord(table2, key1, abi.encode(0), tableFieldLayout); + world.setRecord(table2, key1, abi.encode(0), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all keys in table1 QueryFragment[] memory fragments = new QueryFragment[](1); @@ -320,9 +321,9 @@ contract QueryTest is Test, GasReporter { for (uint256 i; i < 1000; i++) { bytes32[] memory keyTuple = new bytes32[](1); keyTuple[0] = bytes32(i); - world.setRecord(table1, keyTuple, abi.encode(1), tableFieldLayout); + world.setRecord(table1, keyTuple, abi.encode(1), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); } - world.setRecord(table2, key1, abi.encode(0), tableFieldLayout); + world.setRecord(table2, key1, abi.encode(0), PackedCounter.wrap(bytes32(0)), new bytes(0), tableFieldLayout); // Query should return all keys in table1 QueryFragment[] memory fragments = new QueryFragment[](1); diff --git a/packages/world/test/tables/AddressArray.sol b/packages/world/test/tables/AddressArray.sol index 004e97be40..ecd9e930ac 100644 --- a/packages/world/test/tables/AddressArray.sol +++ b/packages/world/test/tables/AddressArray.sol @@ -227,15 +227,26 @@ library AddressArray { } } - /** Tightly pack full data using this table's field layout */ - function encode(address[] memory value) internal pure returns (bytes memory) { - PackedCounter _encodedLengths; + /** 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 unchecked { _encodedLengths = PackedCounterLib.pack(value.length * 20); } + } + + /** Tightly pack dynamic data using this table's schema */ + function encodeDynamic(address[] memory value) internal pure returns (bytes memory) { + return abi.encodePacked(EncodeArray.encode((value))); + } + + /** Tightly pack full data using this table's field layout */ + function encode(address[] memory value) internal pure returns (bytes memory) { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(value); + bytes memory _dynamicData = encodeDynamic(value); - return abi.encodePacked(_encodedLengths.unwrap(), EncodeArray.encode((value))); + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/world/test/tables/Bool.sol b/packages/world/test/tables/Bool.sol index 955432d6b9..9d471471ac 100644 --- a/packages/world/test/tables/Bool.sol +++ b/packages/world/test/tables/Bool.sol @@ -100,9 +100,19 @@ library Bool { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); } + /** 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) { - return abi.encodePacked(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b66e40e5bd..cedd484c9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -782,14 +782,14 @@ importers: specifier: ^0.2.22 version: 0.2.22(typescript@5.1.6) better-sqlite3: - specifier: ^8.4.0 - version: 8.4.0 + specifier: ^8.6.0 + version: 8.6.0 debug: specifier: ^4.3.4 version: 4.3.4(supports-color@8.1.1) drizzle-orm: - specifier: ^0.27.0 - version: 0.27.0(@types/better-sqlite3@7.6.4)(better-sqlite3@8.4.0)(postgres@3.3.5) + specifier: ^0.28.5 + version: 0.28.5(@types/better-sqlite3@7.6.4)(better-sqlite3@8.6.0)(postgres@3.3.5) fastify: specifier: ^4.21.0 version: 4.21.0 @@ -861,11 +861,11 @@ importers: specifier: ^4.3.4 version: 4.3.4(supports-color@8.1.1) drizzle-orm: - specifier: ^0.27.0 - version: 0.27.0(@types/sql.js@1.4.4)(kysely@0.26.1)(postgres@3.3.5)(sql.js@1.8.0) + specifier: ^0.28.5 + version: 0.28.5(@types/sql.js@1.4.4)(kysely@0.26.3)(postgres@3.3.5)(sql.js@1.8.0) kysely: - specifier: ^0.26.1 - version: 0.26.1 + specifier: ^0.26.3 + version: 0.26.3 postgres: specifier: ^3.3.5 version: 3.3.5 @@ -4064,8 +4064,8 @@ packages: is-windows: 1.0.2 dev: true - /better-sqlite3@8.4.0: - resolution: {integrity: sha512-NmsNW1CQvqMszu/CFAJ3pLct6NEFlNfuGM6vw72KHkjOD1UDnL96XNN1BMQc1hiHo8vE2GbOWQYIpZ+YM5wrZw==} + /better-sqlite3@8.6.0: + resolution: {integrity: sha512-jwAudeiTMTSyby+/SfbHDebShbmC2MCH8mU2+DXi0WJfv13ypEJm47cd3kljmy/H130CazEvkf2Li//ewcMJ1g==} requiresBuild: true dependencies: bindings: 1.5.0 @@ -4953,8 +4953,8 @@ packages: detect-libc: 1.0.3 dev: true - /drizzle-orm@0.27.0(@types/better-sqlite3@7.6.4)(better-sqlite3@8.4.0)(postgres@3.3.5): - resolution: {integrity: sha512-LGiJ0icB+wQwgbSCOvAjONY8Ec6G/EDzQQP5PmUaQYeI9OqgpVKHC2T1fFIbvk5dabWsbokJ5NOciVAxriStig==} + /drizzle-orm@0.28.5(@types/better-sqlite3@7.6.4)(better-sqlite3@8.6.0)(postgres@3.3.5): + resolution: {integrity: sha512-6r6Iw4c38NAmW6TiKH3TUpGUQ1YdlEoLJOQptn8XPx3Z63+vFNKfAiANqrIiYZiMjKR9+NYAL219nFrmo1duXA==} peerDependencies: '@aws-sdk/client-rds-data': '>=3' '@cloudflare/workers-types': '>=3' @@ -5016,12 +5016,12 @@ packages: optional: true dependencies: '@types/better-sqlite3': 7.6.4 - better-sqlite3: 8.4.0 + better-sqlite3: 8.6.0 postgres: 3.3.5 dev: false - /drizzle-orm@0.27.0(@types/sql.js@1.4.4)(kysely@0.26.1)(postgres@3.3.5)(sql.js@1.8.0): - resolution: {integrity: sha512-LGiJ0icB+wQwgbSCOvAjONY8Ec6G/EDzQQP5PmUaQYeI9OqgpVKHC2T1fFIbvk5dabWsbokJ5NOciVAxriStig==} + /drizzle-orm@0.28.5(@types/sql.js@1.4.4)(kysely@0.26.3)(postgres@3.3.5)(sql.js@1.8.0): + resolution: {integrity: sha512-6r6Iw4c38NAmW6TiKH3TUpGUQ1YdlEoLJOQptn8XPx3Z63+vFNKfAiANqrIiYZiMjKR9+NYAL219nFrmo1duXA==} peerDependencies: '@aws-sdk/client-rds-data': '>=3' '@cloudflare/workers-types': '>=3' @@ -5083,7 +5083,7 @@ packages: optional: true dependencies: '@types/sql.js': 1.4.4 - kysely: 0.26.1 + kysely: 0.26.3 postgres: 3.3.5 sql.js: 1.8.0 dev: false @@ -7630,8 +7630,8 @@ packages: engines: {node: '>=6'} dev: true - /kysely@0.26.1: - resolution: {integrity: sha512-FVRomkdZofBu3O8SiwAOXrwbhPZZr8mBN5ZeUWyprH29jzvy6Inzqbd0IMmGxpd4rcOCL9HyyBNWBa8FBqDAdg==} + /kysely@0.26.3: + resolution: {integrity: sha512-yWSgGi9bY13b/W06DD2OCDDHQmq1kwTGYlQ4wpZkMOJqMGCstVCFIvxCCVG4KfY1/3G0MhDAcZsip/Lw8/vJWw==} engines: {node: '>=14.0.0'} dev: false diff --git a/templates/phaser/packages/client/src/mud/setupNetwork.ts b/templates/phaser/packages/client/src/mud/setupNetwork.ts index 66a27a95ae..6fe7d00e2c 100644 --- a/templates/phaser/packages/client/src/mud/setupNetwork.ts +++ b/templates/phaser/packages/client/src/mud/setupNetwork.ts @@ -72,7 +72,7 @@ export async function setupNetwork() { * to the viem publicClient to make RPC calls to fetch MUD * events from the chain. */ - const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({ + const { components, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToRecs({ world, config: mudConfig, address: networkConfig.worldAddress as Hex, @@ -115,7 +115,7 @@ export async function setupNetwork() { publicClient, walletClient: burnerWalletClient, latestBlock$, - blockStorageOperations$, + storedBlockLogs$, waitForTransaction, worldContract, write$: write$.asObservable().pipe(share()), diff --git a/templates/phaser/packages/client/src/ui/App.tsx b/templates/phaser/packages/client/src/ui/App.tsx index 47c66ae8f8..a61f2ba87e 100644 --- a/templates/phaser/packages/client/src/ui/App.tsx +++ b/templates/phaser/packages/client/src/ui/App.tsx @@ -21,7 +21,7 @@ export const App = () => { publicClient: networkLayer.network.publicClient, walletClient: networkLayer.network.walletClient, latestBlock$: networkLayer.network.latestBlock$, - blockStorageOperations$: networkLayer.network.blockStorageOperations$, + storedBlockLogs$: networkLayer.network.storedBlockLogs$, worldAddress: networkLayer.network.worldContract.address, worldAbi: networkLayer.network.worldContract.abi, write$: networkLayer.network.write$, diff --git a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol index 302b905c36..6b2a3f319b 100644 --- a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol @@ -103,9 +103,19 @@ library Counter { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint32 value) internal pure returns (bytes memory) { + return abi.encodePacked(value); + } + /** Tightly pack full data using this table's field layout */ function encode(uint32 value) internal pure returns (bytes memory) { - return abi.encodePacked(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/templates/react/packages/client/src/index.tsx b/templates/react/packages/client/src/index.tsx index 9b3f9121e1..da8d70f020 100644 --- a/templates/react/packages/client/src/index.tsx +++ b/templates/react/packages/client/src/index.tsx @@ -24,7 +24,7 @@ setup().then(async (result) => { publicClient: result.network.publicClient, walletClient: result.network.walletClient, latestBlock$: result.network.latestBlock$, - blockStorageOperations$: result.network.blockStorageOperations$, + storedBlockLogs$: result.network.storedBlockLogs$, worldAddress: result.network.worldContract.address, worldAbi: result.network.worldContract.abi, write$: result.network.write$, diff --git a/templates/react/packages/client/src/mud/setupNetwork.ts b/templates/react/packages/client/src/mud/setupNetwork.ts index de4b2c23dd..15d3555441 100644 --- a/templates/react/packages/client/src/mud/setupNetwork.ts +++ b/templates/react/packages/client/src/mud/setupNetwork.ts @@ -74,7 +74,7 @@ export async function setupNetwork() { * to the viem publicClient to make RPC calls to fetch MUD * events from the chain. */ - const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({ + const { components, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToRecs({ world, config: mudConfig, address: networkConfig.worldAddress as Hex, @@ -117,7 +117,7 @@ export async function setupNetwork() { publicClient, walletClient: burnerWalletClient, latestBlock$, - blockStorageOperations$, + storedBlockLogs$, waitForTransaction, worldContract, write$: write$.asObservable().pipe(share()), diff --git a/templates/react/packages/contracts/src/codegen/tables/Counter.sol b/templates/react/packages/contracts/src/codegen/tables/Counter.sol index 302b905c36..6b2a3f319b 100644 --- a/templates/react/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/react/packages/contracts/src/codegen/tables/Counter.sol @@ -103,9 +103,19 @@ library Counter { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint32 value) internal pure returns (bytes memory) { + return abi.encodePacked(value); + } + /** Tightly pack full data using this table's field layout */ function encode(uint32 value) internal pure returns (bytes memory) { - return abi.encodePacked(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/templates/threejs/packages/client/src/index.tsx b/templates/threejs/packages/client/src/index.tsx index 9b3f9121e1..da8d70f020 100644 --- a/templates/threejs/packages/client/src/index.tsx +++ b/templates/threejs/packages/client/src/index.tsx @@ -24,7 +24,7 @@ setup().then(async (result) => { publicClient: result.network.publicClient, walletClient: result.network.walletClient, latestBlock$: result.network.latestBlock$, - blockStorageOperations$: result.network.blockStorageOperations$, + storedBlockLogs$: result.network.storedBlockLogs$, worldAddress: result.network.worldContract.address, worldAbi: result.network.worldContract.abi, write$: result.network.write$, diff --git a/templates/threejs/packages/client/src/mud/setupNetwork.ts b/templates/threejs/packages/client/src/mud/setupNetwork.ts index ca2dc8d669..eb8a98ae84 100644 --- a/templates/threejs/packages/client/src/mud/setupNetwork.ts +++ b/templates/threejs/packages/client/src/mud/setupNetwork.ts @@ -72,7 +72,7 @@ export async function setupNetwork() { * to the viem publicClient to make RPC calls to fetch MUD * events from the chain. */ - const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({ + const { components, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToRecs({ world, config: mudConfig, address: networkConfig.worldAddress as Hex, @@ -115,7 +115,7 @@ export async function setupNetwork() { publicClient, walletClient: burnerWalletClient, latestBlock$, - blockStorageOperations$, + storedBlockLogs$, waitForTransaction, worldContract, write$: write$.asObservable().pipe(share()), diff --git a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol index fa15b967dc..b93c3a63c3 100644 --- a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol +++ b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol @@ -209,22 +209,28 @@ library Position { /** Set the full data using individual values */ function set(bytes32 key, int32 x, int32 y, int32 z) internal { - bytes memory _data = encode(x, y, z); + bytes memory _staticData = encodeStatic(x, y, z); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 key, int32 x, int32 y, int32 z) internal { - bytes memory _data = encode(x, y, z); + bytes memory _staticData = encodeStatic(x, y, z); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setRecord(_tableId, _keyTuple, _data, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); } /** Set the full data using the data struct */ @@ -246,9 +252,19 @@ library Position { _table.z = (int32(uint32(Bytes.slice4(_blob, 8)))); } + /** 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); + } + /** Tightly pack full data using this table's field layout */ function encode(int32 x, int32 y, int32 z) internal pure returns (bytes memory) { - return abi.encodePacked(x, y, z); + bytes memory _staticData = encodeStatic(x, y, z); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/templates/vanilla/packages/client/src/index.ts b/templates/vanilla/packages/client/src/index.ts index 71b05b1f8d..0c7dda5720 100644 --- a/templates/vanilla/packages/client/src/index.ts +++ b/templates/vanilla/packages/client/src/index.ts @@ -28,7 +28,7 @@ if (import.meta.env.DEV) { publicClient: network.publicClient, walletClient: network.walletClient, latestBlock$: network.latestBlock$, - blockStorageOperations$: network.blockStorageOperations$, + storedBlockLogs$: network.storedBlockLogs$, worldAddress: network.worldContract.address, worldAbi: network.worldContract.abi, write$: network.write$, diff --git a/templates/vanilla/packages/client/src/mud/setupNetwork.ts b/templates/vanilla/packages/client/src/mud/setupNetwork.ts index de4b2c23dd..15d3555441 100644 --- a/templates/vanilla/packages/client/src/mud/setupNetwork.ts +++ b/templates/vanilla/packages/client/src/mud/setupNetwork.ts @@ -74,7 +74,7 @@ export async function setupNetwork() { * to the viem publicClient to make RPC calls to fetch MUD * events from the chain. */ - const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({ + const { components, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToRecs({ world, config: mudConfig, address: networkConfig.worldAddress as Hex, @@ -117,7 +117,7 @@ export async function setupNetwork() { publicClient, walletClient: burnerWalletClient, latestBlock$, - blockStorageOperations$, + storedBlockLogs$, waitForTransaction, worldContract, write$: write$.asObservable().pipe(share()), diff --git a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol index 302b905c36..6b2a3f319b 100644 --- a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol @@ -103,9 +103,19 @@ library Counter { _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); } + /** Tightly pack static data using this table's schema */ + function encodeStatic(uint32 value) internal pure returns (bytes memory) { + return abi.encodePacked(value); + } + /** Tightly pack full data using this table's field layout */ function encode(uint32 value) internal pure returns (bytes memory) { - return abi.encodePacked(value); + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/test-data/world-logs.json b/test-data/world-logs.json index 4faea58887..15e99ba751 100644 --- a/test-data/world-logs.json +++ b/test-data/world-logs.json @@ -2,824 +2,824 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000016d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000003400060030220202000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000006003025f5f5fc4c40000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000a0000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000077461626c654964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000b6669656c644c61796f757400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096b6579536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76616c7565536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012616269456e636f6465644b65794e616d657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014616269456e636f6465644669656c644e616d6573000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x1", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000022000000000a0000000000002c0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000016d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000600060030220202000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000006003025f5f5fc4c4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000077461626c654964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000b6669656c644c61796f757400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096b6579536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76616c7565536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012616269456e636f6465644b65794e616d657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014616269456e636f6465644669656c644e616d6573000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x0", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000016d756473746f7265000000000000000053746f7265486f6f6b7300000000000000000000000000000000000000000000000000000000000000000000000001c00000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x2", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000016d756473746f7265000000000000000053746f7265486f6f6b7300000000000000000000000000000000000000000000000000000000000000000000000000600000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x1", "transactionLogIndex": "0x1", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e616d6573706163654f776e6572000000000000000000000000000000000000000000000000000000000000000001c00014010014000000000000000000000000000000000000000000000000000000001001004f000000000000000000000000000000000000000000000000000000001401006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e616d657370616365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000056f776e6572000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x3", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e616d6573706163654f776e6572000000000000000000000000000000000000000000000000000000000000000000600014010014000000000000000000000000000000000000000000000000000000001001004f0000000000000000000000000000000000000000000000000000000014010061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e616d657370616365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000056f776e6572000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x2", "transactionLogIndex": "0x2", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000042616c616e636573000000000000000000000000000000000000000000000000000000000000000000000000000001c00020010020000000000000000000000000000000000000000000000000000000001001004f000000000000000000000000000000000000000000000000000000002001001f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e616d6573706163650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000762616c616e636500000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x4", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000042616c616e636573000000000000000000000000000000000000000000000000000000000000000000000000000000600020010020000000000000000000000000000000000000000000000000000000001001004f000000000000000000000000000000000000000000000000000000002001001f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e616d6573706163650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000762616c616e636500000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x3", "transactionLogIndex": "0x3", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e7374616c6c65644d6f64756c657300000000000000000000000000000000000000000000000000000000000002200014010014000000000000000000000000000000000000000000000000000000003002004f5f0000000000000000000000000000000000000000000000000000001401006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000100000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000a6d6f64756c654e616d6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d617267756d656e74734861736800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d6d6f64756c654164647265737300000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x5", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a00000000100000000000001a00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e7374616c6c65644d6f64756c657300000000000000000000000000000000000000000000000000000000000000600014010014000000000000000000000000000000000000000000000000000000003002004f5f0000000000000000000000000000000000000000000000000000001401006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000a6d6f64756c654e616d6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d617267756d656e74734861736800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d6d6f64756c654164647265737300000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x4", "transactionLogIndex": "0x4", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000044656c65676174696f6e730000000000000000000000000000000000000000000000000000000000000000000000022000200100200000000000000000000000000000000000000000000000000000000028020061610000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000100000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000964656c656761746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964656c6567617465650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001364656c65676174696f6e436f6e74726f6c496400000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x6", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a00000000100000000000001a0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000044656c65676174696f6e730000000000000000000000000000000000000000000000000000000000000000000000006000200100200000000000000000000000000000000000000000000000000000000028020061610000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000964656c656761746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964656c6567617465650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001364656c65676174696f6e436f6e74726f6c496400000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x5", "transactionLogIndex": "0x5", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000002200001010001000000000000000000000000000000000000000000000000000000003402005f610000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000100000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000663616c6c6572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000066163636573730000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x7", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a00000000100000000000001a000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000600001010001000000000000000000000000000000000000000000000000000000003402005f610000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000663616c6c6572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000066163636573730000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x6", "transactionLogIndex": "0x6", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000002200015020014010000000000000000000000000000000000000000000000000000002001005f0000000000000000000000000000000000000000000000000000000015020061600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000a0000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f72000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000673797374656d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7075626c69634163636573730000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x8", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000600015020014010000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000001502006160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f72000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000673797374656d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7075626c69634163636573730000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x7", "transactionLogIndex": "0x7", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000022000240200200400000000000000000000000000000000000000000000000000000004010043000000000000000000000000000000000000000000000000000000002402005f430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001066756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001673797374656d46756e6374696f6e53656c6563746f7200000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x9", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000240200200400000000000000000000000000000000000000000000000000000004010043000000000000000000000000000000000000000000000000000000002402005f43000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001066756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001673797374656d46756e6374696f6e53656c6563746f7200000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x8", "transactionLogIndex": "0x8", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d486f6f6b73000000000000000000000000000000000000000000000000000000000000000000000001c00000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0xa", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d486f6f6b73000000000000000000000000000000000000000000000000000000000000000000000000600000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x9", "transactionLogIndex": "0x9", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d5265676973747279000000000000000000000000000000000000000000000000000000000000000001c000200100200000000000000000000000000000000000000000000000000000000014010061000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000673797374656d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0xb", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d52656769737472790000000000000000000000000000000000000000000000000000000000000000006000200100200000000000000000000000000000000000000000000000000000000014010061000000000000000000000000000000000000000000000000000000002001005f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000673797374656d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0xa", "transactionLogIndex": "0xa", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000001c00001010001000000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c7265736f75726365547970650000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0xc", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000600001010001000000000000000000000000000000000000000000000000000000002001005f0000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c7265736f75726365547970650000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0xb", "transactionLogIndex": "0xb", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000004e616d6573706163654f776e657200000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0xd", + "data": "0x000000000000000000000000000000004e616d6573706163654f776e6572000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0xc", "transactionLogIndex": "0xc", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000005265736f7572636541636365737300000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0xe", + "data": "0x000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0xd", "transactionLogIndex": "0xd", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000005265736f7572636554797065000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0xf", + "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0xe", "transactionLogIndex": "0xe", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000005265736f7572636554797065000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000636f72652e730000000000000000000000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x10", + "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000636f72652e730000000000000000000000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0xf", "transactionLogIndex": "0xf", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000053797374656d73000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000636f72652e73000000000000000000000000000000000000000000000000000000000000000000000000000000000015cafac3dd18ac6c6e92c921884f9e4176737c052c010000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x11", + "data": "0x0000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000636f72652e73000000000000000000000000000000000000000000000000000000000000000000000000000000000015cafac3dd18ac6c6e92c921884f9e4176737c052c0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x10", "transactionLogIndex": "0x10", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x0000000000000000000000000000000053797374656d526567697374727900000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000636f72652e7300000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x12", + "data": "0x0000000000000000000000000000000053797374656d5265676973747279000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000636f72652e7300000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x11", "transactionLogIndex": "0x11", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000005265736f7572636541636365737300000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x13", + "data": "0x000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x12", "transactionLogIndex": "0x12", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000140554c3a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000040554c3a00000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x14", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000140554c3a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000040554c3a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x13", "transactionLogIndex": "0x13", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000018d53b20800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008d53b20800000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x15", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000018d53b20800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008d53b208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x14", "transactionLogIndex": "0x14", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000125f6221000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000025f6221000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x16", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000125f6221000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000025f62210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x15", "transactionLogIndex": "0x15", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000012bfaa27400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000002bfaa27400000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x17", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000012bfaa27400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000002bfaa274000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x16", "transactionLogIndex": "0x16", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000121293ca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000021293ca000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x18", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000121293ca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000021293ca0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x17", "transactionLogIndex": "0x17", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000018818929400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008818929400000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x19", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000013ea8492200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003ea84922000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x18", "transactionLogIndex": "0x18", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000018da798da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008da798da00000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x1a", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000018da798da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008da798da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x19", "transactionLogIndex": "0x19", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010ba51f4900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000000ba51f4900000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x1b", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010ba51f4900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000000ba51f49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x1a", "transactionLogIndex": "0x1a", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001530f4b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000530f4b6000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x1c", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001530f4b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000530f4b60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x1b", "transactionLogIndex": "0x1b", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010560912900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000000560912900000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x1d", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010560912900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000005609129000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x1c", "transactionLogIndex": "0x1c", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a886545e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000a886545e00000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x1e", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001a886545e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000a886545e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x1d", "transactionLogIndex": "0x1d", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001d5f8337f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000d5f8337f00000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x1f", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001d5f8337f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000d5f8337f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x1e", "transactionLogIndex": "0x1e", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a92813ad00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000a92813ad00000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x20", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001a92813ad00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000a92813ad000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x1f", "transactionLogIndex": "0x1f", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000013350b6a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003350b6a900000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x21", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000013350b6a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003350b6a9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x20", "transactionLogIndex": "0x20", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000013c03a51c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003c03a51c00000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x22", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000013c03a51c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003c03a51c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x21", "transactionLogIndex": "0x21", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001b7a3c75600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000b7a3c75600000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x23", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001b7a3c75600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000b7a3c756000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x22", "transactionLogIndex": "0x22", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000011d2257ba00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000001d2257ba00000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x24", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000011d2257ba00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000001d2257ba000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x23", "transactionLogIndex": "0x23", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x00000000000000000000000000000000496e7374616c6c65644d6f64756c6573000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002636f72652e6d0000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000014e7f1725e7734ce288f8367e1bb143e90bb3f0512000000000000000000000000", - "blockHash": "0xfe43f23153c69149ebe20b5941cccf8c55f4bf3acd82b33445ace71a2c5f8a9c", - "blockNumber": "0x2", - "transactionHash": "0xae82b15a8c62db1e23d9c523e730d9b861eed20529b8cff4d3452f86ae3149df", - "transactionIndex": "0x7", - "logIndex": "0x25", + "data": "0x00000000000000000000000000000000496e7374616c6c65644d6f64756c657300000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000002636f72652e6d0000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000014e7f1725e7734ce288f8367e1bb143e90bb3f0512000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "transactionIndex": "0x0", + "logIndex": "0x24", "transactionLogIndex": "0x24", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000005265736f7572636554797065000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737400000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0x7bca8d7dabf72bfa9ff127d2d2fac95a747b5cbd45e44d820789f14a6d340d2f", - "transactionIndex": "0x0", - "logIndex": "0x0", + "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265720000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x607b94e53ff6d14c8af149f742239040a26773006b3916fca7403ab56bc1addf", + "transactionIndex": "0x1", + "logIndex": "0x25", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c697374000000000000000000000000000000000000000000000000000000000000000000000000016000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000040000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0x7bca8d7dabf72bfa9ff127d2d2fac95a747b5cbd45e44d820789f14a6d340d2f", - "transactionIndex": "0x0", - "logIndex": "0x1", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d626572000000000000000000000000000000000000000000000000000000000000000000000000000000000060000401000400000000000000000000000000000000000000000000000000000000040100030000000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x607b94e53ff6d14c8af149f742239040a26773006b3916fca7403ab56bc1addf", + "transactionIndex": "0x1", + "logIndex": "0x26", "transactionLogIndex": "0x1", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000005265736f7572636554797065000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xb5f9defc11305940c4b08a6f34cdb4a671fde33905f288048b70c85b1d0875eb", - "transactionIndex": "0x1", - "logIndex": "0x2", + "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000566563746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x5a88a5686556db275ec64403ada8ee92a761403bfd712f21b6746aabb0029f12", + "transactionIndex": "0x2", + "logIndex": "0x27", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000053797374656d73000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000155fc8d32690cc91d4c39d9d3abcbd16989f875707010000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xb5f9defc11305940c4b08a6f34cdb4a671fde33905f288048b70c85b1d0875eb", - "transactionIndex": "0x1", - "logIndex": "0x3", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000010000000000a0000000000001a00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000566563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000006000080200040400000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000802002323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b6579000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017900000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x5a88a5686556db275ec64403ada8ee92a761403bfd712f21b6746aabb0029f12", + "transactionIndex": "0x2", + "logIndex": "0x28", "transactionLogIndex": "0x1", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x0000000000000000000000000000000053797374656d526567697374727900000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f875707000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000437573746f6d4572726f727353797374", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xb5f9defc11305940c4b08a6f34cdb4a671fde33905f288048b70c85b1d0875eb", - "transactionIndex": "0x1", - "logIndex": "0x4", - "transactionLogIndex": "0x2", + "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737400000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0xaed15d9b279865d827e86039036fcc9d86c5467e36441834ba1f78991785229d", + "transactionIndex": "0x3", + "logIndex": "0x29", + "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x000000000000000000000000000000005265736f7572636541636365737300000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570700000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xb5f9defc11305940c4b08a6f34cdb4a671fde33905f288048b70c85b1d0875eb", - "transactionIndex": "0x1", - "logIndex": "0x5", - "transactionLogIndex": "0x3", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a00000000040000000000000e000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c697374000000000000000000000000000000000000000000000000000000000000000000000000006000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0xaed15d9b279865d827e86039036fcc9d86c5467e36441834ba1f78991785229d", + "transactionIndex": "0x3", + "logIndex": "0x2a", + "transactionLogIndex": "0x1", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000005265736f7572636554797065000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0x5e56042175cee9139c0439cc0df13d0efbdb1a57e93e5353f8fc713ea061bfce", - "transactionIndex": "0x2", - "logIndex": "0x6", + "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004d756c7469000000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x126a9b9fbea2e94295dfd3b380c2f43f4fc96fe1ee732e4d3df29b2433ac5dc1", + "transactionIndex": "0x4", + "logIndex": "0x2b", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000053797374656d73000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000150165878a594ca255338adfa4d48449f69242eb8f010000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0x5e56042175cee9139c0439cc0df13d0efbdb1a57e93e5353f8fc713ea061bfce", - "transactionIndex": "0x2", - "logIndex": "0x7", + "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000010000000001c0000000000002c000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004d756c74690000000000000000000000000000000000000000000000000000000000000000000000000000000000006000210200200100000000000000000000000000000000000000000000000000000034040003601f2e000000000000000000000000000000000000000000000000002102003f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000036e756d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x126a9b9fbea2e94295dfd3b380c2f43f4fc96fe1ee732e4d3df29b2433ac5dc1", + "transactionIndex": "0x4", + "logIndex": "0x2c", "transactionLogIndex": "0x1", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x0000000000000000000000000000000053797374656d526567697374727900000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000004e756d6265724c69737453797374656d", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0x5e56042175cee9139c0439cc0df13d0efbdb1a57e93e5353f8fc713ea061bfce", - "transactionIndex": "0x2", - "logIndex": "0x8", - "transactionLogIndex": "0x2", + "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0xfb5bf0734dca864b8b13107223cb02facd6803ef1a03f39b325cd96a5ab4fd02", + "transactionIndex": "0x5", + "logIndex": "0x2d", + "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x000000000000000000000000000000005265736f7572636541636365737300000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0x5e56042175cee9139c0439cc0df13d0efbdb1a57e93e5353f8fc713ea061bfce", - "transactionIndex": "0x2", - "logIndex": "0x9", - "transactionLogIndex": "0x3", + "data": "0x0000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000155fc8d32690cc91d4c39d9d3abcbd16989f8757070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0xfb5bf0734dca864b8b13107223cb02facd6803ef1a03f39b325cd96a5ab4fd02", + "transactionIndex": "0x5", + "logIndex": "0x2e", + "transactionLogIndex": "0x1", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000005265736f7572636554797065000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000566563746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xb3febd63ed51098bd7062390e4e859508e55a1bbfa5ee8ec197a4df93586f632", - "transactionIndex": "0x3", - "logIndex": "0xa", - "transactionLogIndex": "0x0", + "data": "0x0000000000000000000000000000000053797374656d5265676973747279000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f875707000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000437573746f6d4572726f727353797374", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0xfb5bf0734dca864b8b13107223cb02facd6803ef1a03f39b325cd96a5ab4fd02", + "transactionIndex": "0x5", + "logIndex": "0x2f", + "transactionLogIndex": "0x2", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000566563746f72000000000000000000000000000000000000000000000000000000000000000000000000000000000220000802000404000000000000000000000000000000000000000000000000000000040100030000000000000000000000000000000000000000000000000000000008020023230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000a0000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b6579000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017900000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xb3febd63ed51098bd7062390e4e859508e55a1bbfa5ee8ec197a4df93586f632", - "transactionIndex": "0x3", - "logIndex": "0xb", - "transactionLogIndex": "0x1", + "data": "0x000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570700000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0xfb5bf0734dca864b8b13107223cb02facd6803ef1a03f39b325cd96a5ab4fd02", + "transactionIndex": "0x5", + "logIndex": "0x30", + "transactionLogIndex": "0x3", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000005265736f7572636554797065000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265720000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xd9aea844188d36cd599b3d9ddd523b1269131ec10ebf5b107a50bffe8a03985e", - "transactionIndex": "0x4", - "logIndex": "0xc", + "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x3a45c7867bdaafbebbfe02dc2eb9c7dedd4b6fd27f2540febb2fb49c8caa6ea5", + "transactionIndex": "0x6", + "logIndex": "0x31", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265720000000000000000000000000000000000000000000000000000000000000000000000000000000001c000040100040000000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000401000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xd9aea844188d36cd599b3d9ddd523b1269131ec10ebf5b107a50bffe8a03985e", - "transactionIndex": "0x4", - "logIndex": "0xd", + "data": "0x0000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000150165878a594ca255338adfa4d48449f69242eb8f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x3a45c7867bdaafbebbfe02dc2eb9c7dedd4b6fd27f2540febb2fb49c8caa6ea5", + "transactionIndex": "0x6", + "logIndex": "0x32", "transactionLogIndex": "0x1", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x000000000000000000000000000000005265736f7572636554797065000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004d756c7469000000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xa50c88a503c25f17dc6c8e4cc779f15341f6f8242da501989a64ec87a8f5a85b", - "transactionIndex": "0x5", - "logIndex": "0xe", - "transactionLogIndex": "0x0", + "data": "0x0000000000000000000000000000000053797374656d5265676973747279000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000004e756d6265724c69737453797374656d", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x3a45c7867bdaafbebbfe02dc2eb9c7dedd4b6fd27f2540febb2fb49c8caa6ea5", + "transactionIndex": "0x6", + "logIndex": "0x33", + "transactionLogIndex": "0x2", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" ], - "data": "0x6d756473746f726500000000000000005461626c657300000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004d756c74690000000000000000000000000000000000000000000000000000000000000000000000000000000000034000210200200100000000000000000000000000000000000000000000000000000034040003601f2e000000000000000000000000000000000000000000000000002102003f600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001c0000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000036e756d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xa50c88a503c25f17dc6c8e4cc779f15341f6f8242da501989a64ec87a8f5a85b", - "transactionIndex": "0x5", - "logIndex": "0xf", - "transactionLogIndex": "0x1", + "data": "0x000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x3a45c7867bdaafbebbfe02dc2eb9c7dedd4b6fd27f2540febb2fb49c8caa6ea5", + "transactionIndex": "0x6", + "logIndex": "0x34", + "transactionLogIndex": "0x3", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000015f644e3c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000437573746f6d4572726f7273537973745f644e3c00000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xff27259bf2a15d32d629b5f2dce0f7b248400c760cd4a4f367670e87b4cf81fb", - "transactionIndex": "0x6", - "logIndex": "0x10", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000015f644e3c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000437573746f6d4572726f7273537973745f644e3c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x99183c2ecbd4300f807d9903e3a0048eb27d80386fd655ff4b3bdf4aea5d5208", + "transactionIndex": "0x7", + "logIndex": "0x35", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001b8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656db8a44c7c00000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0x704d3a95376db47cabae3ba83743e46e1eb751b82a9b622af5a555e109d59a66", - "transactionIndex": "0x7", - "logIndex": "0x11", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001a4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656da4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0xa96d498c47174e6315617f6ef8e0fd6e93974a63c77152d173803f070f8023a6", + "transactionIndex": "0x8", + "logIndex": "0x36", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001a4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656da4ece52c00000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0x9d7756b56cd32ba0a3305788a5c412eae328b0a28c4ff2e46f5db939a1190a77", - "transactionIndex": "0x8", - "logIndex": "0x12", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001f7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656df7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x77b03de8eef7f084dea0958f5f69c881d3ff3ae5df88d32110e9095536640b66", + "transactionIndex": "0x9", + "logIndex": "0x37", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001f7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656df7f0e44000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0x8a7d4a27b5a121f77b0011d084850b4502db7cc7e30f5a22e1fdf61247eac74c", - "transactionIndex": "0x9", - "logIndex": "0x13", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656d306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0x6be14198e38f5635f834446da7a3594826ce7a404ae5e238b24c5a9cac751a74", + "transactionIndex": "0xa", + "logIndex": "0x38", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656d306d61a500000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40b6d1b700f1f3dc080ebe2d54c3553e6419da61cfeb5a5e2e2272ebe9840b9a", - "blockNumber": "0x3", - "transactionHash": "0xf97efde38e1aaee38023ff6669c33b26ac5230f364af583b6159dfec83099c02", - "transactionIndex": "0xa", - "logIndex": "0x14", + "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001b8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656db8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", + "blockNumber": "0x5", + "transactionHash": "0xbe213a215bd71f17f867b8129a24630241f970e1cf5231f8a3bb2ba412b68a70", + "transactionIndex": "0xb", + "logIndex": "0x39", "transactionLogIndex": "0x0", "removed": false }, { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0x5599f2052ade9808af7738adc73853c23894a2f1e944c827f7f6b8e948c4e885" ], - "data": "0x000000000000000000000000000000004e756d6265724c6973740000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000001a400000000000000000000000000000000000000000000000000000000", - "blockHash": "0xcc9c86d971dbe128cf77e6c94d85c369dc31f6a9b0b75324cc5feb5215a4b045", - "blockNumber": "0x4", - "transactionHash": "0x6b11c4b4d9257da889cd755a9aef98068339dea0770f3c43def5293c47977876", + "data": "0x000000000000000000000000000000004e756d6265724c69737400000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000040000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000001a400000000000000000000000000000000000000000000000000000000", + "blockHash": "0xbca51e861d5bfa7243f5c4b4dd5bf4e38874df40b4489bd87e14e0dca7fb434d", + "blockNumber": "0x6", + "transactionHash": "0x913934c3603cedb30d6ec5131ca347ce5f3906f6146f7fdfe39ad6008e6e0a94", "transactionIndex": "0x0", "logIndex": "0x0", "transactionLogIndex": "0x0", @@ -828,12 +828,12 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46" + "0x5599f2052ade9808af7738adc73853c23894a2f1e944c827f7f6b8e948c4e885" ], - "data": "0x000000000000000000000000000000004e756d6265724c6973740000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000001a400000045000000000000000000000000000000000000000000000000", - "blockHash": "0xcc9c86d971dbe128cf77e6c94d85c369dc31f6a9b0b75324cc5feb5215a4b045", - "blockNumber": "0x4", - "transactionHash": "0x2453e912dfab0eed54e6140d2f5c829034fe51fa844767991510eb71ecff8a3b", + "data": "0x000000000000000000000000000000004e756d6265724c69737400000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000800000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000004500000000000000000000000000000000000000000000000000000000", + "blockHash": "0xbca51e861d5bfa7243f5c4b4dd5bf4e38874df40b4489bd87e14e0dca7fb434d", + "blockNumber": "0x6", + "transactionHash": "0xa5e0a4df59ae785eb7f2abc61ab104cbd97db921a61ad3a5a34b7a959d543ca6", "transactionIndex": "0x1", "logIndex": "0x1", "transactionLogIndex": "0x0", From 211be2a1eba8600ad53be6f8c70c64a8523113b9 Mon Sep 17 00:00:00 2001 From: Boffee Date: Sat, 16 Sep 2023 12:24:52 -0500 Subject: [PATCH 03/17] feat(store): compute FieldLayout at compile time (#1508) Co-authored-by: alvarius --- .changeset/hot-mice-play.md | 8 + .../contracts/src/codegen/tables/Multi.sol | 49 ++-- .../contracts/src/codegen/tables/Number.sol | 32 ++- .../src/codegen/tables/NumberList.sol | 51 ++--- .../contracts/src/codegen/tables/Vector.sol | 49 ++-- .../src/codegen/tables/CounterTable.sol | 32 ++- .../src/codegen/tables/Inventory.sol | 32 ++- .../src/codegen/tables/MessageTable.sol | 23 +- .../src/codegen/tables/Dynamics1.sol | 216 +++++++----------- .../src/codegen/tables/Dynamics2.sol | 115 +++++----- .../src/codegen/tables/Ephemeral.sol | 24 +- .../src/codegen/tables/Singleton.sol | 124 +++++----- .../contracts/src/codegen/tables/Statics.sol | 85 +++---- packages/store/gas-report.json | 132 +++++------ .../store/src/codegen/tables/Callbacks.sol | 58 ++--- packages/store/src/codegen/tables/Hooks.sol | 58 ++--- .../store/src/codegen/tables/KeyEncoding.sol | 32 ++- packages/store/src/codegen/tables/Mixed.sol | 105 ++++----- .../store/src/codegen/tables/StoreHooks.sol | 58 ++--- packages/store/src/codegen/tables/Tables.sol | 114 +++++---- packages/store/src/codegen/tables/Vector2.sol | 49 ++-- packages/store/test/FieldLayout.t.sol | 31 +++ packages/store/ts/codegen/ephemeral.ts | 2 +- packages/store/ts/codegen/field.ts | 14 +- packages/store/ts/codegen/record.ts | 8 +- .../ts/codegen/renderFieldLayout.test.ts | 42 ++++ .../store/ts/codegen/renderFieldLayout.ts | 33 +++ packages/store/ts/codegen/renderTable.ts | 16 +- packages/store/ts/constants.ts | 23 ++ packages/world/gas-report.json | 122 +++++----- .../src/modules/core/tables/Balances.sol | 32 ++- .../modules/core/tables/FunctionSelectors.sol | 49 ++-- .../src/modules/core/tables/ResourceType.sol | 32 ++- .../src/modules/core/tables/SystemHooks.sol | 58 ++--- .../modules/core/tables/SystemRegistry.sol | 32 ++- .../world/src/modules/core/tables/Systems.sol | 49 ++-- .../keysintable/tables/KeysInTable.sol | 206 +++++++---------- .../keysintable/tables/UsedKeysIndex.sol | 49 ++-- .../keyswithvalue/tables/KeysWithValue.sol | 58 ++--- .../tables/CallboundDelegations.sol | 32 ++- .../tables/TimeboundDelegations.sol | 32 ++- .../uniqueentity/tables/UniqueEntity.sol | 32 ++- packages/world/src/tables/Delegations.sol | 32 ++- .../world/src/tables/InstalledModules.sol | 32 ++- packages/world/src/tables/NamespaceOwner.sol | 32 ++- packages/world/src/tables/ResourceAccess.sol | 32 ++- packages/world/test/tables/AddressArray.sol | 58 ++--- packages/world/test/tables/Bool.sol | 32 ++- .../contracts/src/codegen/tables/Counter.sol | 32 ++- .../contracts/src/codegen/tables/Counter.sol | 32 ++- .../contracts/src/codegen/tables/Position.sol | 58 ++--- .../contracts/src/codegen/tables/Counter.sol | 32 ++- 52 files changed, 1267 insertions(+), 1503 deletions(-) create mode 100644 .changeset/hot-mice-play.md create mode 100644 packages/store/ts/codegen/renderFieldLayout.test.ts create mode 100644 packages/store/ts/codegen/renderFieldLayout.ts create mode 100644 packages/store/ts/constants.ts diff --git a/.changeset/hot-mice-play.md b/.changeset/hot-mice-play.md new file mode 100644 index 0000000000..defaa99a25 --- /dev/null +++ b/.changeset/hot-mice-play.md @@ -0,0 +1,8 @@ +--- +"@latticexyz/cli": patch +"@latticexyz/store": patch +"@latticexyz/world": patch +--- + +The `FieldLayout` in table libraries is now generated at compile time instead of dynamically in a table library function. +This significantly reduces gas cost in all table library functions. diff --git a/e2e/packages/contracts/src/codegen/tables/Multi.sol b/e2e/packages/contracts/src/codegen/tables/Multi.sol index a66e9b0d72..2f25c111dd 100644 --- a/e2e/packages/contracts/src/codegen/tables/Multi.sol +++ b/e2e/packages/contracts/src/codegen/tables/Multi.sol @@ -21,6 +21,10 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Multi"))); bytes32 constant MultiTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0021020020010000000000000000000000000000000000000000000000000000 +); + struct MultiData { int256 num; bool value; @@ -29,11 +33,7 @@ struct MultiData { library Multi { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](2); - _fieldLayout[0] = 32; - _fieldLayout[1] = 1; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -74,19 +74,12 @@ library Multi { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get num */ @@ -97,7 +90,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (int256(uint256(Bytes.slice32(_blob, 0)))); } @@ -109,7 +102,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (int256(uint256(Bytes.slice32(_blob, 0)))); } @@ -121,7 +114,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((num)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((num)), _fieldLayout); } /** Set num (using the specified store) */ @@ -132,7 +125,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((num)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((num)), _fieldLayout); } /** Get value */ @@ -143,7 +136,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -155,7 +148,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -167,7 +160,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ @@ -178,7 +171,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((value)), _fieldLayout); } /** Get the full data */ @@ -189,7 +182,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -201,7 +194,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -218,7 +211,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -234,7 +227,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using the data struct */ @@ -288,7 +281,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -299,7 +292,7 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/e2e/packages/contracts/src/codegen/tables/Number.sol b/e2e/packages/contracts/src/codegen/tables/Number.sol index 68d463bacd..07eeb5619e 100644 --- a/e2e/packages/contracts/src/codegen/tables/Number.sol +++ b/e2e/packages/contracts/src/codegen/tables/Number.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Number"))); bytes32 constant NumberTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0004010004000000000000000000000000000000000000000000000000000000 +); + library Number { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 4; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -60,19 +61,12 @@ library Number { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ @@ -80,7 +74,7 @@ library Number { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -89,7 +83,7 @@ library Number { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -98,7 +92,7 @@ library Number { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ @@ -106,7 +100,7 @@ library Number { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -137,7 +131,7 @@ library Number { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -145,6 +139,6 @@ library Number { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _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 76ab24b8e5..0f26dba1a2 100644 --- a/e2e/packages/contracts/src/codegen/tables/NumberList.sol +++ b/e2e/packages/contracts/src/codegen/tables/NumberList.sol @@ -21,12 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("NumberList"))); bytes32 constant NumberListTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000100000000000000000000000000000000000000000000000000000000 +); + library NumberList { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 1); + return _fieldLayout; } /** Get the table's key schema */ @@ -57,26 +59,19 @@ library NumberList { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ function get() internal view returns (uint32[] memory value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -84,7 +79,7 @@ library NumberList { function get(IStore _store) internal view returns (uint32[] memory value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -92,21 +87,21 @@ library NumberList { function set(uint32[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value (using the specified store) */ function set(IStore _store, uint32[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Get the length of value */ function length() internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 4; } @@ -116,7 +111,7 @@ library NumberList { function length(IStore _store) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 4; } @@ -134,7 +129,7 @@ library NumberList { _tableId, _keyTuple, 0, - getFieldLayout(), + _fieldLayout, _index * 4, (_index + 1) * 4 ); @@ -150,7 +145,7 @@ library NumberList { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, getFieldLayout(), _index * 4, (_index + 1) * 4); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 4, (_index + 1) * 4); return (uint32(Bytes.slice4(_blob, 0))); } } @@ -159,28 +154,28 @@ library NumberList { function push(uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value (using the specified store) */ function push(IStore _store, uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from value */ function pop() internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.popFromField(_tableId, _keyTuple, 0, 4, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 0, 4, _fieldLayout); } /** Pop an element from value (using the specified store) */ function pop(IStore _store) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.popFromField(_tableId, _keyTuple, 0, 4, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 0, 4, _fieldLayout); } /** @@ -191,7 +186,7 @@ library NumberList { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -203,7 +198,7 @@ library NumberList { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - _store.updateInField(_tableId, _keyTuple, 0, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 0, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -240,13 +235,13 @@ library NumberList { function deleteRecord() internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.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, getFieldLayout()); + _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 c64c1d9086..a7870c1a6c 100644 --- a/e2e/packages/contracts/src/codegen/tables/Vector.sol +++ b/e2e/packages/contracts/src/codegen/tables/Vector.sol @@ -21,6 +21,10 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Vector"))); bytes32 constant VectorTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0008020004040000000000000000000000000000000000000000000000000000 +); + struct VectorData { int32 x; int32 y; @@ -29,11 +33,7 @@ struct VectorData { library Vector { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](2); - _fieldLayout[0] = 4; - _fieldLayout[1] = 4; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -68,19 +68,12 @@ library Vector { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get x */ @@ -88,7 +81,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -97,7 +90,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -106,7 +99,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } /** Set x (using the specified store) */ @@ -114,7 +107,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } /** Get y */ @@ -122,7 +115,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -131,7 +124,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -140,7 +133,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } /** Set y (using the specified store) */ @@ -148,7 +141,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } /** Get the full data */ @@ -156,7 +149,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -165,7 +158,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -179,7 +172,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -192,7 +185,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using the data struct */ @@ -240,7 +233,7 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -248,6 +241,6 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol index 0de74a8c72..04bf83b923 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("CounterTable"))); bytes32 constant CounterTableTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0004010004000000000000000000000000000000000000000000000000000000 +); + library CounterTable { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 4; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -58,26 +59,19 @@ library CounterTable { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ function get() internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -85,7 +79,7 @@ library CounterTable { function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -93,14 +87,14 @@ library CounterTable { function set(uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ function set(IStore _store, uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -129,13 +123,13 @@ library CounterTable { function deleteRecord() internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.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, getFieldLayout()); + _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 15c35b4678..2fe128efd0 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Inventory"))); bytes32 constant InventoryTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0004010004000000000000000000000000000000000000000000000000000000 +); + library Inventory { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 4; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -64,19 +65,12 @@ library Inventory { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get amount */ @@ -86,7 +80,7 @@ library Inventory { _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -97,7 +91,7 @@ library Inventory { _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -108,7 +102,7 @@ library Inventory { _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((amount)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((amount)), _fieldLayout); } /** Set amount (using the specified store) */ @@ -118,7 +112,7 @@ library Inventory { _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((amount)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((amount)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -153,7 +147,7 @@ library Inventory { _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -163,6 +157,6 @@ library Inventory { _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol index 142691da0a..6e58cfc3df 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol @@ -21,12 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("MessageTable"))); bytes32 constant MessageTableTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000100000000000000000000000000000000000000000000000000000000 +); + library MessageTable { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 1); + return _fieldLayout; } /** Get the table's key schema */ @@ -57,19 +59,12 @@ library MessageTable { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Emit the ephemeral event using individual values */ @@ -80,7 +75,7 @@ library MessageTable { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Emit the ephemeral event using individual values (using the specified store) */ @@ -91,7 +86,7 @@ library MessageTable { bytes32[] memory _keyTuple = new bytes32[](0); - _store.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Tightly pack dynamic data using this table's schema */ diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol index f32451cf30..9d96284463 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol @@ -21,6 +21,10 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Dynamics1"))); bytes32 constant Dynamics1TableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000500000000000000000000000000000000000000000000000000000000 +); + struct Dynamics1Data { bytes32[1] staticB32; int32[2] staticI32; @@ -32,9 +36,7 @@ struct Dynamics1Data { library Dynamics1 { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 5); + return _fieldLayout; } /** Get the table's key schema */ @@ -75,19 +77,12 @@ library Dynamics1 { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get staticB32 */ @@ -95,7 +90,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return toStaticArray_bytes32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -104,7 +99,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return toStaticArray_bytes32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -118,7 +113,7 @@ library Dynamics1 { _keyTuple, 0, EncodeArray.encode(fromStaticArray_bytes32_1(staticB32)), - getFieldLayout() + _fieldLayout ); } @@ -127,7 +122,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode(fromStaticArray_bytes32_1(staticB32)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode(fromStaticArray_bytes32_1(staticB32)), _fieldLayout); } /** Get the length of staticB32 */ @@ -135,7 +130,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 32; } @@ -146,7 +141,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 32; } @@ -165,7 +160,7 @@ library Dynamics1 { _tableId, _keyTuple, 0, - getFieldLayout(), + _fieldLayout, _index * 32, (_index + 1) * 32 ); @@ -182,14 +177,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 0, - getFieldLayout(), - _index * 32, - (_index + 1) * 32 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 32, (_index + 1) * 32); return (Bytes.slice32(_blob, 0)); } } @@ -199,7 +187,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to staticB32 (using the specified store) */ @@ -207,7 +195,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from staticB32 */ @@ -215,7 +203,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 0, 32, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); } /** Pop an element from staticB32 (using the specified store) */ @@ -223,7 +211,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 0, 32, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); } /** @@ -235,7 +223,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -248,7 +236,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -257,7 +245,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return toStaticArray_int32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_int32()); } @@ -266,7 +254,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return toStaticArray_int32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_int32()); } @@ -275,13 +263,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField( - _tableId, - _keyTuple, - 1, - EncodeArray.encode(fromStaticArray_int32_2(staticI32)), - getFieldLayout() - ); + StoreSwitch.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_int32_2(staticI32)), _fieldLayout); } /** Set staticI32 (using the specified store) */ @@ -289,7 +271,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_int32_2(staticI32)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_int32_2(staticI32)), _fieldLayout); } /** Get the length of staticI32 */ @@ -297,7 +279,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 1, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); unchecked { return _byteLength / 4; } @@ -308,7 +290,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 1, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); unchecked { return _byteLength / 4; } @@ -327,7 +309,7 @@ library Dynamics1 { _tableId, _keyTuple, 1, - getFieldLayout(), + _fieldLayout, _index * 4, (_index + 1) * 4 ); @@ -344,7 +326,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 1, getFieldLayout(), _index * 4, (_index + 1) * 4); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 1, _fieldLayout, _index * 4, (_index + 1) * 4); return (int32(uint32(Bytes.slice4(_blob, 0)))); } } @@ -354,7 +336,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to staticI32 (using the specified store) */ @@ -362,7 +344,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from staticI32 */ @@ -370,7 +352,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 1, 4, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 1, 4, _fieldLayout); } /** Pop an element from staticI32 (using the specified store) */ @@ -378,7 +360,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 1, 4, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 1, 4, _fieldLayout); } /** @@ -390,7 +372,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 1, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 1, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -403,7 +385,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 1, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 1, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -412,7 +394,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); return toStaticArray_uint128_3(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint128()); } @@ -421,7 +403,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); return toStaticArray_uint128_3(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint128()); } @@ -435,7 +417,7 @@ library Dynamics1 { _keyTuple, 2, EncodeArray.encode(fromStaticArray_uint128_3(staticU128)), - getFieldLayout() + _fieldLayout ); } @@ -444,13 +426,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField( - _tableId, - _keyTuple, - 2, - EncodeArray.encode(fromStaticArray_uint128_3(staticU128)), - getFieldLayout() - ); + _store.setField(_tableId, _keyTuple, 2, EncodeArray.encode(fromStaticArray_uint128_3(staticU128)), _fieldLayout); } /** Get the length of staticU128 */ @@ -458,7 +434,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 2, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); unchecked { return _byteLength / 16; } @@ -469,7 +445,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 2, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); unchecked { return _byteLength / 16; } @@ -488,7 +464,7 @@ library Dynamics1 { _tableId, _keyTuple, 2, - getFieldLayout(), + _fieldLayout, _index * 16, (_index + 1) * 16 ); @@ -505,14 +481,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 2, - getFieldLayout(), - _index * 16, - (_index + 1) * 16 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 16, (_index + 1) * 16); return (uint128(Bytes.slice16(_blob, 0))); } } @@ -522,7 +491,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to staticU128 (using the specified store) */ @@ -530,7 +499,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from staticU128 */ @@ -538,7 +507,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 2, 16, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 2, 16, _fieldLayout); } /** Pop an element from staticU128 (using the specified store) */ @@ -546,7 +515,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 2, 16, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 2, 16, _fieldLayout); } /** @@ -558,7 +527,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 2, _index * 16, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 2, _index * 16, abi.encodePacked((_element)), _fieldLayout); } } @@ -571,7 +540,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 2, _index * 16, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 2, _index * 16, abi.encodePacked((_element)), _fieldLayout); } } @@ -580,7 +549,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); return toStaticArray_address_4(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); } @@ -589,7 +558,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); return toStaticArray_address_4(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); } @@ -603,7 +572,7 @@ library Dynamics1 { _keyTuple, 3, EncodeArray.encode(fromStaticArray_address_4(staticAddrs)), - getFieldLayout() + _fieldLayout ); } @@ -612,13 +581,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField( - _tableId, - _keyTuple, - 3, - EncodeArray.encode(fromStaticArray_address_4(staticAddrs)), - getFieldLayout() - ); + _store.setField(_tableId, _keyTuple, 3, EncodeArray.encode(fromStaticArray_address_4(staticAddrs)), _fieldLayout); } /** Get the length of staticAddrs */ @@ -626,7 +589,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 3, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); unchecked { return _byteLength / 20; } @@ -637,7 +600,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 3, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); unchecked { return _byteLength / 20; } @@ -656,7 +619,7 @@ library Dynamics1 { _tableId, _keyTuple, 3, - getFieldLayout(), + _fieldLayout, _index * 20, (_index + 1) * 20 ); @@ -673,14 +636,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 3, - getFieldLayout(), - _index * 20, - (_index + 1) * 20 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 20, (_index + 1) * 20); return (address(Bytes.slice20(_blob, 0))); } } @@ -690,7 +646,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to staticAddrs (using the specified store) */ @@ -698,7 +654,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from staticAddrs */ @@ -706,7 +662,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 3, 20, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 3, 20, _fieldLayout); } /** Pop an element from staticAddrs (using the specified store) */ @@ -714,7 +670,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 3, 20, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 3, 20, _fieldLayout); } /** @@ -726,7 +682,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 3, _index * 20, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 3, _index * 20, abi.encodePacked((_element)), _fieldLayout); } } @@ -739,7 +695,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 3, _index * 20, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 3, _index * 20, abi.encodePacked((_element)), _fieldLayout); } } @@ -748,7 +704,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, _fieldLayout); return toStaticArray_bool_5(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bool()); } @@ -757,7 +713,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, _fieldLayout); return toStaticArray_bool_5(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bool()); } @@ -766,13 +722,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField( - _tableId, - _keyTuple, - 4, - EncodeArray.encode(fromStaticArray_bool_5(staticBools)), - getFieldLayout() - ); + StoreSwitch.setField(_tableId, _keyTuple, 4, EncodeArray.encode(fromStaticArray_bool_5(staticBools)), _fieldLayout); } /** Set staticBools (using the specified store) */ @@ -780,7 +730,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 4, EncodeArray.encode(fromStaticArray_bool_5(staticBools)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 4, EncodeArray.encode(fromStaticArray_bool_5(staticBools)), _fieldLayout); } /** Get the length of staticBools */ @@ -788,7 +738,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 4, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 4, _fieldLayout); unchecked { return _byteLength / 1; } @@ -799,7 +749,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 4, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 4, _fieldLayout); unchecked { return _byteLength / 1; } @@ -818,7 +768,7 @@ library Dynamics1 { _tableId, _keyTuple, 4, - getFieldLayout(), + _fieldLayout, _index * 1, (_index + 1) * 1 ); @@ -835,7 +785,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 4, getFieldLayout(), _index * 1, (_index + 1) * 1); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 4, _fieldLayout, _index * 1, (_index + 1) * 1); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } } @@ -845,7 +795,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to staticBools (using the specified store) */ @@ -853,7 +803,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from staticBools */ @@ -861,7 +811,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 4, 1, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 4, 1, _fieldLayout); } /** Pop an element from staticBools (using the specified store) */ @@ -869,7 +819,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 4, 1, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 4, 1, _fieldLayout); } /** @@ -881,7 +831,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 4, _index * 1, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 4, _index * 1, abi.encodePacked((_element)), _fieldLayout); } } @@ -894,7 +844,7 @@ library Dynamics1 { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 4, _index * 1, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 4, _index * 1, abi.encodePacked((_element)), _fieldLayout); } } @@ -903,7 +853,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -912,7 +862,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -932,7 +882,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -952,7 +902,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using the data struct */ @@ -1075,7 +1025,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -1083,7 +1033,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol index 9ced950df1..2317c58515 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol @@ -21,6 +21,10 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Dynamics2"))); bytes32 constant Dynamics2TableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000300000000000000000000000000000000000000000000000000000000 +); + struct Dynamics2Data { uint64[] u64; string str; @@ -30,9 +34,7 @@ struct Dynamics2Data { library Dynamics2 { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 3); + return _fieldLayout; } /** Get the table's key schema */ @@ -69,19 +71,12 @@ library Dynamics2 { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get u64 */ @@ -89,7 +84,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint64()); } @@ -98,7 +93,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint64()); } @@ -107,7 +102,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((u64)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((u64)), _fieldLayout); } /** Set u64 (using the specified store) */ @@ -115,7 +110,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((u64)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((u64)), _fieldLayout); } /** Get the length of u64 */ @@ -123,7 +118,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 8; } @@ -134,7 +129,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 8; } @@ -153,7 +148,7 @@ library Dynamics2 { _tableId, _keyTuple, 0, - getFieldLayout(), + _fieldLayout, _index * 8, (_index + 1) * 8 ); @@ -170,7 +165,7 @@ library Dynamics2 { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, getFieldLayout(), _index * 8, (_index + 1) * 8); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 8, (_index + 1) * 8); return (uint64(Bytes.slice8(_blob, 0))); } } @@ -180,7 +175,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to u64 (using the specified store) */ @@ -188,7 +183,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from u64 */ @@ -196,7 +191,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 0, 8, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 0, 8, _fieldLayout); } /** Pop an element from u64 (using the specified store) */ @@ -204,7 +199,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 0, 8, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 0, 8, _fieldLayout); } /** @@ -216,7 +211,7 @@ library Dynamics2 { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 8, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 8, abi.encodePacked((_element)), _fieldLayout); } } @@ -229,7 +224,7 @@ library Dynamics2 { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 0, _index * 8, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 0, _index * 8, abi.encodePacked((_element)), _fieldLayout); } } @@ -238,7 +233,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (string(_blob)); } @@ -247,7 +242,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (string(_blob)); } @@ -256,7 +251,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 1, bytes((str)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, bytes((str)), _fieldLayout); } /** Set str (using the specified store) */ @@ -264,7 +259,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 1, bytes((str)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, bytes((str)), _fieldLayout); } /** Get the length of str */ @@ -272,7 +267,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 1, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); unchecked { return _byteLength / 1; } @@ -283,7 +278,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 1, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); unchecked { return _byteLength / 1; } @@ -302,7 +297,7 @@ library Dynamics2 { _tableId, _keyTuple, 1, - getFieldLayout(), + _fieldLayout, _index * 1, (_index + 1) * 1 ); @@ -319,7 +314,7 @@ library Dynamics2 { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 1, getFieldLayout(), _index * 1, (_index + 1) * 1); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 1, _fieldLayout, _index * 1, (_index + 1) * 1); return (string(_blob)); } } @@ -329,7 +324,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 1, bytes((_slice)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 1, bytes((_slice)), _fieldLayout); } /** Push a slice to str (using the specified store) */ @@ -337,7 +332,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 1, bytes((_slice)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 1, bytes((_slice)), _fieldLayout); } /** Pop a slice from str */ @@ -345,7 +340,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 1, 1, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 1, 1, _fieldLayout); } /** Pop a slice from str (using the specified store) */ @@ -353,7 +348,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 1, 1, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 1, 1, _fieldLayout); } /** @@ -365,7 +360,7 @@ library Dynamics2 { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 1, _index * 1, bytes((_slice)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 1, _index * 1, bytes((_slice)), _fieldLayout); } } @@ -378,7 +373,7 @@ library Dynamics2 { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 1, _index * 1, bytes((_slice)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 1, _index * 1, bytes((_slice)), _fieldLayout); } } @@ -387,7 +382,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); return (bytes(_blob)); } @@ -396,7 +391,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); return (bytes(_blob)); } @@ -405,7 +400,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 2, bytes((b)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 2, bytes((b)), _fieldLayout); } /** Set b (using the specified store) */ @@ -413,7 +408,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 2, bytes((b)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 2, bytes((b)), _fieldLayout); } /** Get the length of b */ @@ -421,7 +416,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 2, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); unchecked { return _byteLength / 1; } @@ -432,7 +427,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 2, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); unchecked { return _byteLength / 1; } @@ -451,7 +446,7 @@ library Dynamics2 { _tableId, _keyTuple, 2, - getFieldLayout(), + _fieldLayout, _index * 1, (_index + 1) * 1 ); @@ -468,7 +463,7 @@ library Dynamics2 { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, getFieldLayout(), _index * 1, (_index + 1) * 1); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 1, (_index + 1) * 1); return (bytes(_blob)); } } @@ -478,7 +473,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 2, bytes((_slice)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 2, bytes((_slice)), _fieldLayout); } /** Push a slice to b (using the specified store) */ @@ -486,7 +481,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 2, bytes((_slice)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 2, bytes((_slice)), _fieldLayout); } /** Pop a slice from b */ @@ -494,7 +489,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 2, 1, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 2, 1, _fieldLayout); } /** Pop a slice from b (using the specified store) */ @@ -502,7 +497,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 2, 1, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 2, 1, _fieldLayout); } /** @@ -514,7 +509,7 @@ library Dynamics2 { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 2, _index * 1, bytes((_slice)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 2, _index * 1, bytes((_slice)), _fieldLayout); } } @@ -527,7 +522,7 @@ library Dynamics2 { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 2, _index * 1, bytes((_slice)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 2, _index * 1, bytes((_slice)), _fieldLayout); } } @@ -536,7 +531,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -545,7 +540,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -558,7 +553,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -570,7 +565,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using the data struct */ @@ -654,7 +649,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -662,6 +657,6 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol b/packages/cli/contracts/src/codegen/tables/Ephemeral.sol index 0742a42eb8..31b8000e6b 100644 --- a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol +++ b/packages/cli/contracts/src/codegen/tables/Ephemeral.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Ephemeral"))); bytes32 constant EphemeralTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0020010020000000000000000000000000000000000000000000000000000000 +); + library Ephemeral { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 32; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -60,19 +61,12 @@ library Ephemeral { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Emit the ephemeral event using individual values */ @@ -85,7 +79,7 @@ library Ephemeral { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Emit the ephemeral event using individual values (using the specified store) */ @@ -98,7 +92,7 @@ library Ephemeral { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _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 29ef27a1d8..d331c6eda3 100644 --- a/packages/cli/contracts/src/codegen/tables/Singleton.sol +++ b/packages/cli/contracts/src/codegen/tables/Singleton.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Singleton"))); bytes32 constant SingletonTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0020010320000000000000000000000000000000000000000000000000000000 +); + library Singleton { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 32; - - return FieldLayoutLib.encode(_fieldLayout, 3); + return _fieldLayout; } /** Get the table's key schema */ @@ -64,26 +65,19 @@ library Singleton { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get v1 */ function getV1() internal view returns (int256 v1) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (int256(uint256(Bytes.slice32(_blob, 0)))); } @@ -91,7 +85,7 @@ library Singleton { function getV1(IStore _store) internal view returns (int256 v1) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (int256(uint256(Bytes.slice32(_blob, 0)))); } @@ -99,21 +93,21 @@ library Singleton { function setV1(int256 v1) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), _fieldLayout); } /** Set v1 (using the specified store) */ function setV1(IStore _store, int256 v1) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), _fieldLayout); } /** Get v2 */ function getV2() internal view returns (uint32[2] memory v2) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -121,7 +115,7 @@ library Singleton { function getV2(IStore _store) internal view returns (uint32[2] memory v2) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -129,21 +123,21 @@ library Singleton { function setV2(uint32[2] memory v2) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_uint32_2(v2)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_uint32_2(v2)), _fieldLayout); } /** Set v2 (using the specified store) */ function setV2(IStore _store, uint32[2] memory v2) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_uint32_2(v2)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_uint32_2(v2)), _fieldLayout); } /** Get the length of v2 */ function lengthV2() internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 1, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); unchecked { return _byteLength / 4; } @@ -153,7 +147,7 @@ library Singleton { function lengthV2(IStore _store) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 1, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); unchecked { return _byteLength / 4; } @@ -171,7 +165,7 @@ library Singleton { _tableId, _keyTuple, 1, - getFieldLayout(), + _fieldLayout, _index * 4, (_index + 1) * 4 ); @@ -187,7 +181,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 1, getFieldLayout(), _index * 4, (_index + 1) * 4); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 1, _fieldLayout, _index * 4, (_index + 1) * 4); return (uint32(Bytes.slice4(_blob, 0))); } } @@ -196,28 +190,28 @@ library Singleton { function pushV2(uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to v2 (using the specified store) */ function pushV2(IStore _store, uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from v2 */ function popV2() internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.popFromField(_tableId, _keyTuple, 1, 4, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 1, 4, _fieldLayout); } /** Pop an element from v2 (using the specified store) */ function popV2(IStore _store) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.popFromField(_tableId, _keyTuple, 1, 4, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 1, 4, _fieldLayout); } /** @@ -228,7 +222,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 1, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 1, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -240,7 +234,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - _store.updateInField(_tableId, _keyTuple, 1, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 1, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -248,7 +242,7 @@ library Singleton { function getV3() internal view returns (uint32[2] memory v3) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -256,7 +250,7 @@ library Singleton { function getV3(IStore _store) internal view returns (uint32[2] memory v3) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -264,21 +258,21 @@ library Singleton { function setV3(uint32[2] memory v3) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 2, EncodeArray.encode(fromStaticArray_uint32_2(v3)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 2, EncodeArray.encode(fromStaticArray_uint32_2(v3)), _fieldLayout); } /** Set v3 (using the specified store) */ function setV3(IStore _store, uint32[2] memory v3) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 2, EncodeArray.encode(fromStaticArray_uint32_2(v3)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 2, EncodeArray.encode(fromStaticArray_uint32_2(v3)), _fieldLayout); } /** Get the length of v3 */ function lengthV3() internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 2, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); unchecked { return _byteLength / 4; } @@ -288,7 +282,7 @@ library Singleton { function lengthV3(IStore _store) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 2, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); unchecked { return _byteLength / 4; } @@ -306,7 +300,7 @@ library Singleton { _tableId, _keyTuple, 2, - getFieldLayout(), + _fieldLayout, _index * 4, (_index + 1) * 4 ); @@ -322,7 +316,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, getFieldLayout(), _index * 4, (_index + 1) * 4); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 4, (_index + 1) * 4); return (uint32(Bytes.slice4(_blob, 0))); } } @@ -331,28 +325,28 @@ library Singleton { function pushV3(uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to v3 (using the specified store) */ function pushV3(IStore _store, uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from v3 */ function popV3() internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.popFromField(_tableId, _keyTuple, 2, 4, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 2, 4, _fieldLayout); } /** Pop an element from v3 (using the specified store) */ function popV3(IStore _store) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.popFromField(_tableId, _keyTuple, 2, 4, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 2, 4, _fieldLayout); } /** @@ -363,7 +357,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 2, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 2, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -375,7 +369,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - _store.updateInField(_tableId, _keyTuple, 2, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 2, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -383,7 +377,7 @@ library Singleton { function getV4() internal view returns (uint32[1] memory v4) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); return toStaticArray_uint32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -391,7 +385,7 @@ library Singleton { function getV4(IStore _store) internal view returns (uint32[1] memory v4) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); return toStaticArray_uint32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -399,21 +393,21 @@ library Singleton { function setV4(uint32[1] memory v4) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 3, EncodeArray.encode(fromStaticArray_uint32_1(v4)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 3, EncodeArray.encode(fromStaticArray_uint32_1(v4)), _fieldLayout); } /** Set v4 (using the specified store) */ function setV4(IStore _store, uint32[1] memory v4) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 3, EncodeArray.encode(fromStaticArray_uint32_1(v4)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 3, EncodeArray.encode(fromStaticArray_uint32_1(v4)), _fieldLayout); } /** Get the length of v4 */ function lengthV4() internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 3, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); unchecked { return _byteLength / 4; } @@ -423,7 +417,7 @@ library Singleton { function lengthV4(IStore _store) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 3, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); unchecked { return _byteLength / 4; } @@ -441,7 +435,7 @@ library Singleton { _tableId, _keyTuple, 3, - getFieldLayout(), + _fieldLayout, _index * 4, (_index + 1) * 4 ); @@ -457,7 +451,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, getFieldLayout(), _index * 4, (_index + 1) * 4); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 4, (_index + 1) * 4); return (uint32(Bytes.slice4(_blob, 0))); } } @@ -466,28 +460,28 @@ library Singleton { function pushV4(uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to v4 (using the specified store) */ function pushV4(IStore _store, uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from v4 */ function popV4() internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.popFromField(_tableId, _keyTuple, 3, 4, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 3, 4, _fieldLayout); } /** Pop an element from v4 (using the specified store) */ function popV4(IStore _store) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.popFromField(_tableId, _keyTuple, 3, 4, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 3, 4, _fieldLayout); } /** @@ -498,7 +492,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 3, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 3, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -510,7 +504,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); unchecked { - _store.updateInField(_tableId, _keyTuple, 3, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 3, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -518,7 +512,7 @@ library Singleton { function get() internal view returns (int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -528,7 +522,7 @@ library Singleton { ) internal view returns (int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -541,7 +535,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -553,7 +547,7 @@ library Singleton { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** @@ -649,14 +643,14 @@ library Singleton { function deleteRecord() internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.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, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/cli/contracts/src/codegen/tables/Statics.sol b/packages/cli/contracts/src/codegen/tables/Statics.sol index 9d6fcab330..14e42c5370 100644 --- a/packages/cli/contracts/src/codegen/tables/Statics.sol +++ b/packages/cli/contracts/src/codegen/tables/Statics.sol @@ -24,6 +24,10 @@ import { Enum2, Enum1 } from "./../Types.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Statics"))); bytes32 constant StaticsTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x004a060020041014010100000000000000000000000000000000000000000000 +); + struct StaticsData { uint256 v1; int32 v2; @@ -36,15 +40,7 @@ struct StaticsData { library Statics { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](6); - _fieldLayout[0] = 32; - _fieldLayout[1] = 4; - _fieldLayout[2] = 16; - _fieldLayout[3] = 20; - _fieldLayout[4] = 1; - _fieldLayout[5] = 1; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -97,19 +93,12 @@ library Statics { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get v1 */ @@ -122,7 +111,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(Bytes.slice32(_blob, 0))); } @@ -144,7 +133,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(Bytes.slice32(_blob, 0))); } @@ -158,7 +147,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), _fieldLayout); } /** Set v1 (using the specified store) */ @@ -171,7 +160,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), _fieldLayout); } /** Get v2 */ @@ -184,7 +173,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -206,7 +195,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -220,7 +209,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((v2)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((v2)), _fieldLayout); } /** Set v2 (using the specified store) */ @@ -233,7 +222,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((v2)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((v2)), _fieldLayout); } /** Get v3 */ @@ -246,7 +235,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); return (Bytes.slice16(_blob, 0)); } @@ -268,7 +257,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); return (Bytes.slice16(_blob, 0)); } @@ -282,7 +271,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.setField(_tableId, _keyTuple, 2, abi.encodePacked((v3)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 2, abi.encodePacked((v3)), _fieldLayout); } /** Set v3 (using the specified store) */ @@ -295,7 +284,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.setField(_tableId, _keyTuple, 2, abi.encodePacked((v3)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 2, abi.encodePacked((v3)), _fieldLayout); } /** Get v4 */ @@ -308,7 +297,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); return (address(Bytes.slice20(_blob, 0))); } @@ -330,7 +319,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); return (address(Bytes.slice20(_blob, 0))); } @@ -344,7 +333,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.setField(_tableId, _keyTuple, 3, abi.encodePacked((v4)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 3, abi.encodePacked((v4)), _fieldLayout); } /** Set v4 (using the specified store) */ @@ -357,7 +346,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.setField(_tableId, _keyTuple, 3, abi.encodePacked((v4)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 3, abi.encodePacked((v4)), _fieldLayout); } /** Get v5 */ @@ -370,7 +359,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -392,7 +381,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -406,7 +395,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.setField(_tableId, _keyTuple, 4, abi.encodePacked((v5)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 4, abi.encodePacked((v5)), _fieldLayout); } /** Set v5 (using the specified store) */ @@ -419,7 +408,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.setField(_tableId, _keyTuple, 4, abi.encodePacked((v5)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 4, abi.encodePacked((v5)), _fieldLayout); } /** Get v6 */ @@ -432,7 +421,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 5, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 5, _fieldLayout); return Enum1(uint8(Bytes.slice1(_blob, 0))); } @@ -454,7 +443,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 5, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 5, _fieldLayout); return Enum1(uint8(Bytes.slice1(_blob, 0))); } @@ -468,7 +457,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.setField(_tableId, _keyTuple, 5, abi.encodePacked(uint8(v6)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 5, abi.encodePacked(uint8(v6)), _fieldLayout); } /** Set v6 (using the specified store) */ @@ -481,7 +470,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.setField(_tableId, _keyTuple, 5, abi.encodePacked(uint8(v6)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 5, abi.encodePacked(uint8(v6)), _fieldLayout); } /** Get the full data */ @@ -501,7 +490,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -523,7 +512,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -555,7 +544,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -587,7 +576,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using the data struct */ @@ -683,7 +672,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -696,7 +685,7 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 68427b3528..536bc29c03 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -339,7 +339,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register KeyEncoding table", - "gasUsed": 697932 + "gasUsed": 691073 }, { "file": "test/Mixed.t.sol", @@ -351,19 +351,19 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Mixed table", - "gasUsed": 560113 + "gasUsed": 552911 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 108795 + "gasUsed": 105912 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "get record from Mixed", - "gasUsed": 9639 + "gasUsed": 7821 }, { "file": "test/PackedCounter.t.sol", @@ -549,13 +549,13 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (cold, 1 slot)", - "gasUsed": 8425 + "gasUsed": 8424 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 1 slot)", - "gasUsed": 2493 + "gasUsed": 2492 }, { "file": "test/StoreCoreDynamic.t.sol", @@ -567,13 +567,13 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 2 slots)", - "gasUsed": 4725 + "gasUsed": 4724 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetSecondFieldLength", "name": "get field length (cold, 1 slot)", - "gasUsed": 7966 + "gasUsed": 7965 }, { "file": "test/StoreCoreDynamic.t.sol", @@ -597,25 +597,25 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 23281 + "gasUsed": 22215 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 17317 + "gasUsed": 16250 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 25478 + "gasUsed": 24412 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 17514 + "gasUsed": 16447 }, { "file": "test/StoreCoreGas.t.sol", @@ -651,115 +651,115 @@ "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 9470 + "gasUsed": 8403 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "Check for existence of table (existent)", - "gasUsed": 4465 + "gasUsed": 2303 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "check for existence of table (non-existent)", - "gasUsed": 6468 + "gasUsed": 4305 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 62552 + "gasUsed": 60434 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 76175 + "gasUsed": 74048 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 25942 + "gasUsed": 23815 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 21493 + "gasUsed": 19366 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 62552 + "gasUsed": 60434 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 169944 + "gasUsed": 167817 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 29579 + "gasUsed": 27452 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 22878 + "gasUsed": 20750 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 15223 + "gasUsed": 14154 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 37997 + "gasUsed": 36926 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 620426 + "gasUsed": 615037 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get field layout (warm)", - "gasUsed": 4479 + "gasUsed": 2317 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get value schema (warm)", - "gasUsed": 5033 + "gasUsed": 2870 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get key schema (warm)", - "gasUsed": 9281 + "gasUsed": 4952 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 104895 + "gasUsed": 103828 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "get complex record with dynamic data (4 slots)", - "gasUsed": 5105 + "gasUsed": 5104 }, { "file": "test/StoreCoreGas.t.sol", @@ -777,7 +777,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 0", - "gasUsed": 23082 + "gasUsed": 23081 }, { "file": "test/StoreCoreGas.t.sol", @@ -795,19 +795,19 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 34114 + "gasUsed": 33047 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (1 slot)", - "gasUsed": 1482 + "gasUsed": 1483 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 32761 + "gasUsed": 31694 }, { "file": "test/StoreCoreGas.t.sol", @@ -819,7 +819,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 55894 + "gasUsed": 54826 }, { "file": "test/StoreCoreGas.t.sol", @@ -831,31 +831,31 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 34134 + "gasUsed": 33064 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, second dynamic field)", - "gasUsed": 2635 + "gasUsed": 2633 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 34695 + "gasUsed": 33629 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "get static record (1 slot)", - "gasUsed": 1734 + "gasUsed": 1733 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 57199 + "gasUsed": 56133 }, { "file": "test/StoreCoreGas.t.sol", @@ -867,13 +867,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 16261 + "gasUsed": 15192 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 17082 + "gasUsed": 16012 }, { "file": "test/StoreHook.t.sol", @@ -921,121 +921,121 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 60015 + "gasUsed": 57881 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: get field (warm)", - "gasUsed": 5160 + "gasUsed": 4092 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 39345 + "gasUsed": 37215 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 61997 + "gasUsed": 59867 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 61997 + "gasUsed": 59866 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: get field (warm)", - "gasUsed": 5136 + "gasUsed": 4071 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 19410 + "gasUsed": 17284 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 15844 + "gasUsed": 13710 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 17479 + "gasUsed": 15349 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 38603 + "gasUsed": 36470 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 10994 + "gasUsed": 8856 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 34250 + "gasUsed": 32110 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 84688 + "gasUsed": 82558 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 84600 + "gasUsed": 82469 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 19792 + "gasUsed": 17662 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGet", "name": "StoreHooks: get field (cold)", - "gasUsed": 11129 + "gasUsed": 10064 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGetItem", "name": "StoreHooks: get 1 element (cold)", - "gasUsed": 7644 + "gasUsed": 6582 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testLength", "name": "StoreHooks: get length (cold)", - "gasUsed": 7127 + "gasUsed": 6062 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 26291 + "gasUsed": 24160 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 28565 + "gasUsed": 26441 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -1089,18 +1089,18 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 421554 + "gasUsed": 414353 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 37413 + "gasUsed": 34533 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "get Vector2 record", - "gasUsed": 4472 + "gasUsed": 2656 } ] diff --git a/packages/store/src/codegen/tables/Callbacks.sol b/packages/store/src/codegen/tables/Callbacks.sol index 5a370f8a20..8d9b02a251 100644 --- a/packages/store/src/codegen/tables/Callbacks.sol +++ b/packages/store/src/codegen/tables/Callbacks.sol @@ -21,12 +21,14 @@ import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("Callbacks"))); bytes32 constant CallbacksTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000100000000000000000000000000000000000000000000000000000000 +); + library Callbacks { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 1); + return _fieldLayout; } /** Get the table's key schema */ @@ -59,19 +61,12 @@ library Callbacks { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ @@ -79,7 +74,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes24()); } @@ -88,7 +83,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes24()); } @@ -97,7 +92,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value (using the specified store) */ @@ -105,7 +100,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Get the length of value */ @@ -113,7 +108,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 24; } @@ -124,7 +119,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 24; } @@ -143,7 +138,7 @@ library Callbacks { _tableId, _keyTuple, 0, - getFieldLayout(), + _fieldLayout, _index * 24, (_index + 1) * 24 ); @@ -160,14 +155,7 @@ library Callbacks { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 0, - getFieldLayout(), - _index * 24, - (_index + 1) * 24 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 24, (_index + 1) * 24); return (Bytes.slice24(_blob, 0)); } } @@ -177,7 +165,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value (using the specified store) */ @@ -185,7 +173,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from value */ @@ -193,7 +181,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 0, 24, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 0, 24, _fieldLayout); } /** Pop an element from value (using the specified store) */ @@ -201,7 +189,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 0, 24, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 0, 24, _fieldLayout); } /** @@ -213,7 +201,7 @@ library Callbacks { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 24, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 24, abi.encodePacked((_element)), _fieldLayout); } } @@ -226,7 +214,7 @@ library Callbacks { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 0, _index * 24, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 0, _index * 24, abi.encodePacked((_element)), _fieldLayout); } } @@ -265,7 +253,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -273,6 +261,6 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/store/src/codegen/tables/Hooks.sol b/packages/store/src/codegen/tables/Hooks.sol index 4d12e0babb..3332c321e4 100644 --- a/packages/store/src/codegen/tables/Hooks.sol +++ b/packages/store/src/codegen/tables/Hooks.sol @@ -18,12 +18,14 @@ import { FieldLayout, FieldLayoutLib } from "../../FieldLayout.sol"; import { Schema, SchemaLib } from "../../Schema.sol"; import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000100000000000000000000000000000000000000000000000000000000 +); + library Hooks { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 1); + return _fieldLayout; } /** Get the table's key schema */ @@ -56,19 +58,12 @@ library Hooks { /** Register the table with its config */ function register(bytes32 _tableId) internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store, bytes32 _tableId) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ @@ -76,7 +71,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -85,7 +80,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -94,7 +89,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value (using the specified store) */ @@ -102,7 +97,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Get the length of value */ @@ -110,7 +105,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 21; } @@ -121,7 +116,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 21; } @@ -140,7 +135,7 @@ library Hooks { _tableId, _keyTuple, 0, - getFieldLayout(), + _fieldLayout, _index * 21, (_index + 1) * 21 ); @@ -157,14 +152,7 @@ library Hooks { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 0, - getFieldLayout(), - _index * 21, - (_index + 1) * 21 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 21, (_index + 1) * 21); return (Bytes.slice21(_blob, 0)); } } @@ -174,7 +162,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value (using the specified store) */ @@ -182,7 +170,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from value */ @@ -190,7 +178,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** Pop an element from value (using the specified store) */ @@ -198,7 +186,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 0, 21, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** @@ -210,7 +198,7 @@ library Hooks { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); } } @@ -223,7 +211,7 @@ library Hooks { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); } } @@ -262,7 +250,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -270,6 +258,6 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/store/src/codegen/tables/KeyEncoding.sol b/packages/store/src/codegen/tables/KeyEncoding.sol index f8db386345..b23620d632 100644 --- a/packages/store/src/codegen/tables/KeyEncoding.sol +++ b/packages/store/src/codegen/tables/KeyEncoding.sol @@ -24,13 +24,14 @@ import { ExampleEnum } from "./../Types.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("KeyEncoding"))); bytes32 constant KeyEncodingTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0001010001000000000000000000000000000000000000000000000000000000 +); + library KeyEncoding { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 1; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -73,19 +74,12 @@ library KeyEncoding { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ @@ -105,7 +99,7 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -127,7 +121,7 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -141,7 +135,7 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ @@ -163,7 +157,7 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -211,7 +205,7 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -224,7 +218,7 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/store/src/codegen/tables/Mixed.sol b/packages/store/src/codegen/tables/Mixed.sol index 9be293952b..d6060d0c95 100644 --- a/packages/store/src/codegen/tables/Mixed.sol +++ b/packages/store/src/codegen/tables/Mixed.sol @@ -21,6 +21,10 @@ import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("Mixed"))); bytes32 constant MixedTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0014020204100000000000000000000000000000000000000000000000000000 +); + struct MixedData { uint32 u32; uint128 u128; @@ -31,11 +35,7 @@ struct MixedData { library Mixed { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](2); - _fieldLayout[0] = 4; - _fieldLayout[1] = 16; - - return FieldLayoutLib.encode(_fieldLayout, 2); + return _fieldLayout; } /** Get the table's key schema */ @@ -74,19 +74,12 @@ library Mixed { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get u32 */ @@ -94,7 +87,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -103,7 +96,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -112,7 +105,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((u32)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((u32)), _fieldLayout); } /** Set u32 (using the specified store) */ @@ -120,7 +113,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((u32)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((u32)), _fieldLayout); } /** Get u128 */ @@ -128,7 +121,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (uint128(Bytes.slice16(_blob, 0))); } @@ -137,7 +130,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (uint128(Bytes.slice16(_blob, 0))); } @@ -146,7 +139,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((u128)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((u128)), _fieldLayout); } /** Set u128 (using the specified store) */ @@ -154,7 +147,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((u128)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((u128)), _fieldLayout); } /** Get a32 */ @@ -162,7 +155,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -171,7 +164,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -180,7 +173,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 2, EncodeArray.encode((a32)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 2, EncodeArray.encode((a32)), _fieldLayout); } /** Set a32 (using the specified store) */ @@ -188,7 +181,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 2, EncodeArray.encode((a32)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 2, EncodeArray.encode((a32)), _fieldLayout); } /** Get the length of a32 */ @@ -196,7 +189,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 2, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); unchecked { return _byteLength / 4; } @@ -207,7 +200,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 2, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); unchecked { return _byteLength / 4; } @@ -226,7 +219,7 @@ library Mixed { _tableId, _keyTuple, 2, - getFieldLayout(), + _fieldLayout, _index * 4, (_index + 1) * 4 ); @@ -243,7 +236,7 @@ library Mixed { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, getFieldLayout(), _index * 4, (_index + 1) * 4); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 4, (_index + 1) * 4); return (uint32(Bytes.slice4(_blob, 0))); } } @@ -253,7 +246,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to a32 (using the specified store) */ @@ -261,7 +254,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from a32 */ @@ -269,7 +262,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 2, 4, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 2, 4, _fieldLayout); } /** Pop an element from a32 (using the specified store) */ @@ -277,7 +270,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 2, 4, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 2, 4, _fieldLayout); } /** @@ -289,7 +282,7 @@ library Mixed { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 2, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 2, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -302,7 +295,7 @@ library Mixed { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 2, _index * 4, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 2, _index * 4, abi.encodePacked((_element)), _fieldLayout); } } @@ -311,7 +304,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); return (string(_blob)); } @@ -320,7 +313,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); return (string(_blob)); } @@ -329,7 +322,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 3, bytes((s)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 3, bytes((s)), _fieldLayout); } /** Set s (using the specified store) */ @@ -337,7 +330,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 3, bytes((s)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 3, bytes((s)), _fieldLayout); } /** Get the length of s */ @@ -345,7 +338,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 3, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); unchecked { return _byteLength / 1; } @@ -356,7 +349,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 3, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); unchecked { return _byteLength / 1; } @@ -375,7 +368,7 @@ library Mixed { _tableId, _keyTuple, 3, - getFieldLayout(), + _fieldLayout, _index * 1, (_index + 1) * 1 ); @@ -392,7 +385,7 @@ library Mixed { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, getFieldLayout(), _index * 1, (_index + 1) * 1); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 1, (_index + 1) * 1); return (string(_blob)); } } @@ -402,7 +395,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), _fieldLayout); } /** Push a slice to s (using the specified store) */ @@ -410,7 +403,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), _fieldLayout); } /** Pop a slice from s */ @@ -418,7 +411,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 3, 1, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 3, 1, _fieldLayout); } /** Pop a slice from s (using the specified store) */ @@ -426,7 +419,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 3, 1, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 3, 1, _fieldLayout); } /** @@ -438,7 +431,7 @@ library Mixed { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 3, _index * 1, bytes((_slice)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 3, _index * 1, bytes((_slice)), _fieldLayout); } } @@ -451,7 +444,7 @@ library Mixed { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 3, _index * 1, bytes((_slice)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 3, _index * 1, bytes((_slice)), _fieldLayout); } } @@ -460,7 +453,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -469,7 +462,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -483,7 +476,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -496,7 +489,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using the data struct */ @@ -580,7 +573,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -588,6 +581,6 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/store/src/codegen/tables/StoreHooks.sol b/packages/store/src/codegen/tables/StoreHooks.sol index fe82a2a292..e997c1a4f9 100644 --- a/packages/store/src/codegen/tables/StoreHooks.sol +++ b/packages/store/src/codegen/tables/StoreHooks.sol @@ -21,12 +21,14 @@ import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("StoreHooks"))); bytes32 constant StoreHooksTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000100000000000000000000000000000000000000000000000000000000 +); + library StoreHooks { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 1); + return _fieldLayout; } /** Get the table's key schema */ @@ -59,19 +61,12 @@ library StoreHooks { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ @@ -79,7 +74,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -88,7 +83,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -97,7 +92,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value (using the specified store) */ @@ -105,7 +100,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Get the length of value */ @@ -113,7 +108,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 21; } @@ -124,7 +119,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 21; } @@ -143,7 +138,7 @@ library StoreHooks { _tableId, _keyTuple, 0, - getFieldLayout(), + _fieldLayout, _index * 21, (_index + 1) * 21 ); @@ -160,14 +155,7 @@ library StoreHooks { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 0, - getFieldLayout(), - _index * 21, - (_index + 1) * 21 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 21, (_index + 1) * 21); return (Bytes.slice21(_blob, 0)); } } @@ -177,7 +165,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value (using the specified store) */ @@ -185,7 +173,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from value */ @@ -193,7 +181,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** Pop an element from value (using the specified store) */ @@ -201,7 +189,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 0, 21, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** @@ -213,7 +201,7 @@ library StoreHooks { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); } } @@ -226,7 +214,7 @@ library StoreHooks { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); } } @@ -265,7 +253,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -273,6 +261,6 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/store/src/codegen/tables/Tables.sol b/packages/store/src/codegen/tables/Tables.sol index 520bbd4497..b3e553b585 100644 --- a/packages/store/src/codegen/tables/Tables.sol +++ b/packages/store/src/codegen/tables/Tables.sol @@ -21,6 +21,10 @@ import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("Tables"))); bytes32 constant TablesTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0060030220202000000000000000000000000000000000000000000000000000 +); + struct TablesData { bytes32 fieldLayout; bytes32 keySchema; @@ -32,12 +36,7 @@ struct TablesData { library Tables { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](3); - _fieldLayout[0] = 32; - _fieldLayout[1] = 32; - _fieldLayout[2] = 32; - - return FieldLayoutLib.encode(_fieldLayout, 2); + return _fieldLayout; } /** Get the table's key schema */ @@ -78,19 +77,12 @@ library Tables { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get fieldLayout */ @@ -98,7 +90,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -107,7 +99,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -116,7 +108,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((fieldLayout)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((fieldLayout)), _fieldLayout); } /** Set fieldLayout (using the specified store) */ @@ -124,7 +116,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((fieldLayout)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((fieldLayout)), _fieldLayout); } /** Get keySchema */ @@ -132,7 +124,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -141,7 +133,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -150,7 +142,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((keySchema)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((keySchema)), _fieldLayout); } /** Set keySchema (using the specified store) */ @@ -158,7 +150,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((keySchema)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((keySchema)), _fieldLayout); } /** Get valueSchema */ @@ -166,7 +158,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -175,7 +167,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -184,7 +176,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.setField(_tableId, _keyTuple, 2, abi.encodePacked((valueSchema)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 2, abi.encodePacked((valueSchema)), _fieldLayout); } /** Set valueSchema (using the specified store) */ @@ -192,7 +184,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.setField(_tableId, _keyTuple, 2, abi.encodePacked((valueSchema)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 2, abi.encodePacked((valueSchema)), _fieldLayout); } /** Get abiEncodedKeyNames */ @@ -200,7 +192,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); return (bytes(_blob)); } @@ -212,7 +204,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); return (bytes(_blob)); } @@ -221,7 +213,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.setField(_tableId, _keyTuple, 3, bytes((abiEncodedKeyNames)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 3, bytes((abiEncodedKeyNames)), _fieldLayout); } /** Set abiEncodedKeyNames (using the specified store) */ @@ -229,7 +221,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.setField(_tableId, _keyTuple, 3, bytes((abiEncodedKeyNames)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 3, bytes((abiEncodedKeyNames)), _fieldLayout); } /** Get the length of abiEncodedKeyNames */ @@ -237,7 +229,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 3, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); unchecked { return _byteLength / 1; } @@ -248,7 +240,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 3, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); unchecked { return _byteLength / 1; } @@ -267,7 +259,7 @@ library Tables { _tableId, _keyTuple, 3, - getFieldLayout(), + _fieldLayout, _index * 1, (_index + 1) * 1 ); @@ -288,7 +280,7 @@ library Tables { _keyTuple[0] = tableId; unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, getFieldLayout(), _index * 1, (_index + 1) * 1); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 1, (_index + 1) * 1); return (bytes(_blob)); } } @@ -298,7 +290,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), _fieldLayout); } /** Push a slice to abiEncodedKeyNames (using the specified store) */ @@ -306,7 +298,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), _fieldLayout); } /** Pop a slice from abiEncodedKeyNames */ @@ -314,7 +306,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.popFromField(_tableId, _keyTuple, 3, 1, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 3, 1, _fieldLayout); } /** Pop a slice from abiEncodedKeyNames (using the specified store) */ @@ -322,7 +314,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.popFromField(_tableId, _keyTuple, 3, 1, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 3, 1, _fieldLayout); } /** @@ -334,7 +326,7 @@ library Tables { _keyTuple[0] = tableId; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 3, _index * 1, bytes((_slice)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 3, _index * 1, bytes((_slice)), _fieldLayout); } } @@ -347,7 +339,7 @@ library Tables { _keyTuple[0] = tableId; unchecked { - _store.updateInField(_tableId, _keyTuple, 3, _index * 1, bytes((_slice)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 3, _index * 1, bytes((_slice)), _fieldLayout); } } @@ -356,7 +348,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, _fieldLayout); return (bytes(_blob)); } @@ -368,7 +360,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, _fieldLayout); return (bytes(_blob)); } @@ -377,7 +369,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.setField(_tableId, _keyTuple, 4, bytes((abiEncodedFieldNames)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 4, bytes((abiEncodedFieldNames)), _fieldLayout); } /** Set abiEncodedFieldNames (using the specified store) */ @@ -385,7 +377,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.setField(_tableId, _keyTuple, 4, bytes((abiEncodedFieldNames)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 4, bytes((abiEncodedFieldNames)), _fieldLayout); } /** Get the length of abiEncodedFieldNames */ @@ -393,7 +385,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 4, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 4, _fieldLayout); unchecked { return _byteLength / 1; } @@ -404,7 +396,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 4, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 4, _fieldLayout); unchecked { return _byteLength / 1; } @@ -423,7 +415,7 @@ library Tables { _tableId, _keyTuple, 4, - getFieldLayout(), + _fieldLayout, _index * 1, (_index + 1) * 1 ); @@ -444,7 +436,7 @@ library Tables { _keyTuple[0] = tableId; unchecked { - bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 4, getFieldLayout(), _index * 1, (_index + 1) * 1); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 4, _fieldLayout, _index * 1, (_index + 1) * 1); return (bytes(_blob)); } } @@ -454,7 +446,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.pushToField(_tableId, _keyTuple, 4, bytes((_slice)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 4, bytes((_slice)), _fieldLayout); } /** Push a slice to abiEncodedFieldNames (using the specified store) */ @@ -462,7 +454,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.pushToField(_tableId, _keyTuple, 4, bytes((_slice)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 4, bytes((_slice)), _fieldLayout); } /** Pop a slice from abiEncodedFieldNames */ @@ -470,7 +462,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.popFromField(_tableId, _keyTuple, 4, 1, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 4, 1, _fieldLayout); } /** Pop a slice from abiEncodedFieldNames (using the specified store) */ @@ -478,7 +470,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.popFromField(_tableId, _keyTuple, 4, 1, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 4, 1, _fieldLayout); } /** @@ -490,7 +482,7 @@ library Tables { _keyTuple[0] = tableId; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 4, _index * 1, bytes((_slice)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 4, _index * 1, bytes((_slice)), _fieldLayout); } } @@ -503,7 +495,7 @@ library Tables { _keyTuple[0] = tableId; unchecked { - _store.updateInField(_tableId, _keyTuple, 4, _index * 1, bytes((_slice)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 4, _index * 1, bytes((_slice)), _fieldLayout); } } @@ -512,7 +504,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -521,7 +513,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -542,7 +534,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -563,7 +555,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using the data struct */ @@ -680,7 +672,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -688,6 +680,6 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/store/src/codegen/tables/Vector2.sol b/packages/store/src/codegen/tables/Vector2.sol index f71080845a..9c1f7cbea1 100644 --- a/packages/store/src/codegen/tables/Vector2.sol +++ b/packages/store/src/codegen/tables/Vector2.sol @@ -21,6 +21,10 @@ import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("Vector2"))); bytes32 constant Vector2TableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0008020004040000000000000000000000000000000000000000000000000000 +); + struct Vector2Data { uint32 x; uint32 y; @@ -29,11 +33,7 @@ struct Vector2Data { library Vector2 { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](2); - _fieldLayout[0] = 4; - _fieldLayout[1] = 4; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -68,19 +68,12 @@ library Vector2 { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get x */ @@ -88,7 +81,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -97,7 +90,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -106,7 +99,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } /** Set x (using the specified store) */ @@ -114,7 +107,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } /** Get y */ @@ -122,7 +115,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -131,7 +124,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -140,7 +133,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } /** Set y (using the specified store) */ @@ -148,7 +141,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } /** Get the full data */ @@ -156,7 +149,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -165,7 +158,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -179,7 +172,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -192,7 +185,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using the data struct */ @@ -240,7 +233,7 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -248,6 +241,6 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/store/test/FieldLayout.t.sol b/packages/store/test/FieldLayout.t.sol index c8555fb18d..c8f302e1fa 100644 --- a/packages/store/test/FieldLayout.t.sol +++ b/packages/store/test/FieldLayout.t.sol @@ -204,4 +204,35 @@ contract FieldLayoutTest is Test, GasReporter { assertFalse(empty); } + + function testHex() public { + uint256[] memory _fieldLayout = new uint256[](24); + _fieldLayout[0] = 1; + _fieldLayout[1] = 2; + _fieldLayout[2] = 3; + _fieldLayout[3] = 4; + _fieldLayout[4] = 5; + _fieldLayout[5] = 6; + _fieldLayout[6] = 7; + _fieldLayout[7] = 8; + _fieldLayout[8] = 9; + _fieldLayout[9] = 10; + _fieldLayout[10] = 11; + _fieldLayout[11] = 12; + _fieldLayout[12] = 13; + _fieldLayout[13] = 14; + _fieldLayout[14] = 15; + _fieldLayout[15] = 16; + _fieldLayout[16] = 17; + _fieldLayout[17] = 18; + _fieldLayout[18] = 19; + _fieldLayout[19] = 20; + _fieldLayout[20] = 21; + _fieldLayout[21] = 22; + _fieldLayout[22] = 23; + _fieldLayout[23] = 32; + + FieldLayout encodedFieldLayout = FieldLayoutLib.encode(_fieldLayout, 4); + assertEq(encodedFieldLayout.unwrap(), hex"013418040102030405060708090a0b0c0d0e0f10111213141516172000000000"); + } } diff --git a/packages/store/ts/codegen/ephemeral.ts b/packages/store/ts/codegen/ephemeral.ts index 96182f65fb..21b850a782 100644 --- a/packages/store/ts/codegen/ephemeral.ts +++ b/packages/store/ts/codegen/ephemeral.ts @@ -20,7 +20,7 @@ export function renderEphemeralMethods(options: RenderTableOptions) { ${_keyTupleDefinition} - ${_store}.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + ${_store}.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } ` ); diff --git a/packages/store/ts/codegen/field.ts b/packages/store/ts/codegen/field.ts index 29f74789f0..5d1c3bdf81 100644 --- a/packages/store/ts/codegen/field.ts +++ b/packages/store/ts/codegen/field.ts @@ -25,7 +25,7 @@ export function renderFieldMethods(options: RenderTableOptions) { _typedKeyArgs, ])}) internal view returns (${_typedFieldName}) { ${_keyTupleDefinition} - bytes memory _blob = ${_store}.getField(_tableId, _keyTuple, ${schemaIndex}, getFieldLayout()); + bytes memory _blob = ${_store}.getField(_tableId, _keyTuple, ${schemaIndex}, _fieldLayout); return ${renderDecodeFieldSingle(field)}; } ` @@ -42,7 +42,7 @@ export function renderFieldMethods(options: RenderTableOptions) { _typedFieldName, ])}) internal { ${_keyTupleDefinition} - ${_store}.setField(_tableId, _keyTuple, ${schemaIndex}, ${renderEncodeFieldSingle(field)}, getFieldLayout()); + ${_store}.setField(_tableId, _keyTuple, ${schemaIndex}, ${renderEncodeFieldSingle(field)}, _fieldLayout); } ` ); @@ -60,7 +60,7 @@ export function renderFieldMethods(options: RenderTableOptions) { _typedKeyArgs, ])}) internal view returns (uint256) { ${_keyTupleDefinition} - uint256 _byteLength = ${_store}.getFieldLength(_tableId, _keyTuple, ${schemaIndex}, getFieldLayout()); + uint256 _byteLength = ${_store}.getFieldLength(_tableId, _keyTuple, ${schemaIndex}, _fieldLayout); unchecked { return _byteLength / ${portionData.elementLength}; } @@ -87,7 +87,7 @@ export function renderFieldMethods(options: RenderTableOptions) { _tableId, _keyTuple, ${schemaIndex}, - getFieldLayout(), + _fieldLayout, _index * ${portionData.elementLength}, (_index + 1) * ${portionData.elementLength} ); @@ -108,7 +108,7 @@ export function renderFieldMethods(options: RenderTableOptions) { `${portionData.typeWithLocation} ${portionData.name}`, ])}) internal { ${_keyTupleDefinition} - ${_store}.pushToField(_tableId, _keyTuple, ${schemaIndex}, ${portionData.encoded}, getFieldLayout()); + ${_store}.pushToField(_tableId, _keyTuple, ${schemaIndex}, ${portionData.encoded}, _fieldLayout); } ` ); @@ -123,7 +123,7 @@ export function renderFieldMethods(options: RenderTableOptions) { _typedKeyArgs, ])}) internal { ${_keyTupleDefinition} - ${_store}.popFromField(_tableId, _keyTuple, ${schemaIndex}, ${portionData.elementLength}, getFieldLayout()); + ${_store}.popFromField(_tableId, _keyTuple, ${schemaIndex}, ${portionData.elementLength}, _fieldLayout); } ` ); @@ -150,7 +150,7 @@ export function renderFieldMethods(options: RenderTableOptions) { ${schemaIndex}, _index * ${portionData.elementLength}, ${portionData.encoded}, - getFieldLayout() + _fieldLayout ); } } diff --git a/packages/store/ts/codegen/record.ts b/packages/store/ts/codegen/record.ts index b13dfd25d7..75277e463e 100644 --- a/packages/store/ts/codegen/record.ts +++ b/packages/store/ts/codegen/record.ts @@ -1,9 +1,9 @@ import { - renderList, + RenderDynamicField, renderArguments, renderCommonData, + renderList, renderWithStore, - RenderDynamicField, } from "@latticexyz/common/codegen"; import { renderDecodeValueType } from "./field"; import { RenderTableOptions } from "./types"; @@ -22,7 +22,7 @@ export function renderRecordMethods(options: RenderTableOptions) { _typedKeyArgs, ])}) internal view returns (${renderDecodedRecord(options)}) { ${_keyTupleDefinition} - bytes memory _blob = ${_store}.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = ${_store}.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } ` @@ -42,7 +42,7 @@ export function renderRecordMethods(options: RenderTableOptions) { ${_keyTupleDefinition} - ${_store}.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + ${_store}.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } ` ); diff --git a/packages/store/ts/codegen/renderFieldLayout.test.ts b/packages/store/ts/codegen/renderFieldLayout.test.ts new file mode 100644 index 0000000000..a2a170ef8d --- /dev/null +++ b/packages/store/ts/codegen/renderFieldLayout.test.ts @@ -0,0 +1,42 @@ +import { describe, expect, it } from "vitest"; +import { renderFieldLayout } from "./renderFieldLayout"; +import { RenderType } from "@latticexyz/common/codegen"; + +describe("renderFieldLayout", () => { + it("should match the FieldLayout.sol encoding", () => { + const fields = [ + { isDynamic: false, staticByteLength: 1 }, + { isDynamic: false, staticByteLength: 2 }, + { isDynamic: false, staticByteLength: 3 }, + { isDynamic: false, staticByteLength: 4 }, + { isDynamic: false, staticByteLength: 5 }, + { isDynamic: false, staticByteLength: 6 }, + { isDynamic: false, staticByteLength: 7 }, + { isDynamic: false, staticByteLength: 8 }, + { isDynamic: false, staticByteLength: 9 }, + { isDynamic: false, staticByteLength: 10 }, + { isDynamic: false, staticByteLength: 11 }, + { isDynamic: false, staticByteLength: 12 }, + { isDynamic: false, staticByteLength: 13 }, + { isDynamic: false, staticByteLength: 14 }, + { isDynamic: false, staticByteLength: 15 }, + { isDynamic: false, staticByteLength: 16 }, + { isDynamic: false, staticByteLength: 17 }, + { isDynamic: false, staticByteLength: 18 }, + { isDynamic: false, staticByteLength: 19 }, + { isDynamic: false, staticByteLength: 20 }, + { isDynamic: false, staticByteLength: 21 }, + { isDynamic: false, staticByteLength: 22 }, + { isDynamic: false, staticByteLength: 23 }, + { isDynamic: false, staticByteLength: 32 }, + { isDynamic: true, staticByteLength: 0 }, + { isDynamic: true, staticByteLength: 0 }, + { isDynamic: true, staticByteLength: 0 }, + { isDynamic: true, staticByteLength: 0 }, + ] as RenderType[]; + + expect(renderFieldLayout(fields)).toEqual( + `FieldLayout constant _fieldLayout = FieldLayout.wrap(0x013418040102030405060708090a0b0c0d0e0f10111213141516172000000000);` + ); + }); +}); diff --git a/packages/store/ts/codegen/renderFieldLayout.ts b/packages/store/ts/codegen/renderFieldLayout.ts new file mode 100644 index 0000000000..cb112a875c --- /dev/null +++ b/packages/store/ts/codegen/renderFieldLayout.ts @@ -0,0 +1,33 @@ +import { RenderType } from "@latticexyz/common/codegen"; +import { BYTE_TO_BITS, LayoutOffsets, MAX_DYNAMIC_FIELDS, MAX_TOTAL_FIELDS, WORD_LAST_INDEX } from "../constants"; + +export function renderFieldLayout(fields: RenderType[]) { + return `FieldLayout constant _fieldLayout = FieldLayout.wrap(${encodeFieldLayout(fields)});`; +} + +// Make sure this logic stays aligned with @latticexyz/store/src/FieldLayout.sol +export function encodeFieldLayout(fields: RenderType[]) { + const staticFields = fields.filter(({ isDynamic }) => !isDynamic); + const numDynamicFields = fields.length - staticFields.length; + + let fieldLayout = 0n; + let totalLength = 0; + const totalFields = fields.length; + + if (totalFields > MAX_TOTAL_FIELDS) throw new Error(`FieldLayout: invalid length ${totalFields}`); + if (numDynamicFields > MAX_DYNAMIC_FIELDS) throw new Error(`FieldLayout: invalid length ${numDynamicFields}`); + + for (let i = 0; i < staticFields.length; i++) { + const { isDynamic, staticByteLength } = fields[i]; + if (isDynamic) throw new Error(`FieldLayout: static type after dynamic type`); + + totalLength += staticByteLength; + fieldLayout |= BigInt(staticByteLength) << BigInt((WORD_LAST_INDEX - 4 - i) * BYTE_TO_BITS); + } + + fieldLayout |= BigInt(totalLength) << BigInt(LayoutOffsets.TOTAL_LENGTH); + fieldLayout |= BigInt(staticFields.length) << BigInt(LayoutOffsets.NUM_STATIC_FIELDS); + fieldLayout |= BigInt(numDynamicFields) << BigInt(LayoutOffsets.NUM_DYNAMIC_FIELDS); + + return `0x${fieldLayout.toString(16).padStart(64, "0")}`; +} diff --git a/packages/store/ts/codegen/renderTable.ts b/packages/store/ts/codegen/renderTable.ts index 72816bf28f..e918822585 100644 --- a/packages/store/ts/codegen/renderTable.ts +++ b/packages/store/ts/codegen/renderTable.ts @@ -2,17 +2,18 @@ import { renderArguments, renderCommonData, renderList, - renderedSolidityHeader, renderRelativeImports, renderTableId, - renderWithStore, renderTypeHelpers, + renderWithStore, + renderedSolidityHeader, RenderDynamicField, RenderStaticField, } from "@latticexyz/common/codegen"; import { renderEphemeralMethods } from "./ephemeral"; import { renderEncodeFieldSingle, renderFieldMethods } from "./field"; import { renderRecordData, renderRecordMethods } from "./record"; +import { renderFieldLayout } from "./renderFieldLayout"; import { RenderTableOptions } from "./types"; export function renderTable(options: RenderTableOptions) { @@ -64,6 +65,8 @@ export function renderTable(options: RenderTableOptions) { ${staticResourceData ? renderTableId(staticResourceData).tableIdDefinition : ""} + ${renderFieldLayout(fields)} + ${ !structName ? "" @@ -77,10 +80,7 @@ export function renderTable(options: RenderTableOptions) { library ${libraryName} { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](${staticFields.length}); - ${renderList(staticFields, ({ staticByteLength }, index) => `_fieldLayout[${index}] = ${staticByteLength};`)} - - return FieldLayoutLib.encode(_fieldLayout, ${dynamicFields.length}); + return _fieldLayout; } /** Get the table's key schema */ @@ -116,7 +116,7 @@ export function renderTable(options: RenderTableOptions) { (_typedStore, _store, _commentSuffix) => ` /** Register the table with its config${_commentSuffix} */ function register(${renderArguments([_typedStore, _typedTableId])}) internal { - ${_store}.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + ${_store}.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } ` )} @@ -156,7 +156,7 @@ export function renderTable(options: RenderTableOptions) { /* Delete all data for given keys${_commentSuffix} */ function deleteRecord(${renderArguments([_typedStore, _typedTableId, _typedKeyArgs])}) internal { ${_keyTupleDefinition} - ${_store}.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + ${_store}.deleteRecord(_tableId, _keyTuple, _fieldLayout); } ` ) diff --git a/packages/store/ts/constants.ts b/packages/store/ts/constants.ts new file mode 100644 index 0000000000..9c93949bf3 --- /dev/null +++ b/packages/store/ts/constants.ts @@ -0,0 +1,23 @@ +/* Shared constants */ +// Make sure these stay aligned with @latticexyz/store/src/constants.sol + +// Total byte length of an EVM word +export const WORD_SIZE = 32; +// Index of the last byte in an EVM word +export const WORD_LAST_INDEX = 31; +// Conversion for bit shifting +export const BYTE_TO_BITS = 8; + +// Schema's capacity +export const MAX_TOTAL_FIELDS = 28; +// FieldLayout's capacity +export const MAX_STATIC_FIELDS = 28; +// PackedCounter's capacity +export const MAX_DYNAMIC_FIELDS = 5; + +// FieldLayout and Schema have the same offsets for metadata +export const LayoutOffsets = { + TOTAL_LENGTH: (WORD_SIZE - 2) * BYTE_TO_BITS, + NUM_STATIC_FIELDS: (WORD_SIZE - 2 - 1) * BYTE_TO_BITS, + NUM_DYNAMIC_FIELDS: (WORD_SIZE - 2 - 1 - 1) * BYTE_TO_BITS, +}; diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 64b6bfac8c..0757bfb9b3 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -3,31 +3,31 @@ "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (cold)", - "gasUsed": 13860 + "gasUsed": 10912 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm, namespace only)", - "gasUsed": 4007 + "gasUsed": 2532 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm)", - "gasUsed": 7892 + "gasUsed": 4940 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (cold)", - "gasUsed": 13903 + "gasUsed": 10954 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (warm)", - "gasUsed": 7909 + "gasUsed": 4959 }, { "file": "test/AccessControl.t.sol", @@ -39,73 +39,73 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1521715 + "gasUsed": 1453384 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1521715 + "gasUsed": 1453384 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 187187 + "gasUsed": 170849 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1521715 + "gasUsed": 1453384 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1521715 + "gasUsed": 1453384 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 30396 + "gasUsed": 26036 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 256692 + "gasUsed": 205921 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1521715 + "gasUsed": 1453384 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 29117 + "gasUsed": 24758 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 134551 + "gasUsed": 106239 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 730803 + "gasUsed": 682161 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "Get list of keys with a given value", - "gasUsed": 7584 + "gasUsed": 6521 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,264 +117,264 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 730803 + "gasUsed": 682161 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 159933 + "gasUsed": 146160 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 730803 + "gasUsed": 682161 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 129535 + "gasUsed": 115759 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 49133 + "gasUsed": 40440 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 730803 + "gasUsed": 682161 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 164678 + "gasUsed": 150906 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 129437 + "gasUsed": 115665 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 141735 + "gasUsed": 112790 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 69540 + "gasUsed": 57749 }, { "file": "test/query.t.sol", "test": "testCombinedHasNotQuery", "name": "CombinedHasNotQuery", - "gasUsed": 184268 + "gasUsed": 140333 }, { "file": "test/query.t.sol", "test": "testCombinedHasQuery", "name": "CombinedHasQuery", - "gasUsed": 122085 + "gasUsed": 90971 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 117986 + "gasUsed": 91191 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueQuery", "name": "CombinedHasValueQuery", - "gasUsed": 19461 + "gasUsed": 17316 }, { "file": "test/query.t.sol", "test": "testHasQuery", "name": "HasQuery", - "gasUsed": 27973 + "gasUsed": 20461 }, { "file": "test/query.t.sol", "test": "testHasQuery1000Keys", "name": "HasQuery with 1000 keys", - "gasUsed": 7118904 + "gasUsed": 5985870 }, { "file": "test/query.t.sol", "test": "testHasQuery100Keys", "name": "HasQuery with 100 keys", - "gasUsed": 672769 + "gasUsed": 560764 }, { "file": "test/query.t.sol", "test": "testHasValueQuery", "name": "HasValueQuery", - "gasUsed": 9401 + "gasUsed": 8329 }, { "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 63136 + "gasUsed": 51345 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 133856 + "gasUsed": 120433 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 49405 + "gasUsed": 39201 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 128205 + "gasUsed": 114784 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 38496 + "gasUsed": 30837 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 790963 + "gasUsed": 721941 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 67727 + "gasUsed": 57530 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 774507 + "gasUsed": 708712 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 67727 + "gasUsed": 57530 }, { "file": "test/World.t.sol", "test": "testCall", "name": "call a system via the World", - "gasUsed": 19564 + "gasUsed": 15199 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 59312 + "gasUsed": 52070 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "call a system via an unlimited delegation", - "gasUsed": 19972 + "gasUsed": 15608 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 13885 + "gasUsed": 11340 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 93919 + "gasUsed": 91372 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 75955 + "gasUsed": 65058 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 69204 + "gasUsed": 58308 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 96549 + "gasUsed": 85651 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 147155 + "gasUsed": 133367 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 91122 + "gasUsed": 80226 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 686517 + "gasUsed": 660018 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 42174 + "gasUsed": 39628 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 41619 + "gasUsed": 37622 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 32933 + "gasUsed": 30387 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 20046 + "gasUsed": 17500 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 36456 + "gasUsed": 33910 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 23661 + "gasUsed": 21115 } ] diff --git a/packages/world/src/modules/core/tables/Balances.sol b/packages/world/src/modules/core/tables/Balances.sol index 417d4b2751..ac0cada199 100644 --- a/packages/world/src/modules/core/tables/Balances.sol +++ b/packages/world/src/modules/core/tables/Balances.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Balances"))); bytes32 constant BalancesTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0020010020000000000000000000000000000000000000000000000000000000 +); + library Balances { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 32; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -60,19 +61,12 @@ library Balances { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get balance */ @@ -80,7 +74,7 @@ library Balances { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(Bytes.slice32(_blob, 0))); } @@ -89,7 +83,7 @@ library Balances { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(Bytes.slice32(_blob, 0))); } @@ -98,7 +92,7 @@ library Balances { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); } /** Set balance (using the specified store) */ @@ -106,7 +100,7 @@ library Balances { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -137,7 +131,7 @@ library Balances { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -145,6 +139,6 @@ library Balances { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _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 152672637c..f679ed4e18 100644 --- a/packages/world/src/modules/core/tables/FunctionSelectors.sol +++ b/packages/world/src/modules/core/tables/FunctionSelectors.sol @@ -21,14 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("FunctionSelector"))); bytes32 constant FunctionSelectorsTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0024020020040000000000000000000000000000000000000000000000000000 +); + library FunctionSelectors { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](2); - _fieldLayout[0] = 32; - _fieldLayout[1] = 4; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -63,19 +63,12 @@ library FunctionSelectors { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get resourceSelector */ @@ -83,7 +76,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -95,7 +88,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -104,7 +97,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); } /** Set resourceSelector (using the specified store) */ @@ -112,7 +105,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); } /** Get systemFunctionSelector */ @@ -120,7 +113,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (Bytes.slice4(_blob, 0)); } @@ -132,7 +125,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (Bytes.slice4(_blob, 0)); } @@ -141,7 +134,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((systemFunctionSelector)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((systemFunctionSelector)), _fieldLayout); } /** Set systemFunctionSelector (using the specified store) */ @@ -149,7 +142,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((systemFunctionSelector)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((systemFunctionSelector)), _fieldLayout); } /** Get the full data */ @@ -159,7 +152,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -171,7 +164,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -185,7 +178,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -203,7 +196,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Decode the tightly packed blob using this table's field layout */ @@ -241,7 +234,7 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -249,6 +242,6 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/src/modules/core/tables/ResourceType.sol b/packages/world/src/modules/core/tables/ResourceType.sol index ef1ce9ce3d..1d56109aa6 100644 --- a/packages/world/src/modules/core/tables/ResourceType.sol +++ b/packages/world/src/modules/core/tables/ResourceType.sol @@ -24,13 +24,14 @@ import { Resource } from "./../../../Types.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("ResourceType"))); bytes32 constant ResourceTypeTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0001010001000000000000000000000000000000000000000000000000000000 +); + library ResourceType { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 1; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -63,19 +64,12 @@ library ResourceType { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get resourceType */ @@ -83,7 +77,7 @@ library ResourceType { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return Resource(uint8(Bytes.slice1(_blob, 0))); } @@ -92,7 +86,7 @@ library ResourceType { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return Resource(uint8(Bytes.slice1(_blob, 0))); } @@ -101,7 +95,7 @@ library ResourceType { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), _fieldLayout); } /** Set resourceType (using the specified store) */ @@ -109,7 +103,7 @@ library ResourceType { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -140,7 +134,7 @@ library ResourceType { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -148,6 +142,6 @@ library ResourceType { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _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 d0503ff496..8ea6e2b31b 100644 --- a/packages/world/src/modules/core/tables/SystemHooks.sol +++ b/packages/world/src/modules/core/tables/SystemHooks.sol @@ -21,12 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("SystemHooks"))); bytes32 constant SystemHooksTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000100000000000000000000000000000000000000000000000000000000 +); + library SystemHooks { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 1); + return _fieldLayout; } /** Get the table's key schema */ @@ -59,19 +61,12 @@ library SystemHooks { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ @@ -79,7 +74,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -88,7 +83,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -97,7 +92,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value (using the specified store) */ @@ -105,7 +100,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Get the length of value */ @@ -113,7 +108,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 21; } @@ -124,7 +119,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 21; } @@ -143,7 +138,7 @@ library SystemHooks { _tableId, _keyTuple, 0, - getFieldLayout(), + _fieldLayout, _index * 21, (_index + 1) * 21 ); @@ -160,14 +155,7 @@ library SystemHooks { _keyTuple[0] = resourceSelector; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 0, - getFieldLayout(), - _index * 21, - (_index + 1) * 21 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 21, (_index + 1) * 21); return (Bytes.slice21(_blob, 0)); } } @@ -177,7 +165,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value (using the specified store) */ @@ -185,7 +173,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from value */ @@ -193,7 +181,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** Pop an element from value (using the specified store) */ @@ -201,7 +189,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.popFromField(_tableId, _keyTuple, 0, 21, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } /** @@ -213,7 +201,7 @@ library SystemHooks { _keyTuple[0] = resourceSelector; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); } } @@ -226,7 +214,7 @@ library SystemHooks { _keyTuple[0] = resourceSelector; unchecked { - _store.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); } } @@ -265,7 +253,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -273,6 +261,6 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _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 fa5e247567..4a83e64bec 100644 --- a/packages/world/src/modules/core/tables/SystemRegistry.sol +++ b/packages/world/src/modules/core/tables/SystemRegistry.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("SystemRegistry"))); bytes32 constant SystemRegistryTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0020010020000000000000000000000000000000000000000000000000000000 +); + library SystemRegistry { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 32; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -60,19 +61,12 @@ library SystemRegistry { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get resourceSelector */ @@ -80,7 +74,7 @@ library SystemRegistry { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -89,7 +83,7 @@ library SystemRegistry { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -98,7 +92,7 @@ library SystemRegistry { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); } /** Set resourceSelector (using the specified store) */ @@ -106,7 +100,7 @@ library SystemRegistry { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -137,7 +131,7 @@ library SystemRegistry { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -145,6 +139,6 @@ library SystemRegistry { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _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 52a9c0ad04..1316f4331a 100644 --- a/packages/world/src/modules/core/tables/Systems.sol +++ b/packages/world/src/modules/core/tables/Systems.sol @@ -21,14 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Systems"))); bytes32 constant SystemsTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0015020014010000000000000000000000000000000000000000000000000000 +); + library Systems { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](2); - _fieldLayout[0] = 20; - _fieldLayout[1] = 1; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -63,19 +63,12 @@ library Systems { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get system */ @@ -83,7 +76,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (address(Bytes.slice20(_blob, 0))); } @@ -92,7 +85,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (address(Bytes.slice20(_blob, 0))); } @@ -101,7 +94,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((system)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((system)), _fieldLayout); } /** Set system (using the specified store) */ @@ -109,7 +102,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((system)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((system)), _fieldLayout); } /** Get publicAccess */ @@ -117,7 +110,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -126,7 +119,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -135,7 +128,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((publicAccess)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((publicAccess)), _fieldLayout); } /** Set publicAccess (using the specified store) */ @@ -143,7 +136,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((publicAccess)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((publicAccess)), _fieldLayout); } /** Get the full data */ @@ -151,7 +144,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -160,7 +153,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -174,7 +167,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -187,7 +180,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Decode the tightly packed blob using this table's field layout */ @@ -225,7 +218,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -233,7 +226,7 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/src/modules/keysintable/tables/KeysInTable.sol b/packages/world/src/modules/keysintable/tables/KeysInTable.sol index ba91e6d7ae..589642c66c 100644 --- a/packages/world/src/modules/keysintable/tables/KeysInTable.sol +++ b/packages/world/src/modules/keysintable/tables/KeysInTable.sol @@ -21,6 +21,10 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("KeysInTable"))); bytes32 constant KeysInTableTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000500000000000000000000000000000000000000000000000000000000 +); + struct KeysInTableData { bytes32[] keys0; bytes32[] keys1; @@ -32,9 +36,7 @@ struct KeysInTableData { library KeysInTable { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 5); + return _fieldLayout; } /** Get the table's key schema */ @@ -75,19 +77,12 @@ library KeysInTable { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get keys0 */ @@ -95,7 +90,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -104,7 +99,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -113,7 +108,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keys0)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keys0)), _fieldLayout); } /** Set keys0 (using the specified store) */ @@ -121,7 +116,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keys0)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keys0)), _fieldLayout); } /** Get the length of keys0 */ @@ -129,7 +124,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 32; } @@ -140,7 +135,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 32; } @@ -159,7 +154,7 @@ library KeysInTable { _tableId, _keyTuple, 0, - getFieldLayout(), + _fieldLayout, _index * 32, (_index + 1) * 32 ); @@ -176,14 +171,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 0, - getFieldLayout(), - _index * 32, - (_index + 1) * 32 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 32, (_index + 1) * 32); return (Bytes.slice32(_blob, 0)); } } @@ -193,7 +181,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to keys0 (using the specified store) */ @@ -201,7 +189,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from keys0 */ @@ -209,7 +197,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.popFromField(_tableId, _keyTuple, 0, 32, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); } /** Pop an element from keys0 (using the specified store) */ @@ -217,7 +205,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.popFromField(_tableId, _keyTuple, 0, 32, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); } /** @@ -229,7 +217,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -242,7 +230,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - _store.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -251,7 +239,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -260,7 +248,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -269,7 +257,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.setField(_tableId, _keyTuple, 1, EncodeArray.encode((keys1)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, EncodeArray.encode((keys1)), _fieldLayout); } /** Set keys1 (using the specified store) */ @@ -277,7 +265,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.setField(_tableId, _keyTuple, 1, EncodeArray.encode((keys1)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, EncodeArray.encode((keys1)), _fieldLayout); } /** Get the length of keys1 */ @@ -285,7 +273,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 1, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); unchecked { return _byteLength / 32; } @@ -296,7 +284,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 1, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); unchecked { return _byteLength / 32; } @@ -315,7 +303,7 @@ library KeysInTable { _tableId, _keyTuple, 1, - getFieldLayout(), + _fieldLayout, _index * 32, (_index + 1) * 32 ); @@ -332,14 +320,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 1, - getFieldLayout(), - _index * 32, - (_index + 1) * 32 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 1, _fieldLayout, _index * 32, (_index + 1) * 32); return (Bytes.slice32(_blob, 0)); } } @@ -349,7 +330,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to keys1 (using the specified store) */ @@ -357,7 +338,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from keys1 */ @@ -365,7 +346,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.popFromField(_tableId, _keyTuple, 1, 32, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 1, 32, _fieldLayout); } /** Pop an element from keys1 (using the specified store) */ @@ -373,7 +354,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.popFromField(_tableId, _keyTuple, 1, 32, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 1, 32, _fieldLayout); } /** @@ -385,7 +366,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 1, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 1, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -398,7 +379,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - _store.updateInField(_tableId, _keyTuple, 1, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 1, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -407,7 +388,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -416,7 +397,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -425,7 +406,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.setField(_tableId, _keyTuple, 2, EncodeArray.encode((keys2)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 2, EncodeArray.encode((keys2)), _fieldLayout); } /** Set keys2 (using the specified store) */ @@ -433,7 +414,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.setField(_tableId, _keyTuple, 2, EncodeArray.encode((keys2)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 2, EncodeArray.encode((keys2)), _fieldLayout); } /** Get the length of keys2 */ @@ -441,7 +422,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 2, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); unchecked { return _byteLength / 32; } @@ -452,7 +433,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 2, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); unchecked { return _byteLength / 32; } @@ -471,7 +452,7 @@ library KeysInTable { _tableId, _keyTuple, 2, - getFieldLayout(), + _fieldLayout, _index * 32, (_index + 1) * 32 ); @@ -488,14 +469,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 2, - getFieldLayout(), - _index * 32, - (_index + 1) * 32 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 32, (_index + 1) * 32); return (Bytes.slice32(_blob, 0)); } } @@ -505,7 +479,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to keys2 (using the specified store) */ @@ -513,7 +487,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from keys2 */ @@ -521,7 +495,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.popFromField(_tableId, _keyTuple, 2, 32, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 2, 32, _fieldLayout); } /** Pop an element from keys2 (using the specified store) */ @@ -529,7 +503,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.popFromField(_tableId, _keyTuple, 2, 32, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 2, 32, _fieldLayout); } /** @@ -541,7 +515,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 2, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 2, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -554,7 +528,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - _store.updateInField(_tableId, _keyTuple, 2, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 2, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -563,7 +537,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -572,7 +546,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -581,7 +555,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.setField(_tableId, _keyTuple, 3, EncodeArray.encode((keys3)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 3, EncodeArray.encode((keys3)), _fieldLayout); } /** Set keys3 (using the specified store) */ @@ -589,7 +563,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.setField(_tableId, _keyTuple, 3, EncodeArray.encode((keys3)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 3, EncodeArray.encode((keys3)), _fieldLayout); } /** Get the length of keys3 */ @@ -597,7 +571,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 3, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); unchecked { return _byteLength / 32; } @@ -608,7 +582,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 3, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); unchecked { return _byteLength / 32; } @@ -627,7 +601,7 @@ library KeysInTable { _tableId, _keyTuple, 3, - getFieldLayout(), + _fieldLayout, _index * 32, (_index + 1) * 32 ); @@ -644,14 +618,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 3, - getFieldLayout(), - _index * 32, - (_index + 1) * 32 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 32, (_index + 1) * 32); return (Bytes.slice32(_blob, 0)); } } @@ -661,7 +628,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to keys3 (using the specified store) */ @@ -669,7 +636,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from keys3 */ @@ -677,7 +644,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.popFromField(_tableId, _keyTuple, 3, 32, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 3, 32, _fieldLayout); } /** Pop an element from keys3 (using the specified store) */ @@ -685,7 +652,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.popFromField(_tableId, _keyTuple, 3, 32, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 3, 32, _fieldLayout); } /** @@ -697,7 +664,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 3, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 3, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -710,7 +677,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - _store.updateInField(_tableId, _keyTuple, 3, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 3, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -719,7 +686,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -728,7 +695,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -737,7 +704,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.setField(_tableId, _keyTuple, 4, EncodeArray.encode((keys4)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 4, EncodeArray.encode((keys4)), _fieldLayout); } /** Set keys4 (using the specified store) */ @@ -745,7 +712,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.setField(_tableId, _keyTuple, 4, EncodeArray.encode((keys4)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 4, EncodeArray.encode((keys4)), _fieldLayout); } /** Get the length of keys4 */ @@ -753,7 +720,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 4, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 4, _fieldLayout); unchecked { return _byteLength / 32; } @@ -764,7 +731,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 4, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 4, _fieldLayout); unchecked { return _byteLength / 32; } @@ -783,7 +750,7 @@ library KeysInTable { _tableId, _keyTuple, 4, - getFieldLayout(), + _fieldLayout, _index * 32, (_index + 1) * 32 ); @@ -800,14 +767,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 4, - getFieldLayout(), - _index * 32, - (_index + 1) * 32 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 4, _fieldLayout, _index * 32, (_index + 1) * 32); return (Bytes.slice32(_blob, 0)); } } @@ -817,7 +777,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to keys4 (using the specified store) */ @@ -825,7 +785,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from keys4 */ @@ -833,7 +793,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.popFromField(_tableId, _keyTuple, 4, 32, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 4, 32, _fieldLayout); } /** Pop an element from keys4 (using the specified store) */ @@ -841,7 +801,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.popFromField(_tableId, _keyTuple, 4, 32, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 4, 32, _fieldLayout); } /** @@ -853,7 +813,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 4, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 4, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -866,7 +826,7 @@ library KeysInTable { _keyTuple[0] = sourceTable; unchecked { - _store.updateInField(_tableId, _keyTuple, 4, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 4, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -875,7 +835,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -884,7 +844,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -904,7 +864,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -924,7 +884,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using the data struct */ @@ -1047,7 +1007,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -1055,6 +1015,6 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _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 ac68814aa7..a0ebf6dea2 100644 --- a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol +++ b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol @@ -21,14 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("UsedKeysIndex"))); bytes32 constant UsedKeysIndexTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0006020001050000000000000000000000000000000000000000000000000000 +); + library UsedKeysIndex { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](2); - _fieldLayout[0] = 1; - _fieldLayout[1] = 5; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -65,19 +65,12 @@ library UsedKeysIndex { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get has */ @@ -86,7 +79,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -96,7 +89,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -106,7 +99,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((has)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((has)), _fieldLayout); } /** Set has (using the specified store) */ @@ -115,7 +108,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((has)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((has)), _fieldLayout); } /** Get index */ @@ -124,7 +117,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (uint40(Bytes.slice5(_blob, 0))); } @@ -134,7 +127,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (uint40(Bytes.slice5(_blob, 0))); } @@ -144,7 +137,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((index)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((index)), _fieldLayout); } /** Set index (using the specified store) */ @@ -153,7 +146,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((index)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((index)), _fieldLayout); } /** Get the full data */ @@ -162,7 +155,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -172,7 +165,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -187,7 +180,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -201,7 +194,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Decode the tightly packed blob using this table's field layout */ @@ -241,7 +234,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -250,7 +243,7 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol index a13236775a..47b0af5076 100644 --- a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol +++ b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol @@ -18,12 +18,14 @@ 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"; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000100000000000000000000000000000000000000000000000000000000 +); + library KeysWithValue { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 1); + return _fieldLayout; } /** Get the table's key schema */ @@ -56,19 +58,12 @@ library KeysWithValue { /** Register the table with its config */ function register(bytes32 _tableId) internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store, bytes32 _tableId) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get keysWithValue */ @@ -76,7 +71,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -89,7 +84,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -98,7 +93,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keysWithValue)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keysWithValue)), _fieldLayout); } /** Set keysWithValue (using the specified store) */ @@ -106,7 +101,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keysWithValue)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keysWithValue)), _fieldLayout); } /** Get the length of keysWithValue */ @@ -114,7 +109,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 32; } @@ -125,7 +120,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 32; } @@ -144,7 +139,7 @@ library KeysWithValue { _tableId, _keyTuple, 0, - getFieldLayout(), + _fieldLayout, _index * 32, (_index + 1) * 32 ); @@ -161,14 +156,7 @@ library KeysWithValue { _keyTuple[0] = valueHash; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 0, - getFieldLayout(), - _index * 32, - (_index + 1) * 32 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 32, (_index + 1) * 32); return (Bytes.slice32(_blob, 0)); } } @@ -178,7 +166,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to keysWithValue (using the specified store) */ @@ -186,7 +174,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from keysWithValue */ @@ -194,7 +182,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - StoreSwitch.popFromField(_tableId, _keyTuple, 0, 32, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); } /** Pop an element from keysWithValue (using the specified store) */ @@ -202,7 +190,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - _store.popFromField(_tableId, _keyTuple, 0, 32, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); } /** @@ -214,7 +202,7 @@ library KeysWithValue { _keyTuple[0] = valueHash; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -227,7 +215,7 @@ library KeysWithValue { _keyTuple[0] = valueHash; unchecked { - _store.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), _fieldLayout); } } @@ -266,7 +254,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -274,6 +262,6 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _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 070d868fe0..0cb37a05be 100644 --- a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("CallboundDelegat"))); bytes32 constant CallboundDelegationsTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0020010020000000000000000000000000000000000000000000000000000000 +); + library CallboundDelegations { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 32; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -66,19 +67,12 @@ library CallboundDelegations { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get availableCalls */ @@ -94,7 +88,7 @@ library CallboundDelegations { _keyTuple[2] = resourceSelector; _keyTuple[3] = funcSelectorAndArgsHash; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(Bytes.slice32(_blob, 0))); } @@ -112,7 +106,7 @@ library CallboundDelegations { _keyTuple[2] = resourceSelector; _keyTuple[3] = funcSelectorAndArgsHash; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(Bytes.slice32(_blob, 0))); } @@ -130,7 +124,7 @@ library CallboundDelegations { _keyTuple[2] = resourceSelector; _keyTuple[3] = funcSelectorAndArgsHash; - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); } /** Set availableCalls (using the specified store) */ @@ -148,7 +142,7 @@ library CallboundDelegations { _keyTuple[2] = resourceSelector; _keyTuple[3] = funcSelectorAndArgsHash; - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -195,7 +189,7 @@ library CallboundDelegations { _keyTuple[2] = resourceSelector; _keyTuple[3] = funcSelectorAndArgsHash; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -212,6 +206,6 @@ library CallboundDelegations { _keyTuple[2] = resourceSelector; _keyTuple[3] = funcSelectorAndArgsHash; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol index 3e7a015869..4fc2762cee 100644 --- a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("TimeboundDelegat"))); bytes32 constant TimeboundDelegationsTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0020010020000000000000000000000000000000000000000000000000000000 +); + library TimeboundDelegations { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 32; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -62,19 +63,12 @@ library TimeboundDelegations { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get maxTimestamp */ @@ -83,7 +77,7 @@ library TimeboundDelegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(Bytes.slice32(_blob, 0))); } @@ -93,7 +87,7 @@ library TimeboundDelegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(Bytes.slice32(_blob, 0))); } @@ -103,7 +97,7 @@ library TimeboundDelegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((maxTimestamp)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((maxTimestamp)), _fieldLayout); } /** Set maxTimestamp (using the specified store) */ @@ -112,7 +106,7 @@ library TimeboundDelegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((maxTimestamp)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((maxTimestamp)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -145,7 +139,7 @@ library TimeboundDelegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -154,6 +148,6 @@ library TimeboundDelegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol index 1b2238a638..a3e4568034 100644 --- a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol +++ b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol @@ -18,13 +18,14 @@ 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"; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0020010020000000000000000000000000000000000000000000000000000000 +); + library UniqueEntity { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 32; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -55,26 +56,19 @@ library UniqueEntity { /** Register the table with its config */ function register(bytes32 _tableId) internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store, bytes32 _tableId) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ function get(bytes32 _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(Bytes.slice32(_blob, 0))); } @@ -82,7 +76,7 @@ library UniqueEntity { function get(IStore _store, bytes32 _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(Bytes.slice32(_blob, 0))); } @@ -90,14 +84,14 @@ library UniqueEntity { function set(bytes32 _tableId, uint256 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ function set(IStore _store, bytes32 _tableId, uint256 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -126,13 +120,13 @@ library UniqueEntity { function deleteRecord(bytes32 _tableId) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.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[](0); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/src/tables/Delegations.sol b/packages/world/src/tables/Delegations.sol index 22420ee76b..5bdb511112 100644 --- a/packages/world/src/tables/Delegations.sol +++ b/packages/world/src/tables/Delegations.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Delegations"))); bytes32 constant DelegationsTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0020010020000000000000000000000000000000000000000000000000000000 +); + library Delegations { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 32; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -62,19 +63,12 @@ library Delegations { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get delegationControlId */ @@ -83,7 +77,7 @@ library Delegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -97,7 +91,7 @@ library Delegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (Bytes.slice32(_blob, 0)); } @@ -107,7 +101,7 @@ library Delegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((delegationControlId)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((delegationControlId)), _fieldLayout); } /** Set delegationControlId (using the specified store) */ @@ -116,7 +110,7 @@ library Delegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((delegationControlId)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((delegationControlId)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -149,7 +143,7 @@ library Delegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -158,6 +152,6 @@ library Delegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/src/tables/InstalledModules.sol b/packages/world/src/tables/InstalledModules.sol index 9f7b45859c..637770c6b9 100644 --- a/packages/world/src/tables/InstalledModules.sol +++ b/packages/world/src/tables/InstalledModules.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("InstalledModules"))); bytes32 constant InstalledModulesTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0014010014000000000000000000000000000000000000000000000000000000 +); + library InstalledModules { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 20; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -62,19 +63,12 @@ library InstalledModules { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get moduleAddress */ @@ -83,7 +77,7 @@ library InstalledModules { _keyTuple[0] = bytes32(moduleName); _keyTuple[1] = argumentsHash; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (address(Bytes.slice20(_blob, 0))); } @@ -93,7 +87,7 @@ library InstalledModules { _keyTuple[0] = bytes32(moduleName); _keyTuple[1] = argumentsHash; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (address(Bytes.slice20(_blob, 0))); } @@ -103,7 +97,7 @@ library InstalledModules { _keyTuple[0] = bytes32(moduleName); _keyTuple[1] = argumentsHash; - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((moduleAddress)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((moduleAddress)), _fieldLayout); } /** Set moduleAddress (using the specified store) */ @@ -112,7 +106,7 @@ library InstalledModules { _keyTuple[0] = bytes32(moduleName); _keyTuple[1] = argumentsHash; - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((moduleAddress)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((moduleAddress)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -145,7 +139,7 @@ library InstalledModules { _keyTuple[0] = bytes32(moduleName); _keyTuple[1] = argumentsHash; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -154,6 +148,6 @@ library InstalledModules { _keyTuple[0] = bytes32(moduleName); _keyTuple[1] = argumentsHash; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/src/tables/NamespaceOwner.sol b/packages/world/src/tables/NamespaceOwner.sol index 85d58a4921..d290e3fcab 100644 --- a/packages/world/src/tables/NamespaceOwner.sol +++ b/packages/world/src/tables/NamespaceOwner.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("NamespaceOwner"))); bytes32 constant NamespaceOwnerTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0014010014000000000000000000000000000000000000000000000000000000 +); + library NamespaceOwner { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 20; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -60,19 +61,12 @@ library NamespaceOwner { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get owner */ @@ -80,7 +74,7 @@ library NamespaceOwner { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (address(Bytes.slice20(_blob, 0))); } @@ -89,7 +83,7 @@ library NamespaceOwner { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (address(Bytes.slice20(_blob, 0))); } @@ -98,7 +92,7 @@ library NamespaceOwner { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); } /** Set owner (using the specified store) */ @@ -106,7 +100,7 @@ library NamespaceOwner { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -137,7 +131,7 @@ library NamespaceOwner { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -145,6 +139,6 @@ library NamespaceOwner { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/src/tables/ResourceAccess.sol b/packages/world/src/tables/ResourceAccess.sol index 51a3dba36d..1e6b75690b 100644 --- a/packages/world/src/tables/ResourceAccess.sol +++ b/packages/world/src/tables/ResourceAccess.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("ResourceAccess"))); bytes32 constant ResourceAccessTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0001010001000000000000000000000000000000000000000000000000000000 +); + library ResourceAccess { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 1; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -62,19 +63,12 @@ library ResourceAccess { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get access */ @@ -83,7 +77,7 @@ library ResourceAccess { _keyTuple[0] = resourceSelector; _keyTuple[1] = bytes32(uint256(uint160(caller))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -93,7 +87,7 @@ library ResourceAccess { _keyTuple[0] = resourceSelector; _keyTuple[1] = bytes32(uint256(uint160(caller))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -103,7 +97,7 @@ library ResourceAccess { _keyTuple[0] = resourceSelector; _keyTuple[1] = bytes32(uint256(uint160(caller))); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); } /** Set access (using the specified store) */ @@ -112,7 +106,7 @@ library ResourceAccess { _keyTuple[0] = resourceSelector; _keyTuple[1] = bytes32(uint256(uint160(caller))); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -145,7 +139,7 @@ library ResourceAccess { _keyTuple[0] = resourceSelector; _keyTuple[1] = bytes32(uint256(uint160(caller))); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -154,7 +148,7 @@ library ResourceAccess { _keyTuple[0] = resourceSelector; _keyTuple[1] = bytes32(uint256(uint160(caller))); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/test/tables/AddressArray.sol b/packages/world/test/tables/AddressArray.sol index ecd9e930ac..8064fad34e 100644 --- a/packages/world/test/tables/AddressArray.sol +++ b/packages/world/test/tables/AddressArray.sol @@ -18,12 +18,14 @@ 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"; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0000000100000000000000000000000000000000000000000000000000000000 +); + library AddressArray { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](0); - - return FieldLayoutLib.encode(_fieldLayout, 1); + return _fieldLayout; } /** Get the table's key schema */ @@ -56,19 +58,12 @@ library AddressArray { /** Register the table with its config */ function register(bytes32 _tableId) internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store, bytes32 _tableId) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ @@ -76,7 +71,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); } @@ -85,7 +80,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); } @@ -94,7 +89,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Set value (using the specified store) */ @@ -102,7 +97,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } /** Get the length of value */ @@ -110,7 +105,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = StoreSwitch.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 20; } @@ -121,7 +116,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, getFieldLayout()); + uint256 _byteLength = _store.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); unchecked { return _byteLength / 20; } @@ -140,7 +135,7 @@ library AddressArray { _tableId, _keyTuple, 0, - getFieldLayout(), + _fieldLayout, _index * 20, (_index + 1) * 20 ); @@ -157,14 +152,7 @@ library AddressArray { _keyTuple[0] = key; unchecked { - bytes memory _blob = _store.getFieldSlice( - _tableId, - _keyTuple, - 0, - getFieldLayout(), - _index * 20, - (_index + 1) * 20 - ); + bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 20, (_index + 1) * 20); return (address(Bytes.slice20(_blob, 0))); } } @@ -174,7 +162,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Push an element to value (using the specified store) */ @@ -182,7 +170,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), getFieldLayout()); + _store.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } /** Pop an element from value */ @@ -190,7 +178,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.popFromField(_tableId, _keyTuple, 0, 20, getFieldLayout()); + StoreSwitch.popFromField(_tableId, _keyTuple, 0, 20, _fieldLayout); } /** Pop an element from value (using the specified store) */ @@ -198,7 +186,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.popFromField(_tableId, _keyTuple, 0, 20, getFieldLayout()); + _store.popFromField(_tableId, _keyTuple, 0, 20, _fieldLayout); } /** @@ -210,7 +198,7 @@ library AddressArray { _keyTuple[0] = key; unchecked { - StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 20, abi.encodePacked((_element)), getFieldLayout()); + StoreSwitch.updateInField(_tableId, _keyTuple, 0, _index * 20, abi.encodePacked((_element)), _fieldLayout); } } @@ -223,7 +211,7 @@ library AddressArray { _keyTuple[0] = key; unchecked { - _store.updateInField(_tableId, _keyTuple, 0, _index * 20, abi.encodePacked((_element)), getFieldLayout()); + _store.updateInField(_tableId, _keyTuple, 0, _index * 20, abi.encodePacked((_element)), _fieldLayout); } } @@ -262,7 +250,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -270,6 +258,6 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/packages/world/test/tables/Bool.sol b/packages/world/test/tables/Bool.sol index 9d471471ac..001f076745 100644 --- a/packages/world/test/tables/Bool.sol +++ b/packages/world/test/tables/Bool.sol @@ -18,13 +18,14 @@ 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"; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0001010001000000000000000000000000000000000000000000000000000000 +); + library Bool { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 1; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -55,26 +56,19 @@ library Bool { /** Register the table with its config */ function register(bytes32 _tableId) internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store, bytes32 _tableId) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ function get(bytes32 _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -82,7 +76,7 @@ library Bool { function get(IStore _store, bytes32 _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); } @@ -90,14 +84,14 @@ library Bool { function set(bytes32 _tableId, bool value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ function set(IStore _store, bytes32 _tableId, bool value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -126,14 +120,14 @@ library Bool { function deleteRecord(bytes32 _tableId) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.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[](0); - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } diff --git a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol index 6b2a3f319b..5422d16dad 100644 --- a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Counter"))); bytes32 constant CounterTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0004010004000000000000000000000000000000000000000000000000000000 +); + library Counter { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 4; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -58,26 +59,19 @@ library Counter { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ function get() internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -85,7 +79,7 @@ library Counter { function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -93,14 +87,14 @@ library Counter { function set(uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ function set(IStore _store, uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -129,13 +123,13 @@ library Counter { function deleteRecord() internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.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, getFieldLayout()); + _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 6b2a3f319b..5422d16dad 100644 --- a/templates/react/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/react/packages/contracts/src/codegen/tables/Counter.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Counter"))); bytes32 constant CounterTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0004010004000000000000000000000000000000000000000000000000000000 +); + library Counter { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 4; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -58,26 +59,19 @@ library Counter { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ function get() internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -85,7 +79,7 @@ library Counter { function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -93,14 +87,14 @@ library Counter { function set(uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ function set(IStore _store, uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -129,13 +123,13 @@ library Counter { function deleteRecord() internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.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, getFieldLayout()); + _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 b93c3a63c3..624887fbb2 100644 --- a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol +++ b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol @@ -21,6 +21,10 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Position"))); bytes32 constant PositionTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x000c030004040400000000000000000000000000000000000000000000000000 +); + struct PositionData { int32 x; int32 y; @@ -30,12 +34,7 @@ struct PositionData { library Position { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](3); - _fieldLayout[0] = 4; - _fieldLayout[1] = 4; - _fieldLayout[2] = 4; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -72,19 +71,12 @@ library Position { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get x */ @@ -92,7 +84,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -101,7 +93,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -110,7 +102,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } /** Set x (using the specified store) */ @@ -118,7 +110,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } /** Get y */ @@ -126,7 +118,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -135,7 +127,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -144,7 +136,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } /** Set y (using the specified store) */ @@ -152,7 +144,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } /** Get z */ @@ -160,7 +152,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -169,7 +161,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); return (int32(uint32(Bytes.slice4(_blob, 0)))); } @@ -178,7 +170,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setField(_tableId, _keyTuple, 2, abi.encodePacked((z)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 2, abi.encodePacked((z)), _fieldLayout); } /** Set z (using the specified store) */ @@ -186,7 +178,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setField(_tableId, _keyTuple, 2, abi.encodePacked((z)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 2, abi.encodePacked((z)), _fieldLayout); } /** Get the full data */ @@ -194,7 +186,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -203,7 +195,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, getFieldLayout()); + bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); } @@ -217,7 +209,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using individual values (using the specified store) */ @@ -230,7 +222,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, getFieldLayout()); + _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } /** Set the full data using the data struct */ @@ -280,7 +272,7 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } /* Delete all data for given keys (using the specified store) */ @@ -288,6 +280,6 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - _store.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + _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 6b2a3f319b..5422d16dad 100644 --- a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol @@ -21,13 +21,14 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Counter"))); bytes32 constant CounterTableId = _tableId; +FieldLayout constant _fieldLayout = FieldLayout.wrap( + 0x0004010004000000000000000000000000000000000000000000000000000000 +); + library Counter { /** Get the table values' field layout */ function getFieldLayout() internal pure returns (FieldLayout) { - uint256[] memory _fieldLayout = new uint256[](1); - _fieldLayout[0] = 4; - - return FieldLayoutLib.encode(_fieldLayout, 0); + return _fieldLayout; } /** Get the table's key schema */ @@ -58,26 +59,19 @@ library Counter { /** Register the table with its config */ function register() internal { - StoreSwitch.registerTable( - _tableId, - getFieldLayout(), - getKeySchema(), - getValueSchema(), - getKeyNames(), - getFieldNames() - ); + StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { - _store.registerTable(_tableId, getFieldLayout(), getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } /** Get value */ function get() internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -85,7 +79,7 @@ library Counter { function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, getFieldLayout()); + bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); return (uint32(Bytes.slice4(_blob, 0))); } @@ -93,14 +87,14 @@ library Counter { function set(uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Set value (using the specified store) */ function set(IStore _store, uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); - _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), getFieldLayout()); + _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } /** Tightly pack static data using this table's schema */ @@ -129,13 +123,13 @@ library Counter { function deleteRecord() internal { bytes32[] memory _keyTuple = new bytes32[](0); - StoreSwitch.deleteRecord(_tableId, _keyTuple, getFieldLayout()); + StoreSwitch.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, getFieldLayout()); + _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } } From be313068b158265c2deada55eebfd6ba753abb87 Mon Sep 17 00:00:00 2001 From: Boffee Date: Sat, 16 Sep 2023 13:03:59 -0500 Subject: [PATCH 04/17] feat(store): optimize storage location hash (#1509) Co-authored-by: alvrs --- .changeset/short-dragons-shout.md | 6 ++ packages/store/gas-report.json | 162 +++++++++++++++--------------- packages/store/src/StoreCore.sol | 8 +- packages/world/gas-report.json | 122 +++++++++++----------- 4 files changed, 153 insertions(+), 145 deletions(-) create mode 100644 .changeset/short-dragons-shout.md diff --git a/.changeset/short-dragons-shout.md b/.changeset/short-dragons-shout.md new file mode 100644 index 0000000000..d2c8abe6f1 --- /dev/null +++ b/.changeset/short-dragons-shout.md @@ -0,0 +1,6 @@ +--- +"@latticexyz/store": patch +"@latticexyz/world": patch +--- + +Optimized the `StoreCore` hash function determining the data location to use less gas. diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 536bc29c03..c9ad2ff992 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -339,7 +339,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register KeyEncoding table", - "gasUsed": 691073 + "gasUsed": 690015 }, { "file": "test/Mixed.t.sol", @@ -351,19 +351,19 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Mixed table", - "gasUsed": 552911 + "gasUsed": 551833 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 105912 + "gasUsed": 104922 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "get record from Mixed", - "gasUsed": 7821 + "gasUsed": 7181 }, { "file": "test/PackedCounter.t.sol", @@ -549,217 +549,217 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (cold, 1 slot)", - "gasUsed": 8424 + "gasUsed": 8281 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 1 slot)", - "gasUsed": 2492 + "gasUsed": 2349 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (semi-cold, 1 slot)", - "gasUsed": 4498 + "gasUsed": 4353 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 2 slots)", - "gasUsed": 4724 + "gasUsed": 4580 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetSecondFieldLength", "name": "get field length (cold, 1 slot)", - "gasUsed": 7965 + "gasUsed": 7756 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetSecondFieldLength", "name": "get field length (warm, 1 slot)", - "gasUsed": 1961 + "gasUsed": 1752 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetThirdFieldLength", "name": "get field length (warm due to , 2 slots)", - "gasUsed": 7965 + "gasUsed": 7756 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetThirdFieldLength", "name": "get field length (warm, 2 slots)", - "gasUsed": 1962 + "gasUsed": 1752 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 22215 + "gasUsed": 21297 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 16250 + "gasUsed": 15309 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 24412 + "gasUsed": 23493 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 16447 + "gasUsed": 15505 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access non-existing record", - "gasUsed": 6533 + "gasUsed": 6197 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access static field of non-existing record", - "gasUsed": 1481 + "gasUsed": 1357 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access dynamic field of non-existing record", - "gasUsed": 2449 + "gasUsed": 2090 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access length of dynamic field of non-existing record", - "gasUsed": 1335 + "gasUsed": 1120 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access slice of dynamic field of non-existing record", - "gasUsed": 1631 + "gasUsed": 1484 }, { "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 8403 + "gasUsed": 7702 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "Check for existence of table (existent)", - "gasUsed": 2303 + "gasUsed": 2178 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "check for existence of table (non-existent)", - "gasUsed": 4305 + "gasUsed": 4180 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 60434 + "gasUsed": 59474 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 74048 + "gasUsed": 73142 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 23815 + "gasUsed": 22908 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 19366 + "gasUsed": 18460 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 60434 + "gasUsed": 59474 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 167817 + "gasUsed": 166238 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 27452 + "gasUsed": 26108 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 20750 + "gasUsed": 19445 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 14154 + "gasUsed": 13053 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 36926 + "gasUsed": 35807 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 615037 + "gasUsed": 613985 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get field layout (warm)", - "gasUsed": 2317 + "gasUsed": 2191 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get value schema (warm)", - "gasUsed": 2870 + "gasUsed": 2744 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get key schema (warm)", - "gasUsed": 4952 + "gasUsed": 4699 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 103828 + "gasUsed": 102843 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "get complex record with dynamic data (4 slots)", - "gasUsed": 5104 + "gasUsed": 4469 }, { "file": "test/StoreCoreGas.t.sol", @@ -771,109 +771,109 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "compare: Set complex record with dynamic data using abi.encode", - "gasUsed": 267372 + "gasUsed": 267368 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 0", - "gasUsed": 23081 + "gasUsed": 22870 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 1", - "gasUsed": 1183 + "gasUsed": 970 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "reduce dynamic length of dynamic index 0", - "gasUsed": 1174 + "gasUsed": 961 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 33047 + "gasUsed": 32564 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (1 slot)", - "gasUsed": 1483 + "gasUsed": 1357 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 31694 + "gasUsed": 31204 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (overlap 2 slot)", - "gasUsed": 2010 + "gasUsed": 1883 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 54826 + "gasUsed": 54090 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, first dynamic field)", - "gasUsed": 2627 + "gasUsed": 2258 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 33064 + "gasUsed": 32317 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, second dynamic field)", - "gasUsed": 2633 + "gasUsed": 2260 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 33629 + "gasUsed": 33148 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "get static record (1 slot)", - "gasUsed": 1733 + "gasUsed": 1608 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 56133 + "gasUsed": 55652 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "get static record (2 slots)", - "gasUsed": 1922 + "gasUsed": 1796 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 15192 + "gasUsed": 14090 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 16012 + "gasUsed": 14894 }, { "file": "test/StoreHook.t.sol", @@ -921,121 +921,121 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 57881 + "gasUsed": 57164 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: get field (warm)", - "gasUsed": 4092 + "gasUsed": 3732 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 37215 + "gasUsed": 36119 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 59867 + "gasUsed": 59162 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 59866 + "gasUsed": 59162 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: get field (warm)", - "gasUsed": 4071 + "gasUsed": 3716 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 17284 + "gasUsed": 16205 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 13710 + "gasUsed": 12760 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 15349 + "gasUsed": 14231 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 36470 + "gasUsed": 35329 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 8856 + "gasUsed": 8113 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 32110 + "gasUsed": 31324 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 82558 + "gasUsed": 81853 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 82469 + "gasUsed": 81764 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 17662 + "gasUsed": 16978 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGet", "name": "StoreHooks: get field (cold)", - "gasUsed": 10064 + "gasUsed": 9713 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGetItem", "name": "StoreHooks: get 1 element (cold)", - "gasUsed": 6582 + "gasUsed": 6440 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testLength", "name": "StoreHooks: get length (cold)", - "gasUsed": 6062 + "gasUsed": 5853 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 24160 + "gasUsed": 23246 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 26441 + "gasUsed": 25382 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -1089,18 +1089,18 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 414353 + "gasUsed": 413256 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 34533 + "gasUsed": 34051 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "get Vector2 record", - "gasUsed": 2656 + "gasUsed": 2530 } ] diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 6187beb974..f752e7e7c9 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -624,6 +624,8 @@ library StoreCore { library StoreCoreInternal { 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"); /************************************************************************ * @@ -912,7 +914,7 @@ library StoreCoreInternal { * Compute the storage location based on tableId id and index tuple */ function _getStaticDataLocation(bytes32 tableId, bytes32[] memory keyTuple) internal pure returns (uint256) { - return uint256(keccak256(abi.encode(SLOT, tableId, keyTuple))); + return uint256(SLOT ^ keccak256(abi.encodePacked(tableId, keyTuple))); } /** @@ -938,14 +940,14 @@ library StoreCoreInternal { bytes32[] memory keyTuple, uint8 fieldIndex ) internal pure returns (uint256) { - return uint256(keccak256(abi.encode(SLOT, tableId, keyTuple, fieldIndex))); + return uint256(DYNMAIC_DATA_SLOT ^ bytes1(fieldIndex) ^ keccak256(abi.encodePacked(tableId, keyTuple))); } /** * Compute the storage location for the length of the dynamic data */ function _getDynamicDataLengthLocation(bytes32 tableId, bytes32[] memory keyTuple) internal pure returns (uint256) { - return uint256(keccak256(abi.encode(SLOT, tableId, keyTuple, "length"))); + return uint256(DYNAMIC_DATA_LENGTH_SLOT ^ keccak256(abi.encodePacked(tableId, keyTuple))); } /** diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 0757bfb9b3..7775787446 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -3,31 +3,31 @@ "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (cold)", - "gasUsed": 10912 + "gasUsed": 10667 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm, namespace only)", - "gasUsed": 2532 + "gasUsed": 2408 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm)", - "gasUsed": 4940 + "gasUsed": 4689 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (cold)", - "gasUsed": 10954 + "gasUsed": 10709 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (warm)", - "gasUsed": 4959 + "gasUsed": 4713 }, { "file": "test/AccessControl.t.sol", @@ -39,73 +39,73 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1453384 + "gasUsed": 1443420 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1453384 + "gasUsed": 1443420 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 170849 + "gasUsed": 167906 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1453384 + "gasUsed": 1443420 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1453384 + "gasUsed": 1443420 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 26036 + "gasUsed": 25326 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 205921 + "gasUsed": 195723 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1453384 + "gasUsed": 1443420 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 24758 + "gasUsed": 24049 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 106239 + "gasUsed": 101263 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 682161 + "gasUsed": 674478 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "Get list of keys with a given value", - "gasUsed": 6521 + "gasUsed": 6170 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,264 +117,264 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 682161 + "gasUsed": 674478 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 146160 + "gasUsed": 142864 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 682161 + "gasUsed": 674478 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 115759 + "gasUsed": 112442 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 40440 + "gasUsed": 38443 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 682161 + "gasUsed": 674478 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 150906 + "gasUsed": 147478 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 115665 + "gasUsed": 112237 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 112790 + "gasUsed": 109103 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 57749 + "gasUsed": 55818 }, { "file": "test/query.t.sol", "test": "testCombinedHasNotQuery", "name": "CombinedHasNotQuery", - "gasUsed": 140333 + "gasUsed": 135801 }, { "file": "test/query.t.sol", "test": "testCombinedHasQuery", "name": "CombinedHasQuery", - "gasUsed": 90971 + "gasUsed": 87885 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 91191 + "gasUsed": 88206 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueQuery", "name": "CombinedHasValueQuery", - "gasUsed": 17316 + "gasUsed": 16614 }, { "file": "test/query.t.sol", "test": "testHasQuery", "name": "HasQuery", - "gasUsed": 20461 + "gasUsed": 19725 }, { "file": "test/query.t.sol", "test": "testHasQuery1000Keys", "name": "HasQuery with 1000 keys", - "gasUsed": 5985870 + "gasUsed": 5843418 }, { "file": "test/query.t.sol", "test": "testHasQuery100Keys", "name": "HasQuery with 100 keys", - "gasUsed": 560764 + "gasUsed": 546112 }, { "file": "test/query.t.sol", "test": "testHasValueQuery", "name": "HasValueQuery", - "gasUsed": 8329 + "gasUsed": 7978 }, { "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 51345 + "gasUsed": 49414 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 120433 + "gasUsed": 118637 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 39201 + "gasUsed": 37881 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 114784 + "gasUsed": 112991 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 30837 + "gasUsed": 29993 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 721941 + "gasUsed": 712299 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 57530 + "gasUsed": 56214 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 708712 + "gasUsed": 699545 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 57530 + "gasUsed": 56214 }, { "file": "test/World.t.sol", "test": "testCall", "name": "call a system via the World", - "gasUsed": 15199 + "gasUsed": 14602 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 52070 + "gasUsed": 50997 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "call a system via an unlimited delegation", - "gasUsed": 15608 + "gasUsed": 15010 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 11340 + "gasUsed": 10744 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 91372 + "gasUsed": 90191 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 65058 + "gasUsed": 63739 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 58308 + "gasUsed": 56989 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 85651 + "gasUsed": 84333 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 133367 + "gasUsed": 131214 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 80226 + "gasUsed": 78907 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 660018 + "gasUsed": 655916 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 39628 + "gasUsed": 39031 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 37622 + "gasUsed": 37025 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 30387 + "gasUsed": 29349 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 17500 + "gasUsed": 16462 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 33910 + "gasUsed": 32728 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 21115 + "gasUsed": 19933 } ] From 0f3e2e02b5114e08fe700c18326db76816ffad3c Mon Sep 17 00:00:00 2001 From: Boffee Date: Sat, 16 Sep 2023 14:58:04 -0500 Subject: [PATCH 05/17] feat(store): add Storage.loadField for optimized loading of 32 bytes or less from storage (#1512) Co-authored-by: alvarius --- .changeset/hungry-rings-doubt.md | 5 ++++ packages/store/gas-report.json | 14 +++++++++- packages/store/src/Storage.sol | 35 ++++++++++++++++++++++++ packages/store/test/GasStorageLoad.t.sol | 12 ++++++++ packages/store/test/Storage.t.sol | 18 ++++++++++++ 5 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 .changeset/hungry-rings-doubt.md diff --git a/.changeset/hungry-rings-doubt.md b/.changeset/hungry-rings-doubt.md new file mode 100644 index 0000000000..d5d3ac9263 --- /dev/null +++ b/.changeset/hungry-rings-doubt.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store": patch +--- + +Added `Storage.loadField` to optimize loading 32 bytes or less from storage (which is always the case when loading data for static fields). diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index c9ad2ff992..7ac2f7e9e6 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -281,17 +281,29 @@ "name": "MUD storage load (warm, 1 word)", "gasUsed": 412 }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadMUD", + "name": "MUD storage load field (warm, 1 word)", + "gasUsed": 245 + }, { "file": "test/GasStorageLoad.t.sol", "test": "testCompareStorageLoadMUD", "name": "MUD storage load (warm, 1 word, partial)", "gasUsed": 460 }, + { + "file": "test/GasStorageLoad.t.sol", + "test": "testCompareStorageLoadMUD", + "name": "MUD storage load field (warm, 1 word, partial)", + "gasUsed": 378 + }, { "file": "test/GasStorageLoad.t.sol", "test": "testCompareStorageLoadMUD", "name": "MUD storage load (warm, 10 words)", - "gasUsed": 1914 + "gasUsed": 1916 }, { "file": "test/GasStorageLoad.t.sol", diff --git a/packages/store/src/Storage.sol b/packages/store/src/Storage.sol index 0961cf4d20..427e45748f 100644 --- a/packages/store/src/Storage.sol +++ b/packages/store/src/Storage.sol @@ -209,4 +209,39 @@ library Storage { } } } + + /** + * Load up to 32 bytes from storage at the given storagePointer and offset. + * The return value is left-aligned, the bytes beyond the length are not zeroed out, + * and the caller is expected to truncate as needed. + * Since fields are tightly packed, they can span more than one slot. + * Since the they're max 32 bytes, they can span at most 2 slots. + */ + function loadField(uint256 storagePointer, uint256 length, uint256 offset) internal view returns (bytes32 result) { + if (offset >= 32) { + unchecked { + storagePointer += offset / 32; + offset %= 32; + } + } + + // Extra data past length is not truncated + // This assumes that the caller will handle the overflow bits appropriately + assembly { + result := shl(mul(offset, 8), sload(storagePointer)) + } + + uint256 wordRemainder; + // (safe because of `offset %= 32` at the start) + unchecked { + wordRemainder = 32 - offset; + } + + // Read from the next slot if field spans 2 slots + if (length > wordRemainder) { + assembly { + result := or(result, shr(mul(wordRemainder, 8), sload(add(storagePointer, 1)))) + } + } + } } diff --git a/packages/store/test/GasStorageLoad.t.sol b/packages/store/test/GasStorageLoad.t.sol index 3991d25e12..ab13727d31 100644 --- a/packages/store/test/GasStorageLoad.t.sol +++ b/packages/store/test/GasStorageLoad.t.sol @@ -67,6 +67,9 @@ contract GasStorageLoadTest is Test, GasReporter { bytes memory encodedPartial = abi.encodePacked(valuePartial); bytes memory encoded9Words = abi.encodePacked(value9Words.length, value9Words); + bytes32 encodedFieldSimple = valueSimple; + bytes32 encodedFieldPartial = valuePartial; + startGasReport("MUD storage load (cold, 1 word)"); encodedSimple = Storage.load(SolidityStorage.STORAGE_SLOT_SIMPLE, encodedSimple.length, 0); endGasReport(); @@ -85,10 +88,19 @@ contract GasStorageLoadTest is Test, GasReporter { encodedSimple = Storage.load(SolidityStorage.STORAGE_SLOT_SIMPLE, encodedSimple.length, 0); endGasReport(); + startGasReport("MUD storage load field (warm, 1 word)"); + encodedFieldSimple = Storage.loadField(SolidityStorage.STORAGE_SLOT_SIMPLE, encodedSimple.length, 0); + endGasReport(); + startGasReport("MUD storage load (warm, 1 word, partial)"); encodedPartial = Storage.load(SolidityStorage.STORAGE_SLOT_PARTIAL, encodedPartial.length, 16); endGasReport(); + encodedFieldPartial = Storage.loadField(SolidityStorage.STORAGE_SLOT_PARTIAL, encodedSimple.length, 16); + startGasReport("MUD storage load field (warm, 1 word, partial)"); + encodedFieldPartial = Storage.loadField(SolidityStorage.STORAGE_SLOT_PARTIAL, encodedSimple.length, 16); + endGasReport(); + startGasReport("MUD storage load (warm, 10 words)"); encoded9Words = Storage.load(SolidityStorage.STORAGE_SLOT_BYTES, encoded9Words.length, 0); endGasReport(); diff --git a/packages/store/test/Storage.t.sol b/packages/store/test/Storage.t.sol index 1d6005aa6d..9c6d13ebd9 100644 --- a/packages/store/test/Storage.t.sol +++ b/packages/store/test/Storage.t.sol @@ -75,4 +75,22 @@ contract StorageTest is Test, GasReporter { Storage.store({ storagePointer: uint256(storagePointer), offset: offset, data: data }); assertEq(Storage.load({ storagePointer: uint256(storagePointer), length: data.length, offset: offset }), data); } + + function testStoreLoadFieldBytes32Fuzzy(bytes32 data, uint256 storagePointer, uint256 offset) public { + vm.assume(offset < type(uint256).max); + vm.assume(storagePointer > 0); + vm.assume(storagePointer < type(uint256).max - offset); + + Storage.store({ storagePointer: storagePointer, offset: offset, data: abi.encodePacked((data)) }); + assertEq(Storage.loadField({ storagePointer: storagePointer, length: 32, offset: offset }), data); + } + + function testStoreLoadFieldBytes16Fuzzy(bytes16 data, uint256 storagePointer, uint256 offset) public { + vm.assume(offset < type(uint256).max); + vm.assume(storagePointer > 0); + vm.assume(storagePointer < type(uint256).max - offset); + + Storage.store({ storagePointer: storagePointer, offset: offset, data: abi.encodePacked((data)) }); + assertEq(bytes16(Storage.loadField({ storagePointer: storagePointer, length: 16, offset: offset })), data); + } } From 55ab88a60adb3ad72ebafef4d50513eb71e3c314 Mon Sep 17 00:00:00 2001 From: alvarius Date: Sat, 16 Sep 2023 22:35:08 +0100 Subject: [PATCH 06/17] feat(store): expose `getStaticField` and `getDynamicField` on `IStore` and use it in codegen tables (#1521) --- .changeset/sour-cycles-warn.md | 34 +++++ .../contracts/src/codegen/tables/Multi.sol | 16 +-- .../contracts/src/codegen/tables/Number.sol | 8 +- .../src/codegen/tables/NumberList.sol | 8 +- .../contracts/src/codegen/tables/Vector.sol | 16 +-- .../src/codegen/tables/CounterTable.sol | 8 +- .../src/codegen/tables/Inventory.sol | 8 +- .../src/codegen/tables/Dynamics1.sol | 40 +++--- .../src/codegen/tables/Dynamics2.sol | 16 +-- .../src/codegen/tables/Singleton.sol | 32 ++--- .../contracts/src/codegen/tables/Statics.sol | 48 +++---- packages/store/gas-report.json | 134 +++++++++--------- packages/store/src/IStore.sol | 39 ++++- packages/store/src/StoreCore.sol | 84 +++++++---- packages/store/src/StoreRead.sol | 19 ++- packages/store/src/StoreSwitch.sol | 27 ++++ .../store/src/codegen/tables/Callbacks.sol | 8 +- packages/store/src/codegen/tables/Hooks.sol | 8 +- .../store/src/codegen/tables/KeyEncoding.sol | 8 +- packages/store/src/codegen/tables/Mixed.sol | 28 ++-- .../store/src/codegen/tables/StoreHooks.sol | 8 +- packages/store/src/codegen/tables/Tables.sol | 32 ++--- packages/store/src/codegen/tables/Vector2.sol | 16 +-- packages/store/ts/codegen/field.ts | 35 ++++- packages/world/gas-report.json | 122 ++++++++-------- .../src/modules/core/tables/Balances.sol | 8 +- .../modules/core/tables/FunctionSelectors.sol | 16 +-- .../src/modules/core/tables/ResourceType.sol | 8 +- .../src/modules/core/tables/SystemHooks.sol | 8 +- .../modules/core/tables/SystemRegistry.sol | 8 +- .../world/src/modules/core/tables/Systems.sol | 16 +-- .../keysintable/tables/KeysInTable.sol | 40 +++--- .../keysintable/tables/UsedKeysIndex.sol | 16 +-- .../keyswithvalue/tables/KeysWithValue.sol | 8 +- .../tables/CallboundDelegations.sol | 8 +- .../tables/TimeboundDelegations.sol | 8 +- .../uniqueentity/tables/UniqueEntity.sol | 8 +- packages/world/src/tables/Delegations.sol | 8 +- .../world/src/tables/InstalledModules.sol | 8 +- packages/world/src/tables/NamespaceOwner.sol | 8 +- packages/world/src/tables/ResourceAccess.sol | 8 +- packages/world/test/tables/AddressArray.sol | 8 +- packages/world/test/tables/Bool.sol | 8 +- .../contracts/src/codegen/tables/Counter.sol | 8 +- .../contracts/src/codegen/tables/Counter.sol | 8 +- .../contracts/src/codegen/tables/Position.sol | 24 ++-- .../contracts/src/codegen/tables/Counter.sol | 8 +- 47 files changed, 601 insertions(+), 449 deletions(-) create mode 100644 .changeset/sour-cycles-warn.md diff --git a/.changeset/sour-cycles-warn.md b/.changeset/sour-cycles-warn.md new file mode 100644 index 0000000000..1a79d508c5 --- /dev/null +++ b/.changeset/sour-cycles-warn.md @@ -0,0 +1,34 @@ +--- +"@latticexyz/cli": patch +"@latticexyz/store": minor +"@latticexyz/world": patch +--- + +`StoreCore` and `IStore` now expose specific functions for `getStaticField` and `getDynamicField` in addition to the general `getField`. +Using the specific functions reduces gas overhead because more optimized logic can be executed. + +```solidity +interface IStore { + /** + * Get a single static field from the given tableId and key tuple, with the given value field layout. + * Note: the field value is left-aligned in the returned bytes32, the rest of the word is not zeroed out. + * Consumers are expected to truncate the returned value as needed. + */ + function getStaticField( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint8 fieldIndex, + FieldLayout fieldLayout + ) external view returns (bytes32); + + /** + * Get a single dynamic field from the given tableId and key tuple at the given dynamic field index. + * (Dynamic field index = field index - number of static fields) + */ + function getDynamicField( + bytes32 tableId, + bytes32[] memory keyTuple, + uint8 dynamicFieldIndex + ) external view returns (bytes memory); +} +``` diff --git a/e2e/packages/contracts/src/codegen/tables/Multi.sol b/e2e/packages/contracts/src/codegen/tables/Multi.sol index 2f25c111dd..8b97411563 100644 --- a/e2e/packages/contracts/src/codegen/tables/Multi.sol +++ b/e2e/packages/contracts/src/codegen/tables/Multi.sol @@ -90,8 +90,8 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (int256(uint256(Bytes.slice32(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int256(uint256(bytes32(_blob)))); } /** Get num (using the specified store) */ @@ -102,8 +102,8 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (int256(uint256(Bytes.slice32(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int256(uint256(bytes32(_blob)))); } /** Set num */ @@ -136,8 +136,8 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Get value (using the specified store) */ @@ -148,8 +148,8 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Set value */ diff --git a/e2e/packages/contracts/src/codegen/tables/Number.sol b/e2e/packages/contracts/src/codegen/tables/Number.sol index 07eeb5619e..f5c62ae689 100644 --- a/e2e/packages/contracts/src/codegen/tables/Number.sol +++ b/e2e/packages/contracts/src/codegen/tables/Number.sol @@ -74,8 +74,8 @@ library Number { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Get value (using the specified store) */ @@ -83,8 +83,8 @@ library Number { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Set value */ diff --git a/e2e/packages/contracts/src/codegen/tables/NumberList.sol b/e2e/packages/contracts/src/codegen/tables/NumberList.sol index 0f26dba1a2..8f203ff4d0 100644 --- a/e2e/packages/contracts/src/codegen/tables/NumberList.sol +++ b/e2e/packages/contracts/src/codegen/tables/NumberList.sol @@ -71,7 +71,7 @@ library NumberList { function get() internal view returns (uint32[] memory value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -79,7 +79,7 @@ library NumberList { function get(IStore _store) internal view returns (uint32[] memory value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -133,7 +133,7 @@ library NumberList { _index * 4, (_index + 1) * 4 ); - return (uint32(Bytes.slice4(_blob, 0))); + return (uint32(bytes4(_blob))); } } @@ -146,7 +146,7 @@ library NumberList { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 4, (_index + 1) * 4); - return (uint32(Bytes.slice4(_blob, 0))); + return (uint32(bytes4(_blob))); } } diff --git a/e2e/packages/contracts/src/codegen/tables/Vector.sol b/e2e/packages/contracts/src/codegen/tables/Vector.sol index a7870c1a6c..a872229034 100644 --- a/e2e/packages/contracts/src/codegen/tables/Vector.sol +++ b/e2e/packages/contracts/src/codegen/tables/Vector.sol @@ -81,8 +81,8 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Get x (using the specified store) */ @@ -90,8 +90,8 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Set x */ @@ -115,8 +115,8 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Get y (using the specified store) */ @@ -124,8 +124,8 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Set y */ diff --git a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol index 04bf83b923..ec404deade 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol @@ -71,16 +71,16 @@ library CounterTable { function get() internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Get value (using the specified store) */ function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Set value */ diff --git a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol index 2fe128efd0..40b4913ac1 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol @@ -80,8 +80,8 @@ library Inventory { _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Get amount (using the specified store) */ @@ -91,8 +91,8 @@ library Inventory { _keyTuple[1] = bytes32(uint256(item)); _keyTuple[2] = bytes32(uint256(itemVariant)); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Set amount */ diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol index 9d96284463..b4b6f609cb 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol @@ -90,7 +90,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return toStaticArray_bytes32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -99,7 +99,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return toStaticArray_bytes32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -164,7 +164,7 @@ library Dynamics1 { _index * 32, (_index + 1) * 32 ); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -178,7 +178,7 @@ library Dynamics1 { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 32, (_index + 1) * 32); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -245,7 +245,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 1); return toStaticArray_int32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_int32()); } @@ -254,7 +254,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 1); return toStaticArray_int32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_int32()); } @@ -313,7 +313,7 @@ library Dynamics1 { _index * 4, (_index + 1) * 4 ); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + return (int32(uint32(bytes4(_blob)))); } } @@ -327,7 +327,7 @@ library Dynamics1 { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 1, _fieldLayout, _index * 4, (_index + 1) * 4); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + return (int32(uint32(bytes4(_blob)))); } } @@ -394,7 +394,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 2); return toStaticArray_uint128_3(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint128()); } @@ -403,7 +403,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 2); return toStaticArray_uint128_3(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint128()); } @@ -468,7 +468,7 @@ library Dynamics1 { _index * 16, (_index + 1) * 16 ); - return (uint128(Bytes.slice16(_blob, 0))); + return (uint128(bytes16(_blob))); } } @@ -482,7 +482,7 @@ library Dynamics1 { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 16, (_index + 1) * 16); - return (uint128(Bytes.slice16(_blob, 0))); + return (uint128(bytes16(_blob))); } } @@ -549,7 +549,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 3); return toStaticArray_address_4(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); } @@ -558,7 +558,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 3); return toStaticArray_address_4(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); } @@ -623,7 +623,7 @@ library Dynamics1 { _index * 20, (_index + 1) * 20 ); - return (address(Bytes.slice20(_blob, 0))); + return (address(bytes20(_blob))); } } @@ -637,7 +637,7 @@ library Dynamics1 { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 20, (_index + 1) * 20); - return (address(Bytes.slice20(_blob, 0))); + return (address(bytes20(_blob))); } } @@ -704,7 +704,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 4); return toStaticArray_bool_5(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bool()); } @@ -713,7 +713,7 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 4); return toStaticArray_bool_5(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bool()); } @@ -772,7 +772,7 @@ library Dynamics1 { _index * 1, (_index + 1) * 1 ); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + return (_toBool(uint8(bytes1(_blob)))); } } @@ -786,7 +786,7 @@ library Dynamics1 { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 4, _fieldLayout, _index * 1, (_index + 1) * 1); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + return (_toBool(uint8(bytes1(_blob)))); } } diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol index 2317c58515..59d39a2106 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol @@ -84,7 +84,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint64()); } @@ -93,7 +93,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint64()); } @@ -152,7 +152,7 @@ library Dynamics2 { _index * 8, (_index + 1) * 8 ); - return (uint64(Bytes.slice8(_blob, 0))); + return (uint64(bytes8(_blob))); } } @@ -166,7 +166,7 @@ library Dynamics2 { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 8, (_index + 1) * 8); - return (uint64(Bytes.slice8(_blob, 0))); + return (uint64(bytes8(_blob))); } } @@ -233,7 +233,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 1); return (string(_blob)); } @@ -242,7 +242,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 1); return (string(_blob)); } @@ -382,7 +382,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 2); return (bytes(_blob)); } @@ -391,7 +391,7 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 2); return (bytes(_blob)); } diff --git a/packages/cli/contracts/src/codegen/tables/Singleton.sol b/packages/cli/contracts/src/codegen/tables/Singleton.sol index d331c6eda3..90e1319b41 100644 --- a/packages/cli/contracts/src/codegen/tables/Singleton.sol +++ b/packages/cli/contracts/src/codegen/tables/Singleton.sol @@ -77,16 +77,16 @@ library Singleton { function getV1() internal view returns (int256 v1) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (int256(uint256(Bytes.slice32(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int256(uint256(bytes32(_blob)))); } /** Get v1 (using the specified store) */ function getV1(IStore _store) internal view returns (int256 v1) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (int256(uint256(Bytes.slice32(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int256(uint256(bytes32(_blob)))); } /** Set v1 */ @@ -107,7 +107,7 @@ library Singleton { function getV2() internal view returns (uint32[2] memory v2) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -115,7 +115,7 @@ library Singleton { function getV2(IStore _store) internal view returns (uint32[2] memory v2) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -169,7 +169,7 @@ library Singleton { _index * 4, (_index + 1) * 4 ); - return (uint32(Bytes.slice4(_blob, 0))); + return (uint32(bytes4(_blob))); } } @@ -182,7 +182,7 @@ library Singleton { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 1, _fieldLayout, _index * 4, (_index + 1) * 4); - return (uint32(Bytes.slice4(_blob, 0))); + return (uint32(bytes4(_blob))); } } @@ -242,7 +242,7 @@ library Singleton { function getV3() internal view returns (uint32[2] memory v3) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 1); return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -250,7 +250,7 @@ library Singleton { function getV3(IStore _store) internal view returns (uint32[2] memory v3) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 1); return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -304,7 +304,7 @@ library Singleton { _index * 4, (_index + 1) * 4 ); - return (uint32(Bytes.slice4(_blob, 0))); + return (uint32(bytes4(_blob))); } } @@ -317,7 +317,7 @@ library Singleton { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 4, (_index + 1) * 4); - return (uint32(Bytes.slice4(_blob, 0))); + return (uint32(bytes4(_blob))); } } @@ -377,7 +377,7 @@ library Singleton { function getV4() internal view returns (uint32[1] memory v4) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 2); return toStaticArray_uint32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -385,7 +385,7 @@ library Singleton { function getV4(IStore _store) internal view returns (uint32[1] memory v4) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 2); return toStaticArray_uint32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -439,7 +439,7 @@ library Singleton { _index * 4, (_index + 1) * 4 ); - return (uint32(Bytes.slice4(_blob, 0))); + return (uint32(bytes4(_blob))); } } @@ -452,7 +452,7 @@ library Singleton { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 4, (_index + 1) * 4); - return (uint32(Bytes.slice4(_blob, 0))); + return (uint32(bytes4(_blob))); } } diff --git a/packages/cli/contracts/src/codegen/tables/Statics.sol b/packages/cli/contracts/src/codegen/tables/Statics.sol index 14e42c5370..0f0376d429 100644 --- a/packages/cli/contracts/src/codegen/tables/Statics.sol +++ b/packages/cli/contracts/src/codegen/tables/Statics.sol @@ -111,8 +111,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint256(Bytes.slice32(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); } /** Get v1 (using the specified store) */ @@ -133,8 +133,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint256(Bytes.slice32(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); } /** Set v1 */ @@ -173,8 +173,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Get v2 (using the specified store) */ @@ -195,8 +195,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Set v2 */ @@ -235,8 +235,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); - return (Bytes.slice16(_blob, 0)); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); + return (bytes16(_blob)); } /** Get v3 (using the specified store) */ @@ -257,8 +257,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); - return (Bytes.slice16(_blob, 0)); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); + return (bytes16(_blob)); } /** Set v3 */ @@ -297,8 +297,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); - return (address(Bytes.slice20(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 3, _fieldLayout); + return (address(bytes20(_blob))); } /** Get v4 (using the specified store) */ @@ -319,8 +319,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); - return (address(Bytes.slice20(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 3, _fieldLayout); + return (address(bytes20(_blob))); } /** Set v4 */ @@ -359,8 +359,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 4, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Get v5 (using the specified store) */ @@ -381,8 +381,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 4, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Set v5 */ @@ -421,8 +421,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 5, _fieldLayout); - return Enum1(uint8(Bytes.slice1(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 5, _fieldLayout); + return Enum1(uint8(bytes1(_blob))); } /** Get v6 (using the specified store) */ @@ -443,8 +443,8 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 5, _fieldLayout); - return Enum1(uint8(Bytes.slice1(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 5, _fieldLayout); + return Enum1(uint8(bytes1(_blob))); } /** Set v6 */ diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 7ac2f7e9e6..c1ac85ebb5 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": 690015 + "gasUsed": 688555 }, { "file": "test/Mixed.t.sol", @@ -363,13 +363,13 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Mixed table", - "gasUsed": 551833 + "gasUsed": 550389 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 104922 + "gasUsed": 104102 }, { "file": "test/Mixed.t.sol", @@ -561,13 +561,13 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (cold, 1 slot)", - "gasUsed": 8281 + "gasUsed": 8282 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 1 slot)", - "gasUsed": 2349 + "gasUsed": 2350 }, { "file": "test/StoreCoreDynamic.t.sol", @@ -579,13 +579,13 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 2 slots)", - "gasUsed": 4580 + "gasUsed": 4579 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetSecondFieldLength", "name": "get field length (cold, 1 slot)", - "gasUsed": 7756 + "gasUsed": 7757 }, { "file": "test/StoreCoreDynamic.t.sol", @@ -609,49 +609,49 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 21297 + "gasUsed": 20433 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 15309 + "gasUsed": 14445 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 23493 + "gasUsed": 22629 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 15505 + "gasUsed": 14641 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access non-existing record", - "gasUsed": 6197 + "gasUsed": 6198 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access static field of non-existing record", - "gasUsed": 1357 + "gasUsed": 1318 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access dynamic field of non-existing record", - "gasUsed": 2090 + "gasUsed": 2045 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access length of dynamic field of non-existing record", - "gasUsed": 1120 + "gasUsed": 1121 }, { "file": "test/StoreCoreGas.t.sol", @@ -663,109 +663,109 @@ "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 7702 + "gasUsed": 6882 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "Check for existence of table (existent)", - "gasUsed": 2178 + "gasUsed": 1555 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "check for existence of table (non-existent)", - "gasUsed": 4180 + "gasUsed": 3556 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 59474 + "gasUsed": 58604 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 73142 + "gasUsed": 71502 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 22908 + "gasUsed": 21245 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 18460 + "gasUsed": 16797 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 59474 + "gasUsed": 58604 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 166238 + "gasUsed": 164598 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 26108 + "gasUsed": 24445 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 19445 + "gasUsed": 17782 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 13053 + "gasUsed": 12189 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 35807 + "gasUsed": 34943 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 613985 + "gasUsed": 612540 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get field layout (warm)", - "gasUsed": 2191 + "gasUsed": 1567 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get value schema (warm)", - "gasUsed": 2744 + "gasUsed": 2077 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get key schema (warm)", - "gasUsed": 4699 + "gasUsed": 3406 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 102843 + "gasUsed": 102022 }, { "file": "test/StoreCoreGas.t.sol", @@ -801,61 +801,61 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "reduce dynamic length of dynamic index 0", - "gasUsed": 961 + "gasUsed": 960 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 32564 + "gasUsed": 31744 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (1 slot)", - "gasUsed": 1357 + "gasUsed": 1318 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 31204 + "gasUsed": 30384 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (overlap 2 slot)", - "gasUsed": 1883 + "gasUsed": 1844 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 54090 + "gasUsed": 53269 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, first dynamic field)", - "gasUsed": 2258 + "gasUsed": 2214 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 32317 + "gasUsed": 31496 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, second dynamic field)", - "gasUsed": 2260 + "gasUsed": 2216 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 33148 + "gasUsed": 32328 }, { "file": "test/StoreCoreGas.t.sol", @@ -867,7 +867,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 55652 + "gasUsed": 54832 }, { "file": "test/StoreCoreGas.t.sol", @@ -879,13 +879,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 14090 + "gasUsed": 13227 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 14894 + "gasUsed": 14029 }, { "file": "test/StoreHook.t.sol", @@ -933,103 +933,103 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 57164 + "gasUsed": 56344 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: get field (warm)", - "gasUsed": 3732 + "gasUsed": 2912 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 36119 + "gasUsed": 35254 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 59162 + "gasUsed": 58342 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 59162 + "gasUsed": 58342 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: get field (warm)", - "gasUsed": 3716 + "gasUsed": 2896 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 16205 + "gasUsed": 15341 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 12760 + "gasUsed": 11896 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 14231 + "gasUsed": 13367 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 35329 + "gasUsed": 34465 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 8113 + "gasUsed": 7293 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 31324 + "gasUsed": 30504 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 81853 + "gasUsed": 81033 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 81764 + "gasUsed": 80944 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 16978 + "gasUsed": 16158 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGet", "name": "StoreHooks: get field (cold)", - "gasUsed": 9713 + "gasUsed": 8893 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGetItem", "name": "StoreHooks: get 1 element (cold)", - "gasUsed": 6440 + "gasUsed": 6521 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", @@ -1041,13 +1041,13 @@ "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 23246 + "gasUsed": 22382 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 25382 + "gasUsed": 24518 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -1101,13 +1101,13 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 413256 + "gasUsed": 411812 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 34051 + "gasUsed": 33231 }, { "file": "test/Vector2.t.sol", diff --git a/packages/store/src/IStore.sol b/packages/store/src/IStore.sol index 95bf0e301f..052195b0bc 100644 --- a/packages/store/src/IStore.sol +++ b/packages/store/src/IStore.sol @@ -14,14 +14,18 @@ interface IStoreRead { function getKeySchema(bytes32 tableId) external view returns (Schema keySchema); - // Get full record (including full array) + /** + * Get full record (all fields, static and dynamic data) for the given tableId and key tuple, with the given value field layout + */ function getRecord( bytes32 tableId, bytes32[] calldata keyTuple, FieldLayout fieldLayout ) external view returns (bytes memory data); - // Get partial data at schema index + /** + * Get a single field from the given tableId and key tuple, with the given value field layout + */ function getField( bytes32 tableId, bytes32[] calldata keyTuple, @@ -29,7 +33,31 @@ interface IStoreRead { FieldLayout fieldLayout ) external view returns (bytes memory data); - // Get field length at schema index + /** + * Get a single static field from the given tableId and key tuple, with the given value field layout. + * Note: the field value is left-aligned in the returned bytes32, the rest of the word is not zeroed out. + * Consumers are expected to truncate the returned value as needed. + */ + function getStaticField( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint8 fieldIndex, + FieldLayout fieldLayout + ) external view returns (bytes32); + + /** + * Get a single dynamic field from the given tableId and key tuple at the given dynamic field index. + * (Dynamic field index = field index - number of static fields) + */ + function getDynamicField( + bytes32 tableId, + bytes32[] memory keyTuple, + uint8 dynamicFieldIndex + ) external view returns (bytes memory); + + /** + * Get the byte length of a single field from the given tableId and key tuple, with the given value field layout + */ function getFieldLength( bytes32 tableId, bytes32[] memory keyTuple, @@ -37,7 +65,10 @@ interface IStoreRead { FieldLayout fieldLayout ) external view returns (uint256); - // Get start:end slice of the field at schema index + /** + * Get a byte slice (including start, excluding end) of a single dynamic field from the given tableId and key tuple, with the given value field layout. + * The slice is unchecked and will return invalid data if `start`:`end` overflow. + */ function getFieldSlice( bytes32 tableId, bytes32[] memory keyTuple, diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index f752e7e7c9..684c834c42 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -358,7 +358,7 @@ library StoreCore { // TODO add push-specific hook to avoid the storage read? (https://github.com/latticexyz/mud/issues/444) bytes memory fullData = abi.encodePacked( - StoreCoreInternal._getDynamicField(tableId, keyTuple, fieldIndex, fieldLayout), + getDynamicField(tableId, keyTuple, fieldIndex - uint8(fieldLayout.numStaticFields())), dataToPush ); @@ -399,7 +399,7 @@ library StoreCore { // TODO add pop-specific hook to avoid the storage read? (https://github.com/latticexyz/mud/issues/444) bytes memory fullData; { - bytes memory oldData = StoreCoreInternal._getDynamicField(tableId, keyTuple, fieldIndex, fieldLayout); + bytes memory oldData = getDynamicField(tableId, keyTuple, fieldIndex - uint8(fieldLayout.numStaticFields())); fullData = SliceLib.getSubslice(oldData, 0, oldData.length - byteLengthToPop).toBytes(); } @@ -447,7 +447,7 @@ library StoreCore { // TODO add setItem-specific hook to avoid the storage read? (https://github.com/latticexyz/mud/issues/444) bytes memory fullData; { - bytes memory oldData = StoreCoreInternal._getDynamicField(tableId, keyTuple, fieldIndex, fieldLayout); + bytes memory oldData = getDynamicField(tableId, keyTuple, fieldIndex - uint8(fieldLayout.numStaticFields())); fullData = abi.encodePacked( SliceLib.getSubslice(oldData, 0, startByteIndex).toBytes(), dataToSet, @@ -572,12 +572,51 @@ library StoreCore { FieldLayout fieldLayout ) internal view returns (bytes memory) { if (fieldIndex < fieldLayout.numStaticFields()) { - return StoreCoreInternal._getStaticField(tableId, keyTuple, fieldIndex, fieldLayout); + return StoreCoreInternal._getStaticFieldBytes(tableId, keyTuple, fieldIndex, fieldLayout); } else { - return StoreCoreInternal._getDynamicField(tableId, keyTuple, fieldIndex, fieldLayout); + return getDynamicField(tableId, keyTuple, fieldIndex - uint8(fieldLayout.numStaticFields())); } } + /** + * Get a single static field from the given tableId and key tuple, with the given value field layout. + * Note: the field value is left-aligned in the returned bytes32, the rest of the word is not zeroed out. + * Consumers are expected to truncate the returned value as needed. + */ + function getStaticField( + bytes32 tableId, + bytes32[] memory keyTuple, + uint8 fieldIndex, + FieldLayout fieldLayout + ) internal view returns (bytes32) { + // Get the length, storage location and offset of the static field + // and load the data from storage + return + Storage.loadField({ + storagePointer: StoreCoreInternal._getStaticDataLocation(tableId, keyTuple), + length: fieldLayout.atIndex(fieldIndex), + offset: StoreCoreInternal._getStaticDataOffset(fieldLayout, fieldIndex) + }); + } + + /** + * Get a single dynamic field from the given tableId and key tuple, with the given value field layout + */ + function getDynamicField( + bytes32 tableId, + bytes32[] memory keyTuple, + uint8 dynamicFieldIndex + ) internal view returns (bytes memory) { + // Get the storage location of the dynamic field + // and load the data from storage + return + Storage.load({ + storagePointer: StoreCoreInternal._getDynamicDataLocation(tableId, keyTuple, dynamicFieldIndex), + length: StoreCoreInternal._loadEncodedDynamicDataLength(tableId, keyTuple).atIndex(dynamicFieldIndex), + offset: 0 + }); + } + /** * Get the byte length of a single field from the given tableId and key tuple, with the given value field layout */ @@ -848,38 +887,23 @@ library StoreCoreInternal { } /** - * Get a single static field from the given tableId and key tuple, with the given value field layout + * Get a single static field from the given tableId and key tuple, with the given value field layout. + * Returns dynamic bytes memory in the size of the field. */ - function _getStaticField( + function _getStaticFieldBytes( bytes32 tableId, bytes32[] memory keyTuple, uint8 fieldIndex, FieldLayout fieldLayout ) internal view returns (bytes memory) { // Get the length, storage location and offset of the static field - uint256 staticByteLength = fieldLayout.atIndex(fieldIndex); - uint256 location = _getStaticDataLocation(tableId, keyTuple); - uint256 offset = _getStaticDataOffset(fieldLayout, fieldIndex); - - // Load the data from storage - return Storage.load({ storagePointer: location, length: staticByteLength, offset: offset }); - } - - /** - * Get a single dynamic field from the given tableId and key tuple, with the given value field layout - */ - function _getDynamicField( - bytes32 tableId, - bytes32[] memory keyTuple, - uint8 fieldIndex, - FieldLayout fieldLayout - ) internal view returns (bytes memory) { - // Get the length and storage location of the dynamic field - uint8 dynamicSchemaIndex = fieldIndex - uint8(fieldLayout.numStaticFields()); - uint256 location = _getDynamicDataLocation(tableId, keyTuple, dynamicSchemaIndex); - uint256 dataLength = _loadEncodedDynamicDataLength(tableId, keyTuple).atIndex(dynamicSchemaIndex); - - return Storage.load({ storagePointer: location, length: dataLength, offset: 0 }); + // and load the data from storage + return + Storage.load({ + storagePointer: StoreCoreInternal._getStaticDataLocation(tableId, keyTuple), + length: fieldLayout.atIndex(fieldIndex), + offset: StoreCoreInternal._getStaticDataOffset(fieldLayout, fieldIndex) + }); } /************************************************************************ diff --git a/packages/store/src/StoreRead.sol b/packages/store/src/StoreRead.sol index 92125f5bd0..3017f1510f 100644 --- a/packages/store/src/StoreRead.sol +++ b/packages/store/src/StoreRead.sol @@ -19,7 +19,6 @@ contract StoreRead is IStoreRead { keySchema = StoreCore.getKeySchema(tableId); } - // Get full record (static and dynamic data) function getRecord( bytes32 tableId, bytes32[] calldata keyTuple, @@ -28,7 +27,6 @@ contract StoreRead is IStoreRead { data = StoreCore.getRecord(tableId, keyTuple, fieldLayout); } - // Get partial data at schema index function getField( bytes32 tableId, bytes32[] calldata keyTuple, @@ -38,6 +36,23 @@ contract StoreRead is IStoreRead { data = StoreCore.getField(tableId, keyTuple, fieldIndex, fieldLayout); } + function getStaticField( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint8 fieldIndex, + FieldLayout fieldLayout + ) public view virtual returns (bytes32 data) { + data = StoreCore.getStaticField(tableId, keyTuple, fieldIndex, fieldLayout); + } + + function getDynamicField( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint8 dynamicFieldIndex + ) public view virtual returns (bytes memory data) { + data = StoreCore.getDynamicField(tableId, keyTuple, dynamicFieldIndex); + } + function getFieldLength( bytes32 tableId, bytes32[] memory keyTuple, diff --git a/packages/store/src/StoreSwitch.sol b/packages/store/src/StoreSwitch.sol index ed3e243b0e..412d34bc5b 100644 --- a/packages/store/src/StoreSwitch.sol +++ b/packages/store/src/StoreSwitch.sol @@ -244,6 +244,33 @@ library StoreSwitch { } } + function getStaticField( + bytes32 tableId, + bytes32[] memory keyTuple, + uint8 fieldIndex, + FieldLayout fieldLayout + ) internal view returns (bytes32) { + address _storeAddress = getStoreAddress(); + if (_storeAddress == address(this)) { + return StoreCore.getStaticField(tableId, keyTuple, fieldIndex, fieldLayout); + } else { + return IStore(_storeAddress).getStaticField(tableId, keyTuple, fieldIndex, fieldLayout); + } + } + + function getDynamicField( + bytes32 tableId, + bytes32[] memory keyTuple, + uint8 dynamicFieldIndex + ) internal view returns (bytes memory) { + address _storeAddress = getStoreAddress(); + if (_storeAddress == address(this)) { + return StoreCore.getDynamicField(tableId, keyTuple, dynamicFieldIndex); + } else { + return IStore(_storeAddress).getDynamicField(tableId, keyTuple, dynamicFieldIndex); + } + } + function getFieldLength( bytes32 tableId, bytes32[] memory keyTuple, diff --git a/packages/store/src/codegen/tables/Callbacks.sol b/packages/store/src/codegen/tables/Callbacks.sol index 8d9b02a251..cbe5d850c5 100644 --- a/packages/store/src/codegen/tables/Callbacks.sol +++ b/packages/store/src/codegen/tables/Callbacks.sol @@ -74,7 +74,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes24()); } @@ -83,7 +83,7 @@ library Callbacks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes24()); } @@ -142,7 +142,7 @@ library Callbacks { _index * 24, (_index + 1) * 24 ); - return (Bytes.slice24(_blob, 0)); + return (bytes24(_blob)); } } @@ -156,7 +156,7 @@ library Callbacks { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 24, (_index + 1) * 24); - return (Bytes.slice24(_blob, 0)); + return (bytes24(_blob)); } } diff --git a/packages/store/src/codegen/tables/Hooks.sol b/packages/store/src/codegen/tables/Hooks.sol index 3332c321e4..d01e5b05e0 100644 --- a/packages/store/src/codegen/tables/Hooks.sol +++ b/packages/store/src/codegen/tables/Hooks.sol @@ -71,7 +71,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -80,7 +80,7 @@ library Hooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -139,7 +139,7 @@ library Hooks { _index * 21, (_index + 1) * 21 ); - return (Bytes.slice21(_blob, 0)); + return (bytes21(_blob)); } } @@ -153,7 +153,7 @@ library Hooks { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 21, (_index + 1) * 21); - return (Bytes.slice21(_blob, 0)); + return (bytes21(_blob)); } } diff --git a/packages/store/src/codegen/tables/KeyEncoding.sol b/packages/store/src/codegen/tables/KeyEncoding.sol index b23620d632..78d705bf2d 100644 --- a/packages/store/src/codegen/tables/KeyEncoding.sol +++ b/packages/store/src/codegen/tables/KeyEncoding.sol @@ -99,8 +99,8 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Get value (using the specified store) */ @@ -121,8 +121,8 @@ library KeyEncoding { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Set value */ diff --git a/packages/store/src/codegen/tables/Mixed.sol b/packages/store/src/codegen/tables/Mixed.sol index d6060d0c95..13f6d12dfd 100644 --- a/packages/store/src/codegen/tables/Mixed.sol +++ b/packages/store/src/codegen/tables/Mixed.sol @@ -87,8 +87,8 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Get u32 (using the specified store) */ @@ -96,8 +96,8 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Set u32 */ @@ -121,8 +121,8 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (uint128(Bytes.slice16(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint128(bytes16(_blob))); } /** Get u128 (using the specified store) */ @@ -130,8 +130,8 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (uint128(Bytes.slice16(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint128(bytes16(_blob))); } /** Set u128 */ @@ -155,7 +155,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -164,7 +164,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } @@ -223,7 +223,7 @@ library Mixed { _index * 4, (_index + 1) * 4 ); - return (uint32(Bytes.slice4(_blob, 0))); + return (uint32(bytes4(_blob))); } } @@ -237,7 +237,7 @@ library Mixed { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 4, (_index + 1) * 4); - return (uint32(Bytes.slice4(_blob, 0))); + return (uint32(bytes4(_blob))); } } @@ -304,7 +304,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 1); return (string(_blob)); } @@ -313,7 +313,7 @@ library Mixed { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 1); return (string(_blob)); } diff --git a/packages/store/src/codegen/tables/StoreHooks.sol b/packages/store/src/codegen/tables/StoreHooks.sol index e997c1a4f9..a2632c0b20 100644 --- a/packages/store/src/codegen/tables/StoreHooks.sol +++ b/packages/store/src/codegen/tables/StoreHooks.sol @@ -74,7 +74,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -83,7 +83,7 @@ library StoreHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -142,7 +142,7 @@ library StoreHooks { _index * 21, (_index + 1) * 21 ); - return (Bytes.slice21(_blob, 0)); + return (bytes21(_blob)); } } @@ -156,7 +156,7 @@ library StoreHooks { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 21, (_index + 1) * 21); - return (Bytes.slice21(_blob, 0)); + return (bytes21(_blob)); } } diff --git a/packages/store/src/codegen/tables/Tables.sol b/packages/store/src/codegen/tables/Tables.sol index b3e553b585..6204d3de73 100644 --- a/packages/store/src/codegen/tables/Tables.sol +++ b/packages/store/src/codegen/tables/Tables.sol @@ -90,8 +90,8 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); } /** Get fieldLayout (using the specified store) */ @@ -99,8 +99,8 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); } /** Set fieldLayout */ @@ -124,8 +124,8 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (bytes32(_blob)); } /** Get keySchema (using the specified store) */ @@ -133,8 +133,8 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (bytes32(_blob)); } /** Set keySchema */ @@ -158,8 +158,8 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); + return (bytes32(_blob)); } /** Get valueSchema (using the specified store) */ @@ -167,8 +167,8 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); + return (bytes32(_blob)); } /** Set valueSchema */ @@ -192,7 +192,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (bytes(_blob)); } @@ -204,7 +204,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (bytes(_blob)); } @@ -348,7 +348,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 1); return (bytes(_blob)); } @@ -360,7 +360,7 @@ library Tables { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = tableId; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 1); return (bytes(_blob)); } diff --git a/packages/store/src/codegen/tables/Vector2.sol b/packages/store/src/codegen/tables/Vector2.sol index 9c1f7cbea1..d7694660eb 100644 --- a/packages/store/src/codegen/tables/Vector2.sol +++ b/packages/store/src/codegen/tables/Vector2.sol @@ -81,8 +81,8 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Get x (using the specified store) */ @@ -90,8 +90,8 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Set x */ @@ -115,8 +115,8 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Get y (using the specified store) */ @@ -124,8 +124,8 @@ library Vector2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Set y */ diff --git a/packages/store/ts/codegen/field.ts b/packages/store/ts/codegen/field.ts index 5d1c3bdf81..e63ad43f2d 100644 --- a/packages/store/ts/codegen/field.ts +++ b/packages/store/ts/codegen/field.ts @@ -13,6 +13,8 @@ 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 + const _typedFieldName = `${field.typeWithLocation} ${field.name}`; result += renderWithStore( @@ -25,7 +27,20 @@ export function renderFieldMethods(options: RenderTableOptions) { _typedKeyArgs, ])}) internal view returns (${_typedFieldName}) { ${_keyTupleDefinition} - bytes memory _blob = ${_store}.getField(_tableId, _keyTuple, ${schemaIndex}, _fieldLayout); + ${ + field.isDynamic + ? `bytes memory _blob = ${_store}.getDynamicField( + _tableId, + _keyTuple, + ${schemaIndex - options.staticFields.length} + );` + : `bytes32 _blob = ${_store}.getStaticField( + _tableId, + _keyTuple, + ${schemaIndex}, + _fieldLayout + );` + } return ${renderDecodeFieldSingle(field)}; } ` @@ -174,20 +189,26 @@ export function renderEncodeFieldSingle(field: RenderField) { } export function renderDecodeValueType(field: RenderType, offset: number) { - const { staticByteLength, internalTypeId } = field; + const { staticByteLength } = field; const innerSlice = `Bytes.slice${staticByteLength}(_blob, ${offset})`; + + return renderCastStaticBytesToType(field, innerSlice); +} + +function renderCastStaticBytesToType(field: RenderType, staticBytes: string) { + const { staticByteLength, internalTypeId } = field; const bits = staticByteLength * 8; let result; if (internalTypeId.match(/^uint\d{1,3}$/) || internalTypeId === "address") { - result = `${internalTypeId}(${innerSlice})`; + result = `${internalTypeId}(${staticBytes})`; } else if (internalTypeId.match(/^int\d{1,3}$/)) { - result = `${internalTypeId}(uint${bits}(${innerSlice}))`; + result = `${internalTypeId}(uint${bits}(${staticBytes}))`; } else if (internalTypeId.match(/^bytes\d{1,2}$/)) { - result = innerSlice; + result = staticBytes; } else if (internalTypeId === "bool") { - result = `_toBool(uint8(${innerSlice}))`; + result = `_toBool(uint8(${staticBytes}))`; } else { throw new Error(`Unknown value type id ${internalTypeId}`); } @@ -233,6 +254,6 @@ function renderDecodeFieldSingle(field: RenderField) { // bytes/string return `${field.typeWrap}(${field.internalTypeId}(_blob))`; } else { - return renderDecodeValueType(field, 0); + return renderCastStaticBytesToType(field, `bytes${field.staticByteLength}(_blob)`); } } diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 7775787446..1568db80f3 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -3,31 +3,31 @@ "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (cold)", - "gasUsed": 10667 + "gasUsed": 9514 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm, namespace only)", - "gasUsed": 2408 + "gasUsed": 1829 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm)", - "gasUsed": 4689 + "gasUsed": 3534 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (cold)", - "gasUsed": 10709 + "gasUsed": 9556 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (warm)", - "gasUsed": 4713 + "gasUsed": 3559 }, { "file": "test/AccessControl.t.sol", @@ -39,73 +39,73 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1443420 + "gasUsed": 1425069 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1443420 + "gasUsed": 1425069 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 167906 + "gasUsed": 161043 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1443420 + "gasUsed": 1425069 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1443420 + "gasUsed": 1425069 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 25326 + "gasUsed": 22513 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 195723 + "gasUsed": 178377 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1443420 + "gasUsed": 1425069 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 24049 + "gasUsed": 21235 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 101263 + "gasUsed": 91846 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 674478 + "gasUsed": 661189 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "Get list of keys with a given value", - "gasUsed": 6170 + "gasUsed": 5351 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,264 +117,264 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 674478 + "gasUsed": 661189 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 142864 + "gasUsed": 136579 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 674478 + "gasUsed": 661189 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 112442 + "gasUsed": 106157 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 38443 + "gasUsed": 34216 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 674478 + "gasUsed": 661189 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 147478 + "gasUsed": 141193 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 112237 + "gasUsed": 105952 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 109103 + "gasUsed": 103370 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 55818 + "gasUsed": 52259 }, { "file": "test/query.t.sol", "test": "testCombinedHasNotQuery", "name": "CombinedHasNotQuery", - "gasUsed": 135801 + "gasUsed": 130426 }, { "file": "test/query.t.sol", "test": "testCombinedHasQuery", "name": "CombinedHasQuery", - "gasUsed": 87885 + "gasUsed": 83357 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 88206 + "gasUsed": 84121 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueQuery", "name": "CombinedHasValueQuery", - "gasUsed": 16614 + "gasUsed": 14966 }, { "file": "test/query.t.sol", "test": "testHasQuery", "name": "HasQuery", - "gasUsed": 19725 + "gasUsed": 18578 }, { "file": "test/query.t.sol", "test": "testHasQuery1000Keys", "name": "HasQuery with 1000 keys", - "gasUsed": 5843418 + "gasUsed": 5902151 }, { "file": "test/query.t.sol", "test": "testHasQuery100Keys", "name": "HasQuery with 100 keys", - "gasUsed": 546112 + "gasUsed": 550845 }, { "file": "test/query.t.sol", "test": "testHasValueQuery", "name": "HasValueQuery", - "gasUsed": 7978 + "gasUsed": 7154 }, { "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 49414 + "gasUsed": 45855 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 118637 + "gasUsed": 116017 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 37881 + "gasUsed": 35016 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 112991 + "gasUsed": 110371 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 29993 + "gasUsed": 27946 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 712299 + "gasUsed": 693352 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 56214 + "gasUsed": 52577 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 699545 + "gasUsed": 680858 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 56214 + "gasUsed": 52577 }, { "file": "test/World.t.sol", "test": "testCall", "name": "call a system via the World", - "gasUsed": 14602 + "gasUsed": 13196 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 50997 + "gasUsed": 49345 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "call a system via an unlimited delegation", - "gasUsed": 15010 + "gasUsed": 13590 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 10744 + "gasUsed": 9343 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 90191 + "gasUsed": 88725 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 63739 + "gasUsed": 60882 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 56989 + "gasUsed": 54136 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 84333 + "gasUsed": 81476 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 131214 + "gasUsed": 127343 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 78907 + "gasUsed": 76054 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 655916 + "gasUsed": 648531 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 39031 + "gasUsed": 37631 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 37025 + "gasUsed": 35625 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 29349 + "gasUsed": 27929 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 16462 + "gasUsed": 15042 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 32728 + "gasUsed": 31284 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 19933 + "gasUsed": 18489 } ] diff --git a/packages/world/src/modules/core/tables/Balances.sol b/packages/world/src/modules/core/tables/Balances.sol index ac0cada199..280b77ae71 100644 --- a/packages/world/src/modules/core/tables/Balances.sol +++ b/packages/world/src/modules/core/tables/Balances.sol @@ -74,8 +74,8 @@ library Balances { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint256(Bytes.slice32(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); } /** Get balance (using the specified store) */ @@ -83,8 +83,8 @@ library Balances { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint256(Bytes.slice32(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); } /** Set balance */ diff --git a/packages/world/src/modules/core/tables/FunctionSelectors.sol b/packages/world/src/modules/core/tables/FunctionSelectors.sol index f679ed4e18..28ee846849 100644 --- a/packages/world/src/modules/core/tables/FunctionSelectors.sol +++ b/packages/world/src/modules/core/tables/FunctionSelectors.sol @@ -76,8 +76,8 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); } /** Get resourceSelector (using the specified store) */ @@ -88,8 +88,8 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); } /** Set resourceSelector */ @@ -113,8 +113,8 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (Bytes.slice4(_blob, 0)); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (bytes4(_blob)); } /** Get systemFunctionSelector (using the specified store) */ @@ -125,8 +125,8 @@ library FunctionSelectors { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(functionSelector); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (Bytes.slice4(_blob, 0)); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (bytes4(_blob)); } /** Set systemFunctionSelector */ diff --git a/packages/world/src/modules/core/tables/ResourceType.sol b/packages/world/src/modules/core/tables/ResourceType.sol index 1d56109aa6..4dd272567b 100644 --- a/packages/world/src/modules/core/tables/ResourceType.sol +++ b/packages/world/src/modules/core/tables/ResourceType.sol @@ -77,8 +77,8 @@ library ResourceType { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return Resource(uint8(Bytes.slice1(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return Resource(uint8(bytes1(_blob))); } /** Get resourceType (using the specified store) */ @@ -86,8 +86,8 @@ library ResourceType { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return Resource(uint8(Bytes.slice1(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return Resource(uint8(bytes1(_blob))); } /** Set resourceType */ diff --git a/packages/world/src/modules/core/tables/SystemHooks.sol b/packages/world/src/modules/core/tables/SystemHooks.sol index 8ea6e2b31b..1314088f74 100644 --- a/packages/world/src/modules/core/tables/SystemHooks.sol +++ b/packages/world/src/modules/core/tables/SystemHooks.sol @@ -74,7 +74,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -83,7 +83,7 @@ library SystemHooks { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } @@ -142,7 +142,7 @@ library SystemHooks { _index * 21, (_index + 1) * 21 ); - return (Bytes.slice21(_blob, 0)); + return (bytes21(_blob)); } } @@ -156,7 +156,7 @@ library SystemHooks { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 21, (_index + 1) * 21); - return (Bytes.slice21(_blob, 0)); + return (bytes21(_blob)); } } diff --git a/packages/world/src/modules/core/tables/SystemRegistry.sol b/packages/world/src/modules/core/tables/SystemRegistry.sol index 4a83e64bec..e27e2fdd95 100644 --- a/packages/world/src/modules/core/tables/SystemRegistry.sol +++ b/packages/world/src/modules/core/tables/SystemRegistry.sol @@ -74,8 +74,8 @@ library SystemRegistry { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); } /** Get resourceSelector (using the specified store) */ @@ -83,8 +83,8 @@ library SystemRegistry { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(uint160(system))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); } /** Set resourceSelector */ diff --git a/packages/world/src/modules/core/tables/Systems.sol b/packages/world/src/modules/core/tables/Systems.sol index 1316f4331a..edffc1d222 100644 --- a/packages/world/src/modules/core/tables/Systems.sol +++ b/packages/world/src/modules/core/tables/Systems.sol @@ -76,8 +76,8 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (address(Bytes.slice20(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (address(bytes20(_blob))); } /** Get system (using the specified store) */ @@ -85,8 +85,8 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (address(Bytes.slice20(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (address(bytes20(_blob))); } /** Set system */ @@ -110,8 +110,8 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Get publicAccess (using the specified store) */ @@ -119,8 +119,8 @@ library Systems { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = resourceSelector; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Set publicAccess */ diff --git a/packages/world/src/modules/keysintable/tables/KeysInTable.sol b/packages/world/src/modules/keysintable/tables/KeysInTable.sol index 589642c66c..c18a7915d5 100644 --- a/packages/world/src/modules/keysintable/tables/KeysInTable.sol +++ b/packages/world/src/modules/keysintable/tables/KeysInTable.sol @@ -90,7 +90,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -99,7 +99,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -158,7 +158,7 @@ library KeysInTable { _index * 32, (_index + 1) * 32 ); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -172,7 +172,7 @@ library KeysInTable { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 32, (_index + 1) * 32); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -239,7 +239,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 1); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -248,7 +248,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 1); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -307,7 +307,7 @@ library KeysInTable { _index * 32, (_index + 1) * 32 ); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -321,7 +321,7 @@ library KeysInTable { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 1, _fieldLayout, _index * 32, (_index + 1) * 32); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -388,7 +388,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 2); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -397,7 +397,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 2); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -456,7 +456,7 @@ library KeysInTable { _index * 32, (_index + 1) * 32 ); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -470,7 +470,7 @@ library KeysInTable { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 32, (_index + 1) * 32); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -537,7 +537,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 3, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 3); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -546,7 +546,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 3, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 3); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -605,7 +605,7 @@ library KeysInTable { _index * 32, (_index + 1) * 32 ); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -619,7 +619,7 @@ library KeysInTable { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 32, (_index + 1) * 32); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -686,7 +686,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 4, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 4); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -695,7 +695,7 @@ library KeysInTable { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = sourceTable; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 4, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 4); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -754,7 +754,7 @@ library KeysInTable { _index * 32, (_index + 1) * 32 ); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -768,7 +768,7 @@ library KeysInTable { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 4, _fieldLayout, _index * 32, (_index + 1) * 32); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } diff --git a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol index a0ebf6dea2..a0ab8dc9fd 100644 --- a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol +++ b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol @@ -79,8 +79,8 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Get has (using the specified store) */ @@ -89,8 +89,8 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Set has */ @@ -117,8 +117,8 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (uint40(Bytes.slice5(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint40(bytes5(_blob))); } /** Get index (using the specified store) */ @@ -127,8 +127,8 @@ library UsedKeysIndex { _keyTuple[0] = sourceTable; _keyTuple[1] = keysHash; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (uint40(Bytes.slice5(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint40(bytes5(_blob))); } /** Set index */ diff --git a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol index 47b0af5076..9255f04f3f 100644 --- a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol +++ b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol @@ -71,7 +71,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -84,7 +84,7 @@ library KeysWithValue { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = valueHash; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } @@ -143,7 +143,7 @@ library KeysWithValue { _index * 32, (_index + 1) * 32 ); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } @@ -157,7 +157,7 @@ library KeysWithValue { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 32, (_index + 1) * 32); - return (Bytes.slice32(_blob, 0)); + return (bytes32(_blob)); } } diff --git a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol index 0cb37a05be..54d2f15682 100644 --- a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol @@ -88,8 +88,8 @@ library CallboundDelegations { _keyTuple[2] = resourceSelector; _keyTuple[3] = funcSelectorAndArgsHash; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint256(Bytes.slice32(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); } /** Get availableCalls (using the specified store) */ @@ -106,8 +106,8 @@ library CallboundDelegations { _keyTuple[2] = resourceSelector; _keyTuple[3] = funcSelectorAndArgsHash; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint256(Bytes.slice32(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); } /** Set availableCalls */ diff --git a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol index 4fc2762cee..f751ad7f14 100644 --- a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol @@ -77,8 +77,8 @@ library TimeboundDelegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint256(Bytes.slice32(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); } /** Get maxTimestamp (using the specified store) */ @@ -87,8 +87,8 @@ library TimeboundDelegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint256(Bytes.slice32(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); } /** Set maxTimestamp */ diff --git a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol index a3e4568034..a47b78e150 100644 --- a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol +++ b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol @@ -68,16 +68,16 @@ library UniqueEntity { function get(bytes32 _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint256(Bytes.slice32(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); } /** Get value (using the specified store) */ function get(IStore _store, bytes32 _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint256(Bytes.slice32(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); } /** Set value */ diff --git a/packages/world/src/tables/Delegations.sol b/packages/world/src/tables/Delegations.sol index 5bdb511112..2e0378a220 100644 --- a/packages/world/src/tables/Delegations.sol +++ b/packages/world/src/tables/Delegations.sol @@ -77,8 +77,8 @@ library Delegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); } /** Get delegationControlId (using the specified store) */ @@ -91,8 +91,8 @@ library Delegations { _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (Bytes.slice32(_blob, 0)); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); } /** Set delegationControlId */ diff --git a/packages/world/src/tables/InstalledModules.sol b/packages/world/src/tables/InstalledModules.sol index 637770c6b9..b89b19bb88 100644 --- a/packages/world/src/tables/InstalledModules.sol +++ b/packages/world/src/tables/InstalledModules.sol @@ -77,8 +77,8 @@ library InstalledModules { _keyTuple[0] = bytes32(moduleName); _keyTuple[1] = argumentsHash; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (address(Bytes.slice20(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (address(bytes20(_blob))); } /** Get moduleAddress (using the specified store) */ @@ -87,8 +87,8 @@ library InstalledModules { _keyTuple[0] = bytes32(moduleName); _keyTuple[1] = argumentsHash; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (address(Bytes.slice20(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (address(bytes20(_blob))); } /** Set moduleAddress */ diff --git a/packages/world/src/tables/NamespaceOwner.sol b/packages/world/src/tables/NamespaceOwner.sol index d290e3fcab..10f34300f2 100644 --- a/packages/world/src/tables/NamespaceOwner.sol +++ b/packages/world/src/tables/NamespaceOwner.sol @@ -74,8 +74,8 @@ library NamespaceOwner { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (address(Bytes.slice20(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (address(bytes20(_blob))); } /** Get owner (using the specified store) */ @@ -83,8 +83,8 @@ library NamespaceOwner { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(namespace); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (address(Bytes.slice20(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (address(bytes20(_blob))); } /** Set owner */ diff --git a/packages/world/src/tables/ResourceAccess.sol b/packages/world/src/tables/ResourceAccess.sol index 1e6b75690b..56ce7e7616 100644 --- a/packages/world/src/tables/ResourceAccess.sol +++ b/packages/world/src/tables/ResourceAccess.sol @@ -77,8 +77,8 @@ library ResourceAccess { _keyTuple[0] = resourceSelector; _keyTuple[1] = bytes32(uint256(uint160(caller))); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Get access (using the specified store) */ @@ -87,8 +87,8 @@ library ResourceAccess { _keyTuple[0] = resourceSelector; _keyTuple[1] = bytes32(uint256(uint160(caller))); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Set access */ diff --git a/packages/world/test/tables/AddressArray.sol b/packages/world/test/tables/AddressArray.sol index 8064fad34e..32a0e2131e 100644 --- a/packages/world/test/tables/AddressArray.sol +++ b/packages/world/test/tables/AddressArray.sol @@ -71,7 +71,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); } @@ -80,7 +80,7 @@ library AddressArray { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); + bytes memory _blob = _store.getDynamicField(_tableId, _keyTuple, 0); return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); } @@ -139,7 +139,7 @@ library AddressArray { _index * 20, (_index + 1) * 20 ); - return (address(Bytes.slice20(_blob, 0))); + return (address(bytes20(_blob))); } } @@ -153,7 +153,7 @@ library AddressArray { unchecked { bytes memory _blob = _store.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 20, (_index + 1) * 20); - return (address(Bytes.slice20(_blob, 0))); + return (address(bytes20(_blob))); } } diff --git a/packages/world/test/tables/Bool.sol b/packages/world/test/tables/Bool.sol index 001f076745..87b9f6e209 100644 --- a/packages/world/test/tables/Bool.sol +++ b/packages/world/test/tables/Bool.sol @@ -68,16 +68,16 @@ library Bool { function get(bytes32 _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Get value (using the specified store) */ function get(IStore _store, bytes32 _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(Bytes.slice1(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); } /** Set value */ diff --git a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol index 5422d16dad..77ca8cd102 100644 --- a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol @@ -71,16 +71,16 @@ library Counter { function get() internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Get value (using the specified store) */ function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Set value */ diff --git a/templates/react/packages/contracts/src/codegen/tables/Counter.sol b/templates/react/packages/contracts/src/codegen/tables/Counter.sol index 5422d16dad..77ca8cd102 100644 --- a/templates/react/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/react/packages/contracts/src/codegen/tables/Counter.sol @@ -71,16 +71,16 @@ library Counter { function get() internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Get value (using the specified store) */ function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Set value */ diff --git a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol index 624887fbb2..f757dc4c9f 100644 --- a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol +++ b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol @@ -84,8 +84,8 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Get x (using the specified store) */ @@ -93,8 +93,8 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Set x */ @@ -118,8 +118,8 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Get y (using the specified store) */ @@ -127,8 +127,8 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 1, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Set y */ @@ -152,8 +152,8 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 2, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Get z (using the specified store) */ @@ -161,8 +161,8 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getField(_tableId, _keyTuple, 2, _fieldLayout); - return (int32(uint32(Bytes.slice4(_blob, 0)))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); } /** Set z */ diff --git a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol index 5422d16dad..77ca8cd102 100644 --- a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol @@ -71,16 +71,16 @@ library Counter { function get() internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Get value (using the specified store) */ function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getField(_tableId, _keyTuple, 0, _fieldLayout); - return (uint32(Bytes.slice4(_blob, 0))); + bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); } /** Set value */ From 708b49c50e05f7b67b596e72ebfcbd76e1ff6280 Mon Sep 17 00:00:00 2001 From: Boffee Date: Sat, 16 Sep 2023 17:06:33 -0500 Subject: [PATCH 07/17] feat(common,store,world): add internal table functions and use them for internal mud logic (#1513) Co-authored-by: alvrs --- .changeset/thin-terms-lay.md | 25 + .../contracts/src/codegen/tables/Multi.sol | 95 ++++ .../contracts/src/codegen/tables/Number.sol | 30 ++ .../src/codegen/tables/NumberList.sol | 76 +++ .../contracts/src/codegen/tables/Vector.sol | 74 +++ .../src/codegen/tables/CounterTable.sol | 27 ++ .../src/codegen/tables/Inventory.sol | 36 ++ .../src/codegen/tables/MessageTable.sol | 16 + .../src/codegen/tables/Dynamics1.sol | 428 +++++++++++++++++ .../src/codegen/tables/Dynamics2.sol | 252 ++++++++++ .../src/codegen/tables/Ephemeral.sol | 18 + .../src/codegen/tables/Singleton.sol | 239 ++++++++++ .../contracts/src/codegen/tables/Statics.sol | 237 ++++++++++ .../src/codegen/render-solidity/common.ts | 8 +- packages/store/gas-report.json | 102 ++-- packages/store/src/Hook.sol | 4 +- packages/store/src/StoreCore.sol | 22 +- .../store/src/codegen/tables/Callbacks.sol | 91 ++++ packages/store/src/codegen/tables/Hooks.sol | 91 ++++ .../store/src/codegen/tables/KeyEncoding.sol | 52 +++ packages/store/src/codegen/tables/Mixed.sol | 216 +++++++++ .../store/src/codegen/tables/StoreHooks.sol | 91 ++++ packages/store/src/codegen/tables/Tables.sol | 247 ++++++++++ packages/store/src/codegen/tables/Vector2.sol | 74 +++ packages/store/ts/codegen/ephemeral.ts | 28 +- packages/store/ts/codegen/field.ts | 28 +- packages/store/ts/codegen/record.ts | 40 +- packages/store/ts/codegen/renderTable.ts | 14 +- packages/world/gas-report.json | 116 ++--- packages/world/src/AccessControl.sol | 6 +- packages/world/src/SystemCall.sol | 8 +- packages/world/src/World.sol | 14 +- .../world/src/modules/core/CoreModule.sol | 6 +- .../AccessManagementSystem.sol | 10 +- .../implementations/BalanceTransferSystem.sol | 10 +- .../ModuleInstallationSystem.sol | 2 +- .../StoreRegistrationSystem.sol | 8 +- .../WorldRegistrationSystem.sol | 38 +- .../src/modules/core/tables/Balances.sol | 30 ++ .../modules/core/tables/FunctionSelectors.sol | 71 +++ .../src/modules/core/tables/ResourceType.sol | 30 ++ .../src/modules/core/tables/SystemHooks.sol | 91 ++++ .../modules/core/tables/SystemRegistry.sol | 30 ++ .../world/src/modules/core/tables/Systems.sol | 69 +++ .../keysintable/tables/KeysInTable.sol | 436 ++++++++++++++++++ .../keysintable/tables/UsedKeysIndex.sol | 76 +++ .../keyswithvalue/tables/KeysWithValue.sol | 91 ++++ .../tables/CallboundDelegations.sol | 55 +++ .../tables/TimeboundDelegations.sol | 33 ++ .../uniqueentity/tables/UniqueEntity.sol | 27 ++ packages/world/src/tables/Delegations.sol | 33 ++ .../world/src/tables/InstalledModules.sol | 33 ++ packages/world/src/tables/NamespaceOwner.sol | 30 ++ packages/world/src/tables/ResourceAccess.sol | 33 ++ packages/world/test/tables/AddressArray.sol | 91 ++++ packages/world/test/tables/Bool.sol | 27 ++ .../contracts/src/codegen/tables/Counter.sol | 27 ++ .../contracts/src/codegen/tables/Counter.sol | 27 ++ .../contracts/src/codegen/tables/Position.sol | 91 ++++ .../contracts/src/codegen/tables/Counter.sol | 27 ++ 60 files changed, 4108 insertions(+), 229 deletions(-) create mode 100644 .changeset/thin-terms-lay.md diff --git a/.changeset/thin-terms-lay.md b/.changeset/thin-terms-lay.md new file mode 100644 index 0000000000..31999bcaa5 --- /dev/null +++ b/.changeset/thin-terms-lay.md @@ -0,0 +1,25 @@ +--- +"@latticexyz/cli": patch +"@latticexyz/common": minor +"@latticexyz/store": minor +"@latticexyz/world": patch +--- + +Generated table libraries now have a set of functions prefixed with `_` that always use their own storage for read/write. +This saves gas for use cases where the functionality to dynamically determine which `Store` to use for read/write is not needed, e.g. root systems in a `World`, or when using `Store` without `World`. + +We decided to continue to always generate a set of functions that dynamically decide which `Store` to use, so that the generated table libraries can still be imported by non-root systems. + +```solidity + +library Counter { + // Dynamically determine which store to write to based on the context + function set(uint32 value) internal; + + // Always write to own storage + function _set(uint32 value) internal; + + // ... equivalent functions for all other Store methods +} + +``` diff --git a/e2e/packages/contracts/src/codegen/tables/Multi.sol b/e2e/packages/contracts/src/codegen/tables/Multi.sol index 8b97411563..fd30c691ef 100644 --- a/e2e/packages/contracts/src/codegen/tables/Multi.sol +++ b/e2e/packages/contracts/src/codegen/tables/Multi.sol @@ -77,6 +77,11 @@ library Multi { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -94,6 +99,18 @@ library Multi { return (int256(uint256(bytes32(_blob)))); } + /** Get num */ + function _getNum(uint32 a, bool b, uint256 c, int120 d) internal view returns (int256 num) { + 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))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int256(uint256(bytes32(_blob)))); + } + /** Get num (using the specified store) */ function getNum(IStore _store, uint32 a, bool b, uint256 c, int120 d) internal view returns (int256 num) { bytes32[] memory _keyTuple = new bytes32[](4); @@ -117,6 +134,17 @@ library Multi { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((num)), _fieldLayout); } + /** Set num */ + function _setNum(uint32 a, bool b, uint256 c, int120 d, int256 num) 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.setField(_tableId, _keyTuple, 0, abi.encodePacked((num)), _fieldLayout); + } + /** Set num (using the specified store) */ function setNum(IStore _store, uint32 a, bool b, uint256 c, int120 d, int256 num) internal { bytes32[] memory _keyTuple = new bytes32[](4); @@ -140,6 +168,18 @@ library Multi { return (_toBool(uint8(bytes1(_blob)))); } + /** Get value */ + function _getValue(uint32 a, bool b, uint256 c, int120 d) internal view returns (bool value) { + 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))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + /** Get value (using the specified store) */ function getValue(IStore _store, uint32 a, bool b, uint256 c, int120 d) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](4); @@ -163,6 +203,17 @@ library Multi { StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((value)), _fieldLayout); } + /** Set value */ + function _setValue(uint32 a, bool b, uint256 c, int120 d, bool value) 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.setField(_tableId, _keyTuple, 1, abi.encodePacked((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function setValue(IStore _store, uint32 a, bool b, uint256 c, int120 d, bool value) internal { bytes32[] memory _keyTuple = new bytes32[](4); @@ -186,6 +237,18 @@ library Multi { return decode(_blob); } + /** Get the full data */ + function _get(uint32 a, bool b, uint256 c, int120 d) internal view returns (MultiData memory _table) { + 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))); + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, uint32 a, bool b, uint256 c, int120 d) internal view returns (MultiData memory _table) { bytes32[] memory _keyTuple = new bytes32[](4); @@ -214,6 +277,22 @@ library Multi { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set(uint32 a, bool b, uint256 c, int120 d, int256 num, bool value) internal { + bytes memory _staticData = encodeStatic(num, value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + 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.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set(IStore _store, uint32 a, bool b, uint256 c, int120 d, int256 num, bool value) internal { bytes memory _staticData = encodeStatic(num, value); @@ -235,6 +314,11 @@ library Multi { set(a, b, c, d, _table.num, _table.value); } + /** Set the full data using the data struct */ + function _set(uint32 a, bool b, uint256 c, int120 d, MultiData memory _table) internal { + set(a, b, c, d, _table.num, _table.value); + } + /** Set the full data using the data struct (using the specified store) */ function set(IStore _store, uint32 a, bool b, uint256 c, int120 d, MultiData memory _table) internal { set(_store, a, b, c, d, _table.num, _table.value); @@ -284,6 +368,17 @@ library Multi { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* 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))); + + StoreCore.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 { bytes32[] memory _keyTuple = new bytes32[](4); diff --git a/e2e/packages/contracts/src/codegen/tables/Number.sol b/e2e/packages/contracts/src/codegen/tables/Number.sol index f5c62ae689..77dcf598c3 100644 --- a/e2e/packages/contracts/src/codegen/tables/Number.sol +++ b/e2e/packages/contracts/src/codegen/tables/Number.sol @@ -64,6 +64,11 @@ library Number { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -78,6 +83,15 @@ library Number { return (uint32(bytes4(_blob))); } + /** Get value */ + function _get(uint32 key) internal view returns (uint32 value) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); + } + /** Get value (using the specified store) */ function get(IStore _store, uint32 key) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -95,6 +109,14 @@ library Number { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Set value */ + function _set(uint32 key, uint32 value) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, uint32 key, uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -134,6 +156,14 @@ library Number { 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); diff --git a/e2e/packages/contracts/src/codegen/tables/NumberList.sol b/e2e/packages/contracts/src/codegen/tables/NumberList.sol index 8f203ff4d0..2703550074 100644 --- a/e2e/packages/contracts/src/codegen/tables/NumberList.sol +++ b/e2e/packages/contracts/src/codegen/tables/NumberList.sol @@ -62,6 +62,11 @@ library NumberList { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -75,6 +80,14 @@ library NumberList { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } + /** Get value */ + function _get() internal view returns (uint32[] memory value) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); + } + /** Get value (using the specified store) */ function get(IStore _store) internal view returns (uint32[] memory value) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -90,6 +103,13 @@ library NumberList { StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } + /** Set value */ + function _set(uint32[] memory value) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, uint32[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -107,6 +127,16 @@ library NumberList { } } + /** Get the length of value */ + function _length() internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](0); + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); + unchecked { + return _byteLength / 4; + } + } + /** Get the length of value (using the specified store) */ function length(IStore _store) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -137,6 +167,19 @@ library NumberList { } } + /** + * Get an item of value + * (unchecked, returns invalid data if index overflows) + */ + function _getItem(uint256 _index) internal view returns (uint32) { + bytes32[] memory _keyTuple = new bytes32[](0); + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 4, (_index + 1) * 4); + return (uint32(bytes4(_blob))); + } + } + /** * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -157,6 +200,13 @@ library NumberList { StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to value */ + function _push(uint32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to value (using the specified store) */ function push(IStore _store, uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -171,6 +221,13 @@ library NumberList { StoreSwitch.popFromField(_tableId, _keyTuple, 0, 4, _fieldLayout); } + /** Pop an element from value */ + function _pop() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.popFromField(_tableId, _keyTuple, 0, 4, _fieldLayout); + } + /** Pop an element from value (using the specified store) */ function pop(IStore _store) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -190,6 +247,18 @@ library NumberList { } } + /** + * Update an element of value at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _update(uint256 _index, uint32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 4, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -238,6 +307,13 @@ library NumberList { 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); diff --git a/e2e/packages/contracts/src/codegen/tables/Vector.sol b/e2e/packages/contracts/src/codegen/tables/Vector.sol index a872229034..380f222702 100644 --- a/e2e/packages/contracts/src/codegen/tables/Vector.sol +++ b/e2e/packages/contracts/src/codegen/tables/Vector.sol @@ -71,6 +71,11 @@ library Vector { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -85,6 +90,15 @@ library Vector { return (int32(uint32(bytes4(_blob)))); } + /** Get x */ + function _getX(uint32 key) internal view returns (int32 x) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); + } + /** Get x (using the specified store) */ function getX(IStore _store, uint32 key) internal view returns (int32 x) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -102,6 +116,14 @@ library Vector { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } + /** Set x */ + function _setX(uint32 key, int32 x) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); + } + /** Set x (using the specified store) */ function setX(IStore _store, uint32 key, int32 x) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -119,6 +141,15 @@ library Vector { return (int32(uint32(bytes4(_blob)))); } + /** Get y */ + function _getY(uint32 key) internal view returns (int32 y) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); + } + /** Get y (using the specified store) */ function getY(IStore _store, uint32 key) internal view returns (int32 y) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -136,6 +167,14 @@ library Vector { StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } + /** Set y */ + function _setY(uint32 key, int32 y) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + StoreCore.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); + } + /** Set y (using the specified store) */ function setY(IStore _store, uint32 key, int32 y) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -153,6 +192,15 @@ library Vector { return decode(_blob); } + /** Get the full data */ + function _get(uint32 key) internal view returns (VectorData memory _table) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, uint32 key) internal view returns (VectorData memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -175,6 +223,19 @@ library Vector { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set(uint32 key, int32 x, int32 y) internal { + bytes memory _staticData = encodeStatic(x, y); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(key)); + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set(IStore _store, uint32 key, int32 x, int32 y) internal { bytes memory _staticData = encodeStatic(x, y); @@ -193,6 +254,11 @@ library Vector { set(key, _table.x, _table.y); } + /** Set the full data using the data struct */ + function _set(uint32 key, VectorData memory _table) internal { + set(key, _table.x, _table.y); + } + /** Set the full data using the data struct (using the specified store) */ function set(IStore _store, uint32 key, VectorData memory _table) internal { set(_store, key, _table.x, _table.y); @@ -236,6 +302,14 @@ library Vector { 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); diff --git a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol index ec404deade..8cff969735 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol @@ -62,6 +62,11 @@ library CounterTable { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -75,6 +80,14 @@ library CounterTable { return (uint32(bytes4(_blob))); } + /** Get value */ + function _get() internal view returns (uint32 value) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); + } + /** Get value (using the specified store) */ function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -90,6 +103,13 @@ library CounterTable { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Set value */ + function _set(uint32 value) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -126,6 +146,13 @@ library CounterTable { 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); diff --git a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol index 40b4913ac1..8344c02274 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol @@ -68,6 +68,11 @@ library Inventory { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -84,6 +89,17 @@ library Inventory { return (uint32(bytes4(_blob))); } + /** Get amount */ + function _get(address owner, uint32 item, uint32 itemVariant) internal view returns (uint32 amount) { + bytes32[] memory _keyTuple = new bytes32[](3); + _keyTuple[0] = bytes32(uint256(uint160(owner))); + _keyTuple[1] = bytes32(uint256(item)); + _keyTuple[2] = bytes32(uint256(itemVariant)); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); + } + /** Get amount (using the specified store) */ function get(IStore _store, address owner, uint32 item, uint32 itemVariant) internal view returns (uint32 amount) { bytes32[] memory _keyTuple = new bytes32[](3); @@ -105,6 +121,16 @@ library Inventory { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((amount)), _fieldLayout); } + /** Set amount */ + function _set(address owner, uint32 item, uint32 itemVariant, uint32 amount) internal { + bytes32[] memory _keyTuple = new bytes32[](3); + _keyTuple[0] = bytes32(uint256(uint160(owner))); + _keyTuple[1] = bytes32(uint256(item)); + _keyTuple[2] = bytes32(uint256(itemVariant)); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((amount)), _fieldLayout); + } + /** Set amount (using the specified store) */ function set(IStore _store, address owner, uint32 item, uint32 itemVariant, uint32 amount) internal { bytes32[] memory _keyTuple = new bytes32[](3); @@ -150,6 +176,16 @@ library Inventory { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* 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)); + + StoreCore.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 { bytes32[] memory _keyTuple = new bytes32[](3); diff --git a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol index 6e58cfc3df..9bcba034c6 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol @@ -62,6 +62,11 @@ library MessageTable { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -78,6 +83,17 @@ library MessageTable { StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Emit the ephemeral event using individual values */ + function _emitEphemeral(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); + } + /** Emit the ephemeral event using individual values (using the specified store) */ function emitEphemeral(IStore _store, string memory value) internal { bytes memory _staticData; diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol index b4b6f609cb..1b7dee5110 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol @@ -80,6 +80,11 @@ library Dynamics1 { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -94,6 +99,15 @@ library Dynamics1 { return toStaticArray_bytes32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } + /** Get staticB32 */ + function _getStaticB32(bytes32 key) internal view returns (bytes32[1] memory staticB32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return toStaticArray_bytes32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); + } + /** Get staticB32 (using the specified store) */ function getStaticB32(IStore _store, bytes32 key) internal view returns (bytes32[1] memory staticB32) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -117,6 +131,14 @@ library Dynamics1 { ); } + /** Set staticB32 */ + function _setStaticB32(bytes32 key, bytes32[1] memory staticB32) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode(fromStaticArray_bytes32_1(staticB32)), _fieldLayout); + } + /** Set staticB32 (using the specified store) */ function setStaticB32(IStore _store, bytes32 key, bytes32[1] memory staticB32) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -136,6 +158,17 @@ library Dynamics1 { } } + /** Get the length of staticB32 */ + function _lengthStaticB32(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); + unchecked { + return _byteLength / 32; + } + } + /** Get the length of staticB32 (using the specified store) */ function lengthStaticB32(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -168,6 +201,27 @@ library Dynamics1 { } } + /** + * Get an item of staticB32 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemStaticB32(bytes32 key, uint256 _index) internal view returns (bytes32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 0, + _fieldLayout, + _index * 32, + (_index + 1) * 32 + ); + return (bytes32(_blob)); + } + } + /** * Get an item of staticB32 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -190,6 +244,14 @@ library Dynamics1 { StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to staticB32 */ + function _pushStaticB32(bytes32 key, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to staticB32 (using the specified store) */ function pushStaticB32(IStore _store, bytes32 key, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -206,6 +268,14 @@ library Dynamics1 { StoreSwitch.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); } + /** Pop an element from staticB32 */ + function _popStaticB32(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); + } + /** Pop an element from staticB32 (using the specified store) */ function popStaticB32(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -227,6 +297,19 @@ library Dynamics1 { } } + /** + * Update an element of staticB32 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateStaticB32(bytes32 key, uint256 _index, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of staticB32 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -249,6 +332,15 @@ library Dynamics1 { return toStaticArray_int32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_int32()); } + /** Get staticI32 */ + function _getStaticI32(bytes32 key) internal view returns (int32[2] memory staticI32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 1); + return toStaticArray_int32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_int32()); + } + /** Get staticI32 (using the specified store) */ function getStaticI32(IStore _store, bytes32 key) internal view returns (int32[2] memory staticI32) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -266,6 +358,14 @@ library Dynamics1 { StoreSwitch.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_int32_2(staticI32)), _fieldLayout); } + /** Set staticI32 */ + function _setStaticI32(bytes32 key, int32[2] memory staticI32) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_int32_2(staticI32)), _fieldLayout); + } + /** Set staticI32 (using the specified store) */ function setStaticI32(IStore _store, bytes32 key, int32[2] memory staticI32) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -285,6 +385,17 @@ library Dynamics1 { } } + /** Get the length of staticI32 */ + function _lengthStaticI32(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); + unchecked { + return _byteLength / 4; + } + } + /** Get the length of staticI32 (using the specified store) */ function lengthStaticI32(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -317,6 +428,20 @@ library Dynamics1 { } } + /** + * Get an item of staticI32 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemStaticI32(bytes32 key, uint256 _index) internal view returns (int32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 1, _fieldLayout, _index * 4, (_index + 1) * 4); + return (int32(uint32(bytes4(_blob)))); + } + } + /** * Get an item of staticI32 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -339,6 +464,14 @@ library Dynamics1 { StoreSwitch.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to staticI32 */ + function _pushStaticI32(bytes32 key, int32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to staticI32 (using the specified store) */ function pushStaticI32(IStore _store, bytes32 key, int32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -355,6 +488,14 @@ library Dynamics1 { StoreSwitch.popFromField(_tableId, _keyTuple, 1, 4, _fieldLayout); } + /** Pop an element from staticI32 */ + function _popStaticI32(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 1, 4, _fieldLayout); + } + /** Pop an element from staticI32 (using the specified store) */ function popStaticI32(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -376,6 +517,19 @@ library Dynamics1 { } } + /** + * Update an element of staticI32 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateStaticI32(bytes32 key, uint256 _index, int32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 1, _index * 4, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of staticI32 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -398,6 +552,15 @@ library Dynamics1 { return toStaticArray_uint128_3(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint128()); } + /** Get staticU128 */ + function _getStaticU128(bytes32 key) internal view returns (uint128[3] memory staticU128) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 2); + return toStaticArray_uint128_3(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint128()); + } + /** Get staticU128 (using the specified store) */ function getStaticU128(IStore _store, bytes32 key) internal view returns (uint128[3] memory staticU128) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -421,6 +584,14 @@ library Dynamics1 { ); } + /** Set staticU128 */ + function _setStaticU128(bytes32 key, uint128[3] memory staticU128) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 2, EncodeArray.encode(fromStaticArray_uint128_3(staticU128)), _fieldLayout); + } + /** Set staticU128 (using the specified store) */ function setStaticU128(IStore _store, bytes32 key, uint128[3] memory staticU128) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -440,6 +611,17 @@ library Dynamics1 { } } + /** Get the length of staticU128 */ + function _lengthStaticU128(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); + unchecked { + return _byteLength / 16; + } + } + /** Get the length of staticU128 (using the specified store) */ function lengthStaticU128(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -472,6 +654,27 @@ library Dynamics1 { } } + /** + * Get an item of staticU128 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemStaticU128(bytes32 key, uint256 _index) internal view returns (uint128) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 2, + _fieldLayout, + _index * 16, + (_index + 1) * 16 + ); + return (uint128(bytes16(_blob))); + } + } + /** * Get an item of staticU128 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -494,6 +697,14 @@ library Dynamics1 { StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to staticU128 */ + function _pushStaticU128(bytes32 key, uint128 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to staticU128 (using the specified store) */ function pushStaticU128(IStore _store, bytes32 key, uint128 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -510,6 +721,14 @@ library Dynamics1 { StoreSwitch.popFromField(_tableId, _keyTuple, 2, 16, _fieldLayout); } + /** Pop an element from staticU128 */ + function _popStaticU128(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 2, 16, _fieldLayout); + } + /** Pop an element from staticU128 (using the specified store) */ function popStaticU128(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -531,6 +750,19 @@ library Dynamics1 { } } + /** + * Update an element of staticU128 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateStaticU128(bytes32 key, uint256 _index, uint128 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 2, _index * 16, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of staticU128 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -553,6 +785,15 @@ library Dynamics1 { return toStaticArray_address_4(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); } + /** Get staticAddrs */ + function _getStaticAddrs(bytes32 key) internal view returns (address[4] memory staticAddrs) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 3); + return toStaticArray_address_4(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); + } + /** Get staticAddrs (using the specified store) */ function getStaticAddrs(IStore _store, bytes32 key) internal view returns (address[4] memory staticAddrs) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -576,6 +817,20 @@ library Dynamics1 { ); } + /** Set staticAddrs */ + function _setStaticAddrs(bytes32 key, address[4] memory staticAddrs) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField( + _tableId, + _keyTuple, + 3, + EncodeArray.encode(fromStaticArray_address_4(staticAddrs)), + _fieldLayout + ); + } + /** Set staticAddrs (using the specified store) */ function setStaticAddrs(IStore _store, bytes32 key, address[4] memory staticAddrs) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -595,6 +850,17 @@ library Dynamics1 { } } + /** Get the length of staticAddrs */ + function _lengthStaticAddrs(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); + unchecked { + return _byteLength / 20; + } + } + /** Get the length of staticAddrs (using the specified store) */ function lengthStaticAddrs(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -627,6 +893,27 @@ library Dynamics1 { } } + /** + * Get an item of staticAddrs + * (unchecked, returns invalid data if index overflows) + */ + function _getItemStaticAddrs(bytes32 key, uint256 _index) internal view returns (address) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 3, + _fieldLayout, + _index * 20, + (_index + 1) * 20 + ); + return (address(bytes20(_blob))); + } + } + /** * Get an item of staticAddrs (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -649,6 +936,14 @@ library Dynamics1 { StoreSwitch.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to staticAddrs */ + function _pushStaticAddrs(bytes32 key, address _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to staticAddrs (using the specified store) */ function pushStaticAddrs(IStore _store, bytes32 key, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -665,6 +960,14 @@ library Dynamics1 { StoreSwitch.popFromField(_tableId, _keyTuple, 3, 20, _fieldLayout); } + /** Pop an element from staticAddrs */ + function _popStaticAddrs(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 3, 20, _fieldLayout); + } + /** Pop an element from staticAddrs (using the specified store) */ function popStaticAddrs(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -686,6 +989,19 @@ library Dynamics1 { } } + /** + * Update an element of staticAddrs at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateStaticAddrs(bytes32 key, uint256 _index, address _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 3, _index * 20, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of staticAddrs (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -708,6 +1024,15 @@ library Dynamics1 { return toStaticArray_bool_5(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bool()); } + /** Get staticBools */ + function _getStaticBools(bytes32 key) internal view returns (bool[5] memory staticBools) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 4); + return toStaticArray_bool_5(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bool()); + } + /** Get staticBools (using the specified store) */ function getStaticBools(IStore _store, bytes32 key) internal view returns (bool[5] memory staticBools) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -725,6 +1050,14 @@ library Dynamics1 { StoreSwitch.setField(_tableId, _keyTuple, 4, EncodeArray.encode(fromStaticArray_bool_5(staticBools)), _fieldLayout); } + /** Set staticBools */ + function _setStaticBools(bytes32 key, bool[5] memory staticBools) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 4, EncodeArray.encode(fromStaticArray_bool_5(staticBools)), _fieldLayout); + } + /** Set staticBools (using the specified store) */ function setStaticBools(IStore _store, bytes32 key, bool[5] memory staticBools) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -744,6 +1077,17 @@ library Dynamics1 { } } + /** Get the length of staticBools */ + function _lengthStaticBools(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 4, _fieldLayout); + unchecked { + return _byteLength / 1; + } + } + /** Get the length of staticBools (using the specified store) */ function lengthStaticBools(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -776,6 +1120,20 @@ library Dynamics1 { } } + /** + * Get an item of staticBools + * (unchecked, returns invalid data if index overflows) + */ + function _getItemStaticBools(bytes32 key, uint256 _index) internal view returns (bool) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 4, _fieldLayout, _index * 1, (_index + 1) * 1); + return (_toBool(uint8(bytes1(_blob)))); + } + } + /** * Get an item of staticBools (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -798,6 +1156,14 @@ library Dynamics1 { StoreSwitch.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to staticBools */ + function _pushStaticBools(bytes32 key, bool _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to staticBools (using the specified store) */ function pushStaticBools(IStore _store, bytes32 key, bool _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -814,6 +1180,14 @@ library Dynamics1 { StoreSwitch.popFromField(_tableId, _keyTuple, 4, 1, _fieldLayout); } + /** Pop an element from staticBools */ + function _popStaticBools(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 4, 1, _fieldLayout); + } + /** Pop an element from staticBools (using the specified store) */ function popStaticBools(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -835,6 +1209,19 @@ library Dynamics1 { } } + /** + * Update an element of staticBools at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateStaticBools(bytes32 key, uint256 _index, bool _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 4, _index * 1, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of staticBools (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -857,6 +1244,15 @@ library Dynamics1 { return decode(_blob); } + /** Get the full data */ + function _get(bytes32 key) internal view returns (Dynamics1Data memory _table) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, bytes32 key) internal view returns (Dynamics1Data memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -885,6 +1281,25 @@ library Dynamics1 { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set( + bytes32 key, + bytes32[1] memory staticB32, + int32[2] memory staticI32, + uint128[3] memory staticU128, + address[4] memory staticAddrs, + bool[5] memory staticBools + ) internal { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(staticB32, staticI32, staticU128, staticAddrs, staticBools); + bytes memory _dynamicData = encodeDynamic(staticB32, staticI32, staticU128, staticAddrs, staticBools); + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set( IStore _store, @@ -910,6 +1325,11 @@ library Dynamics1 { set(key, _table.staticB32, _table.staticI32, _table.staticU128, _table.staticAddrs, _table.staticBools); } + /** Set the full data using the data struct */ + function _set(bytes32 key, Dynamics1Data memory _table) internal { + set(key, _table.staticB32, _table.staticI32, _table.staticU128, _table.staticAddrs, _table.staticBools); + } + /** Set the full data using the data struct (using the specified store) */ function set(IStore _store, bytes32 key, Dynamics1Data memory _table) internal { set(_store, key, _table.staticB32, _table.staticI32, _table.staticU128, _table.staticAddrs, _table.staticBools); @@ -1028,6 +1448,14 @@ library Dynamics1 { 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); diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol index 59d39a2106..77371f92a7 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol @@ -74,6 +74,11 @@ library Dynamics2 { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -88,6 +93,15 @@ library Dynamics2 { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint64()); } + /** Get u64 */ + function _getU64(bytes32 key) internal view returns (uint64[] memory u64) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint64()); + } + /** Get u64 (using the specified store) */ function getU64(IStore _store, bytes32 key) internal view returns (uint64[] memory u64) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -105,6 +119,14 @@ library Dynamics2 { StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((u64)), _fieldLayout); } + /** Set u64 */ + function _setU64(bytes32 key, uint64[] memory u64) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((u64)), _fieldLayout); + } + /** Set u64 (using the specified store) */ function setU64(IStore _store, bytes32 key, uint64[] memory u64) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -124,6 +146,17 @@ library Dynamics2 { } } + /** Get the length of u64 */ + function _lengthU64(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); + unchecked { + return _byteLength / 8; + } + } + /** Get the length of u64 (using the specified store) */ function lengthU64(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -156,6 +189,20 @@ library Dynamics2 { } } + /** + * Get an item of u64 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemU64(bytes32 key, uint256 _index) internal view returns (uint64) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 0, _fieldLayout, _index * 8, (_index + 1) * 8); + return (uint64(bytes8(_blob))); + } + } + /** * Get an item of u64 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -178,6 +225,14 @@ library Dynamics2 { StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to u64 */ + function _pushU64(bytes32 key, uint64 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to u64 (using the specified store) */ function pushU64(IStore _store, bytes32 key, uint64 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -194,6 +249,14 @@ library Dynamics2 { StoreSwitch.popFromField(_tableId, _keyTuple, 0, 8, _fieldLayout); } + /** Pop an element from u64 */ + function _popU64(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 0, 8, _fieldLayout); + } + /** Pop an element from u64 (using the specified store) */ function popU64(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -215,6 +278,19 @@ library Dynamics2 { } } + /** + * Update an element of u64 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateU64(bytes32 key, uint256 _index, uint64 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 8, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of u64 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -237,6 +313,15 @@ library Dynamics2 { return (string(_blob)); } + /** Get str */ + function _getStr(bytes32 key) internal view returns (string memory str) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 1); + return (string(_blob)); + } + /** Get str (using the specified store) */ function getStr(IStore _store, bytes32 key) internal view returns (string memory str) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -254,6 +339,14 @@ library Dynamics2 { StoreSwitch.setField(_tableId, _keyTuple, 1, bytes((str)), _fieldLayout); } + /** Set str */ + function _setStr(bytes32 key, string memory str) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 1, bytes((str)), _fieldLayout); + } + /** Set str (using the specified store) */ function setStr(IStore _store, bytes32 key, string memory str) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -273,6 +366,17 @@ library Dynamics2 { } } + /** Get the length of str */ + function _lengthStr(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); + unchecked { + return _byteLength / 1; + } + } + /** Get the length of str (using the specified store) */ function lengthStr(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -305,6 +409,20 @@ library Dynamics2 { } } + /** + * Get an item of str + * (unchecked, returns invalid data if index overflows) + */ + function _getItemStr(bytes32 key, uint256 _index) internal view returns (string memory) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 1, _fieldLayout, _index * 1, (_index + 1) * 1); + return (string(_blob)); + } + } + /** * Get an item of str (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -327,6 +445,14 @@ library Dynamics2 { StoreSwitch.pushToField(_tableId, _keyTuple, 1, bytes((_slice)), _fieldLayout); } + /** Push a slice to str */ + function _pushStr(bytes32 key, string memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 1, bytes((_slice)), _fieldLayout); + } + /** Push a slice to str (using the specified store) */ function pushStr(IStore _store, bytes32 key, string memory _slice) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -343,6 +469,14 @@ library Dynamics2 { StoreSwitch.popFromField(_tableId, _keyTuple, 1, 1, _fieldLayout); } + /** Pop a slice from str */ + function _popStr(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 1, 1, _fieldLayout); + } + /** Pop a slice from str (using the specified store) */ function popStr(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -364,6 +498,19 @@ library Dynamics2 { } } + /** + * Update a slice of str at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateStr(bytes32 key, uint256 _index, string memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 1, _index * 1, bytes((_slice)), _fieldLayout); + } + } + /** * Update a slice of str (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -386,6 +533,15 @@ library Dynamics2 { return (bytes(_blob)); } + /** Get b */ + function _getB(bytes32 key) internal view returns (bytes memory b) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 2); + return (bytes(_blob)); + } + /** Get b (using the specified store) */ function getB(IStore _store, bytes32 key) internal view returns (bytes memory b) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -403,6 +559,14 @@ library Dynamics2 { StoreSwitch.setField(_tableId, _keyTuple, 2, bytes((b)), _fieldLayout); } + /** Set b */ + function _setB(bytes32 key, bytes memory b) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 2, bytes((b)), _fieldLayout); + } + /** Set b (using the specified store) */ function setB(IStore _store, bytes32 key, bytes memory b) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -422,6 +586,17 @@ library Dynamics2 { } } + /** Get the length of b */ + function _lengthB(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); + unchecked { + return _byteLength / 1; + } + } + /** Get the length of b (using the specified store) */ function lengthB(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -454,6 +629,20 @@ library Dynamics2 { } } + /** + * Get an item of b + * (unchecked, returns invalid data if index overflows) + */ + function _getItemB(bytes32 key, uint256 _index) internal view returns (bytes memory) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 1, (_index + 1) * 1); + return (bytes(_blob)); + } + } + /** * Get an item of b (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -476,6 +665,14 @@ library Dynamics2 { StoreSwitch.pushToField(_tableId, _keyTuple, 2, bytes((_slice)), _fieldLayout); } + /** Push a slice to b */ + function _pushB(bytes32 key, bytes memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 2, bytes((_slice)), _fieldLayout); + } + /** Push a slice to b (using the specified store) */ function pushB(IStore _store, bytes32 key, bytes memory _slice) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -492,6 +689,14 @@ library Dynamics2 { StoreSwitch.popFromField(_tableId, _keyTuple, 2, 1, _fieldLayout); } + /** Pop a slice from b */ + function _popB(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 2, 1, _fieldLayout); + } + /** Pop a slice from b (using the specified store) */ function popB(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -513,6 +718,19 @@ library Dynamics2 { } } + /** + * Update a slice of b at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateB(bytes32 key, uint256 _index, bytes memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 2, _index * 1, bytes((_slice)), _fieldLayout); + } + } + /** * Update a slice of b (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -535,6 +753,15 @@ library Dynamics2 { return decode(_blob); } + /** Get the full data */ + function _get(bytes32 key) internal view returns (Dynamics2Data memory _table) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, bytes32 key) internal view returns (Dynamics2Data memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -556,6 +783,18 @@ library Dynamics2 { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set(bytes32 key, uint64[] memory u64, string memory str, bytes memory b) internal { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(u64, str, b); + bytes memory _dynamicData = encodeDynamic(u64, str, b); + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 key, uint64[] memory u64, string memory str, bytes memory b) internal { bytes memory _staticData; @@ -573,6 +812,11 @@ library Dynamics2 { set(key, _table.u64, _table.str, _table.b); } + /** Set the full data using the data struct */ + function _set(bytes32 key, Dynamics2Data memory _table) internal { + set(key, _table.u64, _table.str, _table.b); + } + /** Set the full data using the data struct (using the specified store) */ function set(IStore _store, bytes32 key, Dynamics2Data memory _table) internal { set(_store, key, _table.u64, _table.str, _table.b); @@ -652,6 +896,14 @@ library Dynamics2 { 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); diff --git a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol b/packages/cli/contracts/src/codegen/tables/Ephemeral.sol index 31b8000e6b..04e78e2503 100644 --- a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol +++ b/packages/cli/contracts/src/codegen/tables/Ephemeral.sol @@ -64,6 +64,11 @@ library Ephemeral { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -82,6 +87,19 @@ library Ephemeral { StoreSwitch.emitEphemeralRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Emit the ephemeral event using individual values */ + function _emitEphemeral(bytes32 key, uint256 value) internal { + bytes memory _staticData = encodeStatic(value); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.emitEphemeralRecord(_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 { bytes memory _staticData = encodeStatic(value); diff --git a/packages/cli/contracts/src/codegen/tables/Singleton.sol b/packages/cli/contracts/src/codegen/tables/Singleton.sol index 90e1319b41..3db7f72067 100644 --- a/packages/cli/contracts/src/codegen/tables/Singleton.sol +++ b/packages/cli/contracts/src/codegen/tables/Singleton.sol @@ -68,6 +68,11 @@ library Singleton { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -81,6 +86,14 @@ library Singleton { return (int256(uint256(bytes32(_blob)))); } + /** Get v1 */ + function _getV1() internal view returns (int256 v1) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int256(uint256(bytes32(_blob)))); + } + /** Get v1 (using the specified store) */ function getV1(IStore _store) internal view returns (int256 v1) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -96,6 +109,13 @@ library Singleton { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), _fieldLayout); } + /** Set v1 */ + function _setV1(int256 v1) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), _fieldLayout); + } + /** Set v1 (using the specified store) */ function setV1(IStore _store, int256 v1) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -111,6 +131,14 @@ library Singleton { return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } + /** Get v2 */ + function _getV2() internal view returns (uint32[2] memory v2) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); + } + /** Get v2 (using the specified store) */ function getV2(IStore _store) internal view returns (uint32[2] memory v2) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -126,6 +154,13 @@ library Singleton { StoreSwitch.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_uint32_2(v2)), _fieldLayout); } + /** Set v2 */ + function _setV2(uint32[2] memory v2) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 1, EncodeArray.encode(fromStaticArray_uint32_2(v2)), _fieldLayout); + } + /** Set v2 (using the specified store) */ function setV2(IStore _store, uint32[2] memory v2) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -143,6 +178,16 @@ library Singleton { } } + /** Get the length of v2 */ + function _lengthV2() internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](0); + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); + unchecked { + return _byteLength / 4; + } + } + /** Get the length of v2 (using the specified store) */ function lengthV2(IStore _store) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -173,6 +218,19 @@ library Singleton { } } + /** + * Get an item of v2 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemV2(uint256 _index) internal view returns (uint32) { + bytes32[] memory _keyTuple = new bytes32[](0); + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 1, _fieldLayout, _index * 4, (_index + 1) * 4); + return (uint32(bytes4(_blob))); + } + } + /** * Get an item of v2 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -193,6 +251,13 @@ library Singleton { StoreSwitch.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to v2 */ + function _pushV2(uint32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to v2 (using the specified store) */ function pushV2(IStore _store, uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -207,6 +272,13 @@ library Singleton { StoreSwitch.popFromField(_tableId, _keyTuple, 1, 4, _fieldLayout); } + /** Pop an element from v2 */ + function _popV2() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.popFromField(_tableId, _keyTuple, 1, 4, _fieldLayout); + } + /** Pop an element from v2 (using the specified store) */ function popV2(IStore _store) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -226,6 +298,18 @@ library Singleton { } } + /** + * Update an element of v2 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateV2(uint256 _index, uint32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 1, _index * 4, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of v2 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -246,6 +330,14 @@ library Singleton { return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } + /** Get v3 */ + function _getV3() internal view returns (uint32[2] memory v3) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 1); + return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); + } + /** Get v3 (using the specified store) */ function getV3(IStore _store) internal view returns (uint32[2] memory v3) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -261,6 +353,13 @@ library Singleton { StoreSwitch.setField(_tableId, _keyTuple, 2, EncodeArray.encode(fromStaticArray_uint32_2(v3)), _fieldLayout); } + /** Set v3 */ + function _setV3(uint32[2] memory v3) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 2, EncodeArray.encode(fromStaticArray_uint32_2(v3)), _fieldLayout); + } + /** Set v3 (using the specified store) */ function setV3(IStore _store, uint32[2] memory v3) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -278,6 +377,16 @@ library Singleton { } } + /** Get the length of v3 */ + function _lengthV3() internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](0); + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); + unchecked { + return _byteLength / 4; + } + } + /** Get the length of v3 (using the specified store) */ function lengthV3(IStore _store) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -308,6 +417,19 @@ library Singleton { } } + /** + * Get an item of v3 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemV3(uint256 _index) internal view returns (uint32) { + bytes32[] memory _keyTuple = new bytes32[](0); + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 4, (_index + 1) * 4); + return (uint32(bytes4(_blob))); + } + } + /** * Get an item of v3 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -328,6 +450,13 @@ library Singleton { StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to v3 */ + function _pushV3(uint32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to v3 (using the specified store) */ function pushV3(IStore _store, uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -342,6 +471,13 @@ library Singleton { StoreSwitch.popFromField(_tableId, _keyTuple, 2, 4, _fieldLayout); } + /** Pop an element from v3 */ + function _popV3() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.popFromField(_tableId, _keyTuple, 2, 4, _fieldLayout); + } + /** Pop an element from v3 (using the specified store) */ function popV3(IStore _store) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -361,6 +497,18 @@ library Singleton { } } + /** + * Update an element of v3 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateV3(uint256 _index, uint32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 2, _index * 4, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of v3 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -381,6 +529,14 @@ library Singleton { return toStaticArray_uint32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } + /** Get v4 */ + function _getV4() internal view returns (uint32[1] memory v4) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 2); + return toStaticArray_uint32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); + } + /** Get v4 (using the specified store) */ function getV4(IStore _store) internal view returns (uint32[1] memory v4) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -396,6 +552,13 @@ library Singleton { StoreSwitch.setField(_tableId, _keyTuple, 3, EncodeArray.encode(fromStaticArray_uint32_1(v4)), _fieldLayout); } + /** Set v4 */ + function _setV4(uint32[1] memory v4) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 3, EncodeArray.encode(fromStaticArray_uint32_1(v4)), _fieldLayout); + } + /** Set v4 (using the specified store) */ function setV4(IStore _store, uint32[1] memory v4) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -413,6 +576,16 @@ library Singleton { } } + /** Get the length of v4 */ + function _lengthV4() internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](0); + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); + unchecked { + return _byteLength / 4; + } + } + /** Get the length of v4 (using the specified store) */ function lengthV4(IStore _store) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -443,6 +616,19 @@ library Singleton { } } + /** + * Get an item of v4 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemV4(uint256 _index) internal view returns (uint32) { + bytes32[] memory _keyTuple = new bytes32[](0); + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 4, (_index + 1) * 4); + return (uint32(bytes4(_blob))); + } + } + /** * Get an item of v4 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -463,6 +649,13 @@ library Singleton { StoreSwitch.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to v4 */ + function _pushV4(uint32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to v4 (using the specified store) */ function pushV4(IStore _store, uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -477,6 +670,13 @@ library Singleton { StoreSwitch.popFromField(_tableId, _keyTuple, 3, 4, _fieldLayout); } + /** Pop an element from v4 */ + function _popV4() internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.popFromField(_tableId, _keyTuple, 3, 4, _fieldLayout); + } + /** Pop an element from v4 (using the specified store) */ function popV4(IStore _store) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -496,6 +696,18 @@ library Singleton { } } + /** + * Update an element of v4 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateV4(uint256 _index, uint32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 3, _index * 4, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of v4 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -516,6 +728,14 @@ library Singleton { return decode(_blob); } + /** Get the full data */ + function _get() internal view returns (int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get( IStore _store @@ -538,6 +758,18 @@ library Singleton { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set(int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) internal { + bytes memory _staticData = encodeStatic(v1); + + PackedCounter _encodedLengths = encodeLengths(v2, v3, v4); + bytes memory _dynamicData = encodeDynamic(v2, v3, v4); + + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set(IStore _store, int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) internal { bytes memory _staticData = encodeStatic(v1); @@ -646,6 +878,13 @@ library Singleton { 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); diff --git a/packages/cli/contracts/src/codegen/tables/Statics.sol b/packages/cli/contracts/src/codegen/tables/Statics.sol index 0f0376d429..0c74e1b419 100644 --- a/packages/cli/contracts/src/codegen/tables/Statics.sol +++ b/packages/cli/contracts/src/codegen/tables/Statics.sol @@ -96,6 +96,11 @@ library Statics { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -115,6 +120,20 @@ library Statics { return (uint256(bytes32(_blob))); } + /** Get v1 */ + function _getV1(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (uint256 v1) { + 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))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); + } + /** Get v1 (using the specified store) */ function getV1( IStore _store, @@ -150,6 +169,19 @@ library Statics { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), _fieldLayout); } + /** Set v1 */ + function _setV1(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, uint256 v1) 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.setField(_tableId, _keyTuple, 0, abi.encodePacked((v1)), _fieldLayout); + } + /** Set v1 (using the specified store) */ function setV1(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, uint256 v1) internal { bytes32[] memory _keyTuple = new bytes32[](6); @@ -177,6 +209,20 @@ library Statics { return (int32(uint32(bytes4(_blob)))); } + /** Get v2 */ + function _getV2(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (int32 v2) { + 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))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); + } + /** Get v2 (using the specified store) */ function getV2( IStore _store, @@ -212,6 +258,19 @@ library Statics { StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((v2)), _fieldLayout); } + /** Set v2 */ + function _setV2(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, int32 v2) 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.setField(_tableId, _keyTuple, 1, abi.encodePacked((v2)), _fieldLayout); + } + /** Set v2 (using the specified store) */ function setV2(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, int32 v2) internal { bytes32[] memory _keyTuple = new bytes32[](6); @@ -239,6 +298,20 @@ library Statics { return (bytes16(_blob)); } + /** Get v3 */ + function _getV3(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (bytes16 v3) { + 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))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); + return (bytes16(_blob)); + } + /** Get v3 (using the specified store) */ function getV3( IStore _store, @@ -274,6 +347,19 @@ library Statics { StoreSwitch.setField(_tableId, _keyTuple, 2, abi.encodePacked((v3)), _fieldLayout); } + /** Set v3 */ + function _setV3(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, bytes16 v3) 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.setField(_tableId, _keyTuple, 2, abi.encodePacked((v3)), _fieldLayout); + } + /** Set v3 (using the specified store) */ function setV3(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, bytes16 v3) internal { bytes32[] memory _keyTuple = new bytes32[](6); @@ -301,6 +387,20 @@ library Statics { return (address(bytes20(_blob))); } + /** Get v4 */ + function _getV4(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (address v4) { + 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))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 3, _fieldLayout); + return (address(bytes20(_blob))); + } + /** Get v4 (using the specified store) */ function getV4( IStore _store, @@ -336,6 +436,19 @@ library Statics { StoreSwitch.setField(_tableId, _keyTuple, 3, abi.encodePacked((v4)), _fieldLayout); } + /** Set v4 */ + function _setV4(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, address v4) 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.setField(_tableId, _keyTuple, 3, abi.encodePacked((v4)), _fieldLayout); + } + /** Set v4 (using the specified store) */ function setV4(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, address v4) internal { bytes32[] memory _keyTuple = new bytes32[](6); @@ -363,6 +476,20 @@ library Statics { return (_toBool(uint8(bytes1(_blob)))); } + /** Get v5 */ + function _getV5(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (bool v5) { + 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))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 4, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + /** Get v5 (using the specified store) */ function getV5( IStore _store, @@ -398,6 +525,19 @@ library Statics { StoreSwitch.setField(_tableId, _keyTuple, 4, abi.encodePacked((v5)), _fieldLayout); } + /** Set v5 */ + function _setV5(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, bool v5) 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.setField(_tableId, _keyTuple, 4, abi.encodePacked((v5)), _fieldLayout); + } + /** Set v5 (using the specified store) */ function setV5(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, bool v5) internal { bytes32[] memory _keyTuple = new bytes32[](6); @@ -425,6 +565,20 @@ library Statics { return Enum1(uint8(bytes1(_blob))); } + /** Get v6 */ + function _getV6(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6) internal view returns (Enum1 v6) { + 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))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 5, _fieldLayout); + return Enum1(uint8(bytes1(_blob))); + } + /** Get v6 (using the specified store) */ function getV6( IStore _store, @@ -460,6 +614,19 @@ library Statics { StoreSwitch.setField(_tableId, _keyTuple, 5, abi.encodePacked(uint8(v6)), _fieldLayout); } + /** Set v6 */ + function _setV6(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, Enum1 v6) 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.setField(_tableId, _keyTuple, 5, abi.encodePacked(uint8(v6)), _fieldLayout); + } + /** Set v6 (using the specified store) */ function setV6(IStore _store, uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, Enum1 v6) internal { bytes32[] memory _keyTuple = new bytes32[](6); @@ -494,6 +661,27 @@ library Statics { return decode(_blob); } + /** Get the full data */ + function _get( + uint256 k1, + int32 k2, + bytes16 k3, + address k4, + bool k5, + Enum2 k6 + ) internal view returns (StaticsData memory _table) { + 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))); + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get( IStore _store, @@ -547,6 +735,37 @@ library Statics { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set( + uint256 k1, + int32 k2, + bytes16 k3, + address k4, + bool k5, + Enum2 k6, + uint256 v1, + int32 v2, + bytes16 v3, + address v4, + bool v5, + Enum1 v6 + ) internal { + bytes memory _staticData = encodeStatic(v1, v2, v3, v4, v5, v6); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + 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.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set( IStore _store, @@ -584,6 +803,11 @@ library Statics { set(k1, k2, k3, k4, k5, k6, _table.v1, _table.v2, _table.v3, _table.v4, _table.v5, _table.v6); } + /** Set the full data using the data struct */ + function _set(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, Enum2 k6, StaticsData memory _table) internal { + set(k1, k2, k3, k4, k5, k6, _table.v1, _table.v2, _table.v3, _table.v4, _table.v5, _table.v6); + } + /** Set the full data using the data struct (using the specified store) */ function set( IStore _store, @@ -675,6 +899,19 @@ library Statics { 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); diff --git a/packages/common/src/codegen/render-solidity/common.ts b/packages/common/src/codegen/render-solidity/common.ts index a853ff8513..4f20e8d965 100644 --- a/packages/common/src/codegen/render-solidity/common.ts +++ b/packages/common/src/codegen/render-solidity/common.ts @@ -131,14 +131,16 @@ export function renderWithStore( _typedStore: string | undefined, _store: string, _commentSuffix: string, - _untypedStore: string | undefined + _untypedStore: string | undefined, + _methodPrefix: string ) => string ): string { let result = ""; - result += callback(undefined, "StoreSwitch", "", undefined); + result += callback(undefined, "StoreSwitch", "", undefined, ""); + result += callback(undefined, "StoreCore", "", undefined, "_"); if (storeArgument) { - result += "\n" + callback("IStore _store", "_store", " (using the specified store)", "_store"); + result += "\n" + callback("IStore _store", "_store", " (using the specified store)", "_store", ""); } return result; diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index c1ac85ebb5..9f301b4105 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": 688555 + "gasUsed": 687695 }, { "file": "test/Mixed.t.sol", @@ -363,13 +363,13 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Mixed table", - "gasUsed": 550389 + "gasUsed": 549513 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 104102 + "gasUsed": 103812 }, { "file": "test/Mixed.t.sol", @@ -609,25 +609,25 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 20433 + "gasUsed": 20143 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 14445 + "gasUsed": 14155 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 22629 + "gasUsed": 22339 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 14641 + "gasUsed": 14351 }, { "file": "test/StoreCoreGas.t.sol", @@ -663,109 +663,109 @@ "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 6882 + "gasUsed": 6592 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "Check for existence of table (existent)", - "gasUsed": 1555 + "gasUsed": 1260 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "check for existence of table (non-existent)", - "gasUsed": 3556 + "gasUsed": 3261 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 58604 + "gasUsed": 60314 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 71502 + "gasUsed": 70846 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 21245 + "gasUsed": 20625 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 16797 + "gasUsed": 16217 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 58604 + "gasUsed": 60314 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 164598 + "gasUsed": 163968 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 24445 + "gasUsed": 23825 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 17782 + "gasUsed": 17202 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 12189 + "gasUsed": 11899 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 34943 + "gasUsed": 34653 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 612540 + "gasUsed": 609664 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get field layout (warm)", - "gasUsed": 1567 + "gasUsed": 1272 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get value schema (warm)", - "gasUsed": 2077 + "gasUsed": 1782 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get key schema (warm)", - "gasUsed": 3406 + "gasUsed": 2816 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 102022 + "gasUsed": 101732 }, { "file": "test/StoreCoreGas.t.sol", @@ -807,7 +807,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 31744 + "gasUsed": 31454 }, { "file": "test/StoreCoreGas.t.sol", @@ -819,7 +819,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 30384 + "gasUsed": 30094 }, { "file": "test/StoreCoreGas.t.sol", @@ -831,7 +831,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 53269 + "gasUsed": 52979 }, { "file": "test/StoreCoreGas.t.sol", @@ -843,7 +843,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 31496 + "gasUsed": 31206 }, { "file": "test/StoreCoreGas.t.sol", @@ -855,7 +855,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 32328 + "gasUsed": 32038 }, { "file": "test/StoreCoreGas.t.sol", @@ -867,7 +867,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 54832 + "gasUsed": 54542 }, { "file": "test/StoreCoreGas.t.sol", @@ -879,13 +879,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 13227 + "gasUsed": 12937 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 14029 + "gasUsed": 13739 }, { "file": "test/StoreHook.t.sol", @@ -933,31 +933,31 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 56344 + "gasUsed": 56047 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: get field (warm)", - "gasUsed": 2912 + "gasUsed": 2894 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 35254 + "gasUsed": 34957 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 58342 + "gasUsed": 58052 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 58342 + "gasUsed": 58052 }, { "file": "test/tables/StoreHooks.t.sol", @@ -969,55 +969,55 @@ "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 15341 + "gasUsed": 15051 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 11896 + "gasUsed": 11606 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 13367 + "gasUsed": 13077 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 34465 + "gasUsed": 34175 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 7293 + "gasUsed": 7003 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 30504 + "gasUsed": 30214 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 81033 + "gasUsed": 80743 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 80944 + "gasUsed": 80654 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 16158 + "gasUsed": 15868 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", @@ -1041,13 +1041,13 @@ "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 22382 + "gasUsed": 22092 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 24518 + "gasUsed": 24228 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -1101,13 +1101,13 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 411812 + "gasUsed": 410936 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 33231 + "gasUsed": 32941 }, { "file": "test/Vector2.t.sol", diff --git a/packages/store/src/Hook.sol b/packages/store/src/Hook.sol index 876f7e7e52..2d7da97a6f 100644 --- a/packages/store/src/Hook.sol +++ b/packages/store/src/Hook.sol @@ -21,7 +21,7 @@ library HookLib { * Filter the given hook from the hook list at the given key in the given hook table */ function filterListByAddress(bytes32 hookTableId, bytes32 key, address hookAddressToRemove) internal { - bytes21[] memory currentHooks = Hooks.get(hookTableId, key); + bytes21[] memory currentHooks = Hooks._get(hookTableId, key); // Initialize the new hooks array with the same length because we don't know if the hook is registered yet bytes21[] memory newHooks = new bytes21[](currentHooks.length); @@ -44,7 +44,7 @@ library HookLib { } // Set the new hooks table - Hooks.set(hookTableId, key, newHooks); + Hooks._set(hookTableId, key, newHooks); } } diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 684c834c42..004c4a5170 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -74,7 +74,7 @@ library StoreCore { * Get the field layout for the given tableId */ function getFieldLayout(bytes32 tableId) internal view returns (FieldLayout fieldLayout) { - fieldLayout = FieldLayout.wrap(Tables.getFieldLayout(tableId)); + fieldLayout = FieldLayout.wrap(Tables._getFieldLayout(tableId)); if (fieldLayout.isEmpty()) { revert IStoreErrors.StoreCore_TableNotFound(tableId, string(abi.encodePacked(tableId))); } @@ -84,7 +84,7 @@ library StoreCore { * Get the key schema for the given tableId */ function getKeySchema(bytes32 tableId) internal view returns (Schema keySchema) { - keySchema = Schema.wrap(Tables.getKeySchema(tableId)); + keySchema = Schema.wrap(Tables._getKeySchema(tableId)); // key schemas can be empty for singleton tables, so we can't depend on key schema for table check if (!hasTable(tableId)) { revert IStoreErrors.StoreCore_TableNotFound(tableId, string(abi.encodePacked(tableId))); @@ -95,7 +95,7 @@ library StoreCore { * Get the schema for the given tableId */ function getValueSchema(bytes32 tableId) internal view returns (Schema valueSchema) { - valueSchema = Schema.wrap(Tables.getValueSchema(tableId)); + valueSchema = Schema.wrap(Tables._getValueSchema(tableId)); if (valueSchema.isEmpty()) { revert IStoreErrors.StoreCore_TableNotFound(tableId, string(abi.encodePacked(tableId))); } @@ -105,7 +105,7 @@ library StoreCore { * Check if a table with the given tableId exists */ function hasTable(bytes32 tableId) internal view returns (bool) { - return Tables.getFieldLayout(tableId) != bytes32(0); + return Tables._getFieldLayout(tableId) != bytes32(0); } /** @@ -147,7 +147,7 @@ library StoreCore { } // Register the table metadata - Tables.set( + Tables._set( tableId, FieldLayout.unwrap(fieldLayout), Schema.unwrap(keySchema), @@ -204,7 +204,7 @@ library StoreCore { emit StoreSetRecord(tableId, keyTuple, staticData, encodedLengths.unwrap(), dynamicData); // Call onBeforeSetRecord hooks (before actually modifying the state, so observers have access to the previous state if needed) - bytes21[] memory hooks = StoreHooks.get(tableId); + bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_RECORD))) { @@ -284,7 +284,7 @@ library StoreCore { FieldLayout fieldLayout ) internal { // Call onBeforeSetField hooks (before modifying the state) - bytes21[] memory hooks = StoreHooks.get(tableId); + bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { @@ -315,7 +315,7 @@ library StoreCore { emit StoreDeleteRecord(tableId, keyTuple); // Call onBeforeDeleteRecord hooks (before actually modifying the state, so observers have access to the previous state if needed) - bytes21[] memory hooks = StoreHooks.get(tableId); + bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_DELETE_RECORD))) { @@ -363,7 +363,7 @@ library StoreCore { ); // Call onBeforeSetField hooks (before modifying the state) - bytes21[] memory hooks = StoreHooks.get(tableId); + bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { @@ -404,7 +404,7 @@ library StoreCore { } // Call onBeforeSetField hooks (before modifying the state) - bytes21[] memory hooks = StoreHooks.get(tableId); + bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { @@ -456,7 +456,7 @@ library StoreCore { } // Call onBeforeSetField hooks (before modifying the state) - bytes21[] memory hooks = StoreHooks.get(tableId); + bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { diff --git a/packages/store/src/codegen/tables/Callbacks.sol b/packages/store/src/codegen/tables/Callbacks.sol index cbe5d850c5..499daf1a2a 100644 --- a/packages/store/src/codegen/tables/Callbacks.sol +++ b/packages/store/src/codegen/tables/Callbacks.sol @@ -64,6 +64,11 @@ library Callbacks { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -78,6 +83,15 @@ library Callbacks { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes24()); } + /** Get value */ + function _get(bytes32 key) internal view returns (bytes24[] memory value) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes24()); + } + /** Get value (using the specified store) */ function get(IStore _store, bytes32 key) internal view returns (bytes24[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -95,6 +109,14 @@ library Callbacks { StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } + /** Set value */ + function _set(bytes32 key, bytes24[] memory value) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, bytes32 key, bytes24[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -114,6 +136,17 @@ library Callbacks { } } + /** Get the length of value */ + function _length(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); + unchecked { + return _byteLength / 24; + } + } + /** Get the length of value (using the specified store) */ function length(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -146,6 +179,27 @@ library Callbacks { } } + /** + * Get an item of value + * (unchecked, returns invalid data if index overflows) + */ + function _getItem(bytes32 key, uint256 _index) internal view returns (bytes24) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 0, + _fieldLayout, + _index * 24, + (_index + 1) * 24 + ); + return (bytes24(_blob)); + } + } + /** * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -168,6 +222,14 @@ library Callbacks { StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to value */ + function _push(bytes32 key, bytes24 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to value (using the specified store) */ function push(IStore _store, bytes32 key, bytes24 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -184,6 +246,14 @@ library Callbacks { StoreSwitch.popFromField(_tableId, _keyTuple, 0, 24, _fieldLayout); } + /** Pop an element from value */ + function _pop(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 0, 24, _fieldLayout); + } + /** Pop an element from value (using the specified store) */ function pop(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -205,6 +275,19 @@ library Callbacks { } } + /** + * Update an element of value at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _update(bytes32 key, uint256 _index, bytes24 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 24, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -256,6 +339,14 @@ library Callbacks { 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); diff --git a/packages/store/src/codegen/tables/Hooks.sol b/packages/store/src/codegen/tables/Hooks.sol index d01e5b05e0..d5eaafb986 100644 --- a/packages/store/src/codegen/tables/Hooks.sol +++ b/packages/store/src/codegen/tables/Hooks.sol @@ -61,6 +61,11 @@ library Hooks { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register(bytes32 _tableId) internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store, bytes32 _tableId) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -75,6 +80,15 @@ library Hooks { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } + /** Get value */ + function _get(bytes32 _tableId, bytes32 key) internal view returns (bytes21[] memory value) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); + } + /** Get value (using the specified store) */ function get(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -92,6 +106,14 @@ library Hooks { StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } + /** Set value */ + function _set(bytes32 _tableId, bytes32 key, bytes21[] memory value) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, bytes32 _tableId, bytes32 key, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -111,6 +133,17 @@ library Hooks { } } + /** Get the length of value */ + function _length(bytes32 _tableId, bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); + unchecked { + return _byteLength / 21; + } + } + /** Get the length of value (using the specified store) */ function length(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -143,6 +176,27 @@ library Hooks { } } + /** + * Get an item of value + * (unchecked, returns invalid data if index overflows) + */ + function _getItem(bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (bytes21) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 0, + _fieldLayout, + _index * 21, + (_index + 1) * 21 + ); + return (bytes21(_blob)); + } + } + /** * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -165,6 +219,14 @@ library Hooks { StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to value */ + function _push(bytes32 _tableId, bytes32 key, bytes21 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to value (using the specified store) */ function push(IStore _store, bytes32 _tableId, bytes32 key, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -181,6 +243,14 @@ library Hooks { StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } + /** Pop an element from value */ + function _pop(bytes32 _tableId, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); + } + /** Pop an element from value (using the specified store) */ function pop(IStore _store, bytes32 _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -202,6 +272,19 @@ library Hooks { } } + /** + * Update an element of value at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _update(bytes32 _tableId, bytes32 key, uint256 _index, bytes21 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -253,6 +336,14 @@ library Hooks { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes32 _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, bytes32 _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); diff --git a/packages/store/src/codegen/tables/KeyEncoding.sol b/packages/store/src/codegen/tables/KeyEncoding.sol index 78d705bf2d..47cc468cb7 100644 --- a/packages/store/src/codegen/tables/KeyEncoding.sol +++ b/packages/store/src/codegen/tables/KeyEncoding.sol @@ -77,6 +77,11 @@ library KeyEncoding { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -103,6 +108,27 @@ library KeyEncoding { return (_toBool(uint8(bytes1(_blob)))); } + /** Get value */ + function _get( + uint256 k1, + int32 k2, + bytes16 k3, + address k4, + bool k5, + ExampleEnum k6 + ) internal view returns (bool value) { + 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))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + /** Get value (using the specified store) */ function get( IStore _store, @@ -138,6 +164,19 @@ library KeyEncoding { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Set value */ + function _set(uint256 k1, int32 k2, bytes16 k3, address k4, bool k5, ExampleEnum k6, bool value) 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.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set( IStore _store, @@ -208,6 +247,19 @@ library KeyEncoding { 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 { + 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, ExampleEnum k6) internal { bytes32[] memory _keyTuple = new bytes32[](6); diff --git a/packages/store/src/codegen/tables/Mixed.sol b/packages/store/src/codegen/tables/Mixed.sol index 13f6d12dfd..fbadcc31ee 100644 --- a/packages/store/src/codegen/tables/Mixed.sol +++ b/packages/store/src/codegen/tables/Mixed.sol @@ -77,6 +77,11 @@ library Mixed { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -91,6 +96,15 @@ library Mixed { return (uint32(bytes4(_blob))); } + /** Get u32 */ + function _getU32(bytes32 key) internal view returns (uint32 u32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); + } + /** Get u32 (using the specified store) */ function getU32(IStore _store, bytes32 key) internal view returns (uint32 u32) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -108,6 +122,14 @@ library Mixed { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((u32)), _fieldLayout); } + /** Set u32 */ + function _setU32(bytes32 key, uint32 u32) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((u32)), _fieldLayout); + } + /** Set u32 (using the specified store) */ function setU32(IStore _store, bytes32 key, uint32 u32) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -125,6 +147,15 @@ library Mixed { return (uint128(bytes16(_blob))); } + /** Get u128 */ + function _getU128(bytes32 key) internal view returns (uint128 u128) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint128(bytes16(_blob))); + } + /** Get u128 (using the specified store) */ function getU128(IStore _store, bytes32 key) internal view returns (uint128 u128) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -142,6 +173,14 @@ library Mixed { StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((u128)), _fieldLayout); } + /** Set u128 */ + function _setU128(bytes32 key, uint128 u128) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 1, abi.encodePacked((u128)), _fieldLayout); + } + /** Set u128 (using the specified store) */ function setU128(IStore _store, bytes32 key, uint128 u128) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -159,6 +198,15 @@ library Mixed { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); } + /** Get a32 */ + function _getA32(bytes32 key) internal view returns (uint32[] memory a32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); + } + /** Get a32 (using the specified store) */ function getA32(IStore _store, bytes32 key) internal view returns (uint32[] memory a32) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -176,6 +224,14 @@ library Mixed { StoreSwitch.setField(_tableId, _keyTuple, 2, EncodeArray.encode((a32)), _fieldLayout); } + /** Set a32 */ + function _setA32(bytes32 key, uint32[] memory a32) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 2, EncodeArray.encode((a32)), _fieldLayout); + } + /** Set a32 (using the specified store) */ function setA32(IStore _store, bytes32 key, uint32[] memory a32) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -195,6 +251,17 @@ library Mixed { } } + /** Get the length of a32 */ + function _lengthA32(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); + unchecked { + return _byteLength / 4; + } + } + /** Get the length of a32 (using the specified store) */ function lengthA32(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -227,6 +294,20 @@ library Mixed { } } + /** + * Get an item of a32 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemA32(bytes32 key, uint256 _index) internal view returns (uint32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 2, _fieldLayout, _index * 4, (_index + 1) * 4); + return (uint32(bytes4(_blob))); + } + } + /** * Get an item of a32 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -249,6 +330,14 @@ library Mixed { StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to a32 */ + function _pushA32(bytes32 key, uint32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to a32 (using the specified store) */ function pushA32(IStore _store, bytes32 key, uint32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -265,6 +354,14 @@ library Mixed { StoreSwitch.popFromField(_tableId, _keyTuple, 2, 4, _fieldLayout); } + /** Pop an element from a32 */ + function _popA32(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 2, 4, _fieldLayout); + } + /** Pop an element from a32 (using the specified store) */ function popA32(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -286,6 +383,19 @@ library Mixed { } } + /** + * Update an element of a32 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateA32(bytes32 key, uint256 _index, uint32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 2, _index * 4, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of a32 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -308,6 +418,15 @@ library Mixed { return (string(_blob)); } + /** Get s */ + function _getS(bytes32 key) internal view returns (string memory s) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 1); + return (string(_blob)); + } + /** Get s (using the specified store) */ function getS(IStore _store, bytes32 key) internal view returns (string memory s) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -325,6 +444,14 @@ library Mixed { StoreSwitch.setField(_tableId, _keyTuple, 3, bytes((s)), _fieldLayout); } + /** Set s */ + function _setS(bytes32 key, string memory s) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 3, bytes((s)), _fieldLayout); + } + /** Set s (using the specified store) */ function setS(IStore _store, bytes32 key, string memory s) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -344,6 +471,17 @@ library Mixed { } } + /** Get the length of s */ + function _lengthS(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); + unchecked { + return _byteLength / 1; + } + } + /** Get the length of s (using the specified store) */ function lengthS(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -376,6 +514,20 @@ library Mixed { } } + /** + * Get an item of s + * (unchecked, returns invalid data if index overflows) + */ + function _getItemS(bytes32 key, uint256 _index) internal view returns (string memory) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 1, (_index + 1) * 1); + return (string(_blob)); + } + } + /** * Get an item of s (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -398,6 +550,14 @@ library Mixed { StoreSwitch.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), _fieldLayout); } + /** Push a slice to s */ + function _pushS(bytes32 key, string memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), _fieldLayout); + } + /** Push a slice to s (using the specified store) */ function pushS(IStore _store, bytes32 key, string memory _slice) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -414,6 +574,14 @@ library Mixed { StoreSwitch.popFromField(_tableId, _keyTuple, 3, 1, _fieldLayout); } + /** Pop a slice from s */ + function _popS(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 3, 1, _fieldLayout); + } + /** Pop a slice from s (using the specified store) */ function popS(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -435,6 +603,19 @@ library Mixed { } } + /** + * Update a slice of s at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateS(bytes32 key, uint256 _index, string memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 3, _index * 1, bytes((_slice)), _fieldLayout); + } + } + /** * Update a slice of s (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -457,6 +638,15 @@ library Mixed { return decode(_blob); } + /** Get the full data */ + function _get(bytes32 key) internal view returns (MixedData memory _table) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, bytes32 key) internal view returns (MixedData memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -479,6 +669,19 @@ library Mixed { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set(bytes32 key, uint32 u32, uint128 u128, uint32[] memory a32, string memory s) internal { + bytes memory _staticData = encodeStatic(u32, u128); + + PackedCounter _encodedLengths = encodeLengths(a32, s); + bytes memory _dynamicData = encodeDynamic(a32, s); + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 key, uint32 u32, uint128 u128, uint32[] memory a32, string memory s) internal { bytes memory _staticData = encodeStatic(u32, u128); @@ -497,6 +700,11 @@ library Mixed { set(key, _table.u32, _table.u128, _table.a32, _table.s); } + /** Set the full data using the data struct */ + function _set(bytes32 key, MixedData memory _table) internal { + set(key, _table.u32, _table.u128, _table.a32, _table.s); + } + /** Set the full data using the data struct (using the specified store) */ function set(IStore _store, bytes32 key, MixedData memory _table) internal { set(_store, key, _table.u32, _table.u128, _table.a32, _table.s); @@ -576,6 +784,14 @@ library Mixed { 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); diff --git a/packages/store/src/codegen/tables/StoreHooks.sol b/packages/store/src/codegen/tables/StoreHooks.sol index a2632c0b20..43ca3b5fc1 100644 --- a/packages/store/src/codegen/tables/StoreHooks.sol +++ b/packages/store/src/codegen/tables/StoreHooks.sol @@ -64,6 +64,11 @@ library StoreHooks { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -78,6 +83,15 @@ library StoreHooks { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } + /** Get value */ + function _get(bytes32 key) internal view returns (bytes21[] memory value) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); + } + /** Get value (using the specified store) */ function get(IStore _store, bytes32 key) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -95,6 +109,14 @@ library StoreHooks { StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } + /** Set value */ + function _set(bytes32 key, bytes21[] memory value) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, bytes32 key, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -114,6 +136,17 @@ library StoreHooks { } } + /** Get the length of value */ + function _length(bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); + unchecked { + return _byteLength / 21; + } + } + /** Get the length of value (using the specified store) */ function length(IStore _store, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -146,6 +179,27 @@ library StoreHooks { } } + /** + * Get an item of value + * (unchecked, returns invalid data if index overflows) + */ + function _getItem(bytes32 key, uint256 _index) internal view returns (bytes21) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 0, + _fieldLayout, + _index * 21, + (_index + 1) * 21 + ); + return (bytes21(_blob)); + } + } + /** * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -168,6 +222,14 @@ library StoreHooks { StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to value */ + function _push(bytes32 key, bytes21 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to value (using the specified store) */ function push(IStore _store, bytes32 key, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -184,6 +246,14 @@ library StoreHooks { StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } + /** Pop an element from value */ + function _pop(bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); + } + /** Pop an element from value (using the specified store) */ function pop(IStore _store, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -205,6 +275,19 @@ library StoreHooks { } } + /** + * Update an element of value at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _update(bytes32 key, uint256 _index, bytes21 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -256,6 +339,14 @@ library StoreHooks { 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); diff --git a/packages/store/src/codegen/tables/Tables.sol b/packages/store/src/codegen/tables/Tables.sol index 6204d3de73..268d19548c 100644 --- a/packages/store/src/codegen/tables/Tables.sol +++ b/packages/store/src/codegen/tables/Tables.sol @@ -80,6 +80,11 @@ library Tables { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -94,6 +99,15 @@ library Tables { return (bytes32(_blob)); } + /** Get fieldLayout */ + function _getFieldLayout(bytes32 tableId) internal view returns (bytes32 fieldLayout) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); + } + /** Get fieldLayout (using the specified store) */ function getFieldLayout(IStore _store, bytes32 tableId) internal view returns (bytes32 fieldLayout) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -111,6 +125,14 @@ library Tables { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((fieldLayout)), _fieldLayout); } + /** Set fieldLayout */ + function _setFieldLayout(bytes32 tableId, bytes32 fieldLayout) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((fieldLayout)), _fieldLayout); + } + /** Set fieldLayout (using the specified store) */ function setFieldLayout(IStore _store, bytes32 tableId, bytes32 fieldLayout) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -128,6 +150,15 @@ library Tables { return (bytes32(_blob)); } + /** Get keySchema */ + function _getKeySchema(bytes32 tableId) internal view returns (bytes32 keySchema) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (bytes32(_blob)); + } + /** Get keySchema (using the specified store) */ function getKeySchema(IStore _store, bytes32 tableId) internal view returns (bytes32 keySchema) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -145,6 +176,14 @@ library Tables { StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((keySchema)), _fieldLayout); } + /** Set keySchema */ + function _setKeySchema(bytes32 tableId, bytes32 keySchema) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.setField(_tableId, _keyTuple, 1, abi.encodePacked((keySchema)), _fieldLayout); + } + /** Set keySchema (using the specified store) */ function setKeySchema(IStore _store, bytes32 tableId, bytes32 keySchema) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -162,6 +201,15 @@ library Tables { return (bytes32(_blob)); } + /** Get valueSchema */ + function _getValueSchema(bytes32 tableId) internal view returns (bytes32 valueSchema) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); + return (bytes32(_blob)); + } + /** Get valueSchema (using the specified store) */ function getValueSchema(IStore _store, bytes32 tableId) internal view returns (bytes32 valueSchema) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -179,6 +227,14 @@ library Tables { StoreSwitch.setField(_tableId, _keyTuple, 2, abi.encodePacked((valueSchema)), _fieldLayout); } + /** Set valueSchema */ + function _setValueSchema(bytes32 tableId, bytes32 valueSchema) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.setField(_tableId, _keyTuple, 2, abi.encodePacked((valueSchema)), _fieldLayout); + } + /** Set valueSchema (using the specified store) */ function setValueSchema(IStore _store, bytes32 tableId, bytes32 valueSchema) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -196,6 +252,15 @@ library Tables { return (bytes(_blob)); } + /** Get abiEncodedKeyNames */ + function _getAbiEncodedKeyNames(bytes32 tableId) internal view returns (bytes memory abiEncodedKeyNames) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (bytes(_blob)); + } + /** Get abiEncodedKeyNames (using the specified store) */ function getAbiEncodedKeyNames( IStore _store, @@ -216,6 +281,14 @@ library Tables { StoreSwitch.setField(_tableId, _keyTuple, 3, bytes((abiEncodedKeyNames)), _fieldLayout); } + /** Set abiEncodedKeyNames */ + function _setAbiEncodedKeyNames(bytes32 tableId, bytes memory abiEncodedKeyNames) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.setField(_tableId, _keyTuple, 3, bytes((abiEncodedKeyNames)), _fieldLayout); + } + /** Set abiEncodedKeyNames (using the specified store) */ function setAbiEncodedKeyNames(IStore _store, bytes32 tableId, bytes memory abiEncodedKeyNames) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -235,6 +308,17 @@ library Tables { } } + /** Get the length of abiEncodedKeyNames */ + function _lengthAbiEncodedKeyNames(bytes32 tableId) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); + unchecked { + return _byteLength / 1; + } + } + /** Get the length of abiEncodedKeyNames (using the specified store) */ function lengthAbiEncodedKeyNames(IStore _store, bytes32 tableId) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -267,6 +351,20 @@ library Tables { } } + /** + * Get an item of abiEncodedKeyNames + * (unchecked, returns invalid data if index overflows) + */ + function _getItemAbiEncodedKeyNames(bytes32 tableId, uint256 _index) internal view returns (bytes memory) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 3, _fieldLayout, _index * 1, (_index + 1) * 1); + return (bytes(_blob)); + } + } + /** * Get an item of abiEncodedKeyNames (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -293,6 +391,14 @@ library Tables { StoreSwitch.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), _fieldLayout); } + /** Push a slice to abiEncodedKeyNames */ + function _pushAbiEncodedKeyNames(bytes32 tableId, bytes memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.pushToField(_tableId, _keyTuple, 3, bytes((_slice)), _fieldLayout); + } + /** Push a slice to abiEncodedKeyNames (using the specified store) */ function pushAbiEncodedKeyNames(IStore _store, bytes32 tableId, bytes memory _slice) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -309,6 +415,14 @@ library Tables { StoreSwitch.popFromField(_tableId, _keyTuple, 3, 1, _fieldLayout); } + /** Pop a slice from abiEncodedKeyNames */ + function _popAbiEncodedKeyNames(bytes32 tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.popFromField(_tableId, _keyTuple, 3, 1, _fieldLayout); + } + /** Pop a slice from abiEncodedKeyNames (using the specified store) */ function popAbiEncodedKeyNames(IStore _store, bytes32 tableId) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -330,6 +444,19 @@ library Tables { } } + /** + * Update a slice of abiEncodedKeyNames at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateAbiEncodedKeyNames(bytes32 tableId, uint256 _index, bytes memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 3, _index * 1, bytes((_slice)), _fieldLayout); + } + } + /** * Update a slice of abiEncodedKeyNames (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -352,6 +479,15 @@ library Tables { return (bytes(_blob)); } + /** Get abiEncodedFieldNames */ + function _getAbiEncodedFieldNames(bytes32 tableId) internal view returns (bytes memory abiEncodedFieldNames) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 1); + return (bytes(_blob)); + } + /** Get abiEncodedFieldNames (using the specified store) */ function getAbiEncodedFieldNames( IStore _store, @@ -372,6 +508,14 @@ library Tables { StoreSwitch.setField(_tableId, _keyTuple, 4, bytes((abiEncodedFieldNames)), _fieldLayout); } + /** Set abiEncodedFieldNames */ + function _setAbiEncodedFieldNames(bytes32 tableId, bytes memory abiEncodedFieldNames) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.setField(_tableId, _keyTuple, 4, bytes((abiEncodedFieldNames)), _fieldLayout); + } + /** Set abiEncodedFieldNames (using the specified store) */ function setAbiEncodedFieldNames(IStore _store, bytes32 tableId, bytes memory abiEncodedFieldNames) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -391,6 +535,17 @@ library Tables { } } + /** Get the length of abiEncodedFieldNames */ + function _lengthAbiEncodedFieldNames(bytes32 tableId) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 4, _fieldLayout); + unchecked { + return _byteLength / 1; + } + } + /** Get the length of abiEncodedFieldNames (using the specified store) */ function lengthAbiEncodedFieldNames(IStore _store, bytes32 tableId) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -423,6 +578,20 @@ library Tables { } } + /** + * Get an item of abiEncodedFieldNames + * (unchecked, returns invalid data if index overflows) + */ + function _getItemAbiEncodedFieldNames(bytes32 tableId, uint256 _index) internal view returns (bytes memory) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice(_tableId, _keyTuple, 4, _fieldLayout, _index * 1, (_index + 1) * 1); + return (bytes(_blob)); + } + } + /** * Get an item of abiEncodedFieldNames (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -449,6 +618,14 @@ library Tables { StoreSwitch.pushToField(_tableId, _keyTuple, 4, bytes((_slice)), _fieldLayout); } + /** Push a slice to abiEncodedFieldNames */ + function _pushAbiEncodedFieldNames(bytes32 tableId, bytes memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.pushToField(_tableId, _keyTuple, 4, bytes((_slice)), _fieldLayout); + } + /** Push a slice to abiEncodedFieldNames (using the specified store) */ function pushAbiEncodedFieldNames(IStore _store, bytes32 tableId, bytes memory _slice) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -465,6 +642,14 @@ library Tables { StoreSwitch.popFromField(_tableId, _keyTuple, 4, 1, _fieldLayout); } + /** Pop a slice from abiEncodedFieldNames */ + function _popAbiEncodedFieldNames(bytes32 tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.popFromField(_tableId, _keyTuple, 4, 1, _fieldLayout); + } + /** Pop a slice from abiEncodedFieldNames (using the specified store) */ function popAbiEncodedFieldNames(IStore _store, bytes32 tableId) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -486,6 +671,19 @@ library Tables { } } + /** + * Update a slice of abiEncodedFieldNames at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateAbiEncodedFieldNames(bytes32 tableId, uint256 _index, bytes memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 4, _index * 1, bytes((_slice)), _fieldLayout); + } + } + /** * Update a slice of abiEncodedFieldNames (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -508,6 +706,15 @@ library Tables { return decode(_blob); } + /** Get the full data */ + function _get(bytes32 tableId) internal view returns (TablesData memory _table) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, bytes32 tableId) internal view returns (TablesData memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -537,6 +744,26 @@ library Tables { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set( + bytes32 tableId, + bytes32 fieldLayout, + bytes32 keySchema, + bytes32 valueSchema, + bytes memory abiEncodedKeyNames, + bytes memory abiEncodedFieldNames + ) internal { + bytes memory _staticData = encodeStatic(fieldLayout, keySchema, valueSchema); + + PackedCounter _encodedLengths = encodeLengths(abiEncodedKeyNames, abiEncodedFieldNames); + bytes memory _dynamicData = encodeDynamic(abiEncodedKeyNames, abiEncodedFieldNames); + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = tableId; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set( IStore _store, @@ -570,6 +797,18 @@ library Tables { ); } + /** Set the full data using the data struct */ + function _set(bytes32 tableId, TablesData memory _table) internal { + set( + tableId, + _table.fieldLayout, + _table.keySchema, + _table.valueSchema, + _table.abiEncodedKeyNames, + _table.abiEncodedFieldNames + ); + } + /** Set the full data using the data struct (using the specified store) */ function set(IStore _store, bytes32 tableId, TablesData memory _table) internal { set( @@ -675,6 +914,14 @@ library Tables { 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); diff --git a/packages/store/src/codegen/tables/Vector2.sol b/packages/store/src/codegen/tables/Vector2.sol index d7694660eb..707c7a3dac 100644 --- a/packages/store/src/codegen/tables/Vector2.sol +++ b/packages/store/src/codegen/tables/Vector2.sol @@ -71,6 +71,11 @@ library Vector2 { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -85,6 +90,15 @@ library Vector2 { return (uint32(bytes4(_blob))); } + /** Get x */ + function _getX(bytes32 key) internal view returns (uint32 x) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); + } + /** Get x (using the specified store) */ function getX(IStore _store, bytes32 key) internal view returns (uint32 x) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -102,6 +116,14 @@ library Vector2 { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } + /** Set x */ + function _setX(bytes32 key, uint32 x) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); + } + /** Set x (using the specified store) */ function setX(IStore _store, bytes32 key, uint32 x) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -119,6 +141,15 @@ library Vector2 { return (uint32(bytes4(_blob))); } + /** Get y */ + function _getY(bytes32 key) internal view returns (uint32 y) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint32(bytes4(_blob))); + } + /** Get y (using the specified store) */ function getY(IStore _store, bytes32 key) internal view returns (uint32 y) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -136,6 +167,14 @@ library Vector2 { StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } + /** Set y */ + function _setY(bytes32 key, uint32 y) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); + } + /** Set y (using the specified store) */ function setY(IStore _store, bytes32 key, uint32 y) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -153,6 +192,15 @@ library Vector2 { return decode(_blob); } + /** Get the full data */ + function _get(bytes32 key) internal view returns (Vector2Data memory _table) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, bytes32 key) internal view returns (Vector2Data memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -175,6 +223,19 @@ library Vector2 { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set(bytes32 key, uint32 x, uint32 y) internal { + bytes memory _staticData = encodeStatic(x, y); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 key, uint32 x, uint32 y) internal { bytes memory _staticData = encodeStatic(x, y); @@ -193,6 +254,11 @@ library Vector2 { set(key, _table.x, _table.y); } + /** Set the full data using the data struct */ + function _set(bytes32 key, Vector2Data memory _table) internal { + set(key, _table.x, _table.y); + } + /** Set the full data using the data struct (using the specified store) */ function set(IStore _store, bytes32 key, Vector2Data memory _table) internal { set(_store, key, _table.x, _table.y); @@ -236,6 +302,14 @@ library Vector2 { 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); diff --git a/packages/store/ts/codegen/ephemeral.ts b/packages/store/ts/codegen/ephemeral.ts index 21b850a782..df57892d8a 100644 --- a/packages/store/ts/codegen/ephemeral.ts +++ b/packages/store/ts/codegen/ephemeral.ts @@ -8,14 +8,14 @@ export function renderEphemeralMethods(options: RenderTableOptions) { let result = renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Emit the ephemeral event using individual values${_commentSuffix} */ - function emitEphemeral(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - renderArguments(options.fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`)), - ])}) internal { + function ${_methodNamePrefix}emitEphemeral(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + renderArguments(options.fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`)), + ])}) internal { ${renderRecordData(options)} ${_keyTupleDefinition} @@ -28,14 +28,14 @@ export function renderEphemeralMethods(options: RenderTableOptions) { if (structName !== undefined) { result += renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix, _untypedStore) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Emit the ephemeral event using the data struct${_commentSuffix} */ - function emitEphemeral(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - `${structName} memory _table`, - ])}) internal { + function ${_methodNamePrefix}emitEphemeral(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + `${structName} memory _table`, + ])}) internal { emitEphemeral(${renderArguments([ _untypedStore, _tableId, diff --git a/packages/store/ts/codegen/field.ts b/packages/store/ts/codegen/field.ts index e63ad43f2d..2b811b864c 100644 --- a/packages/store/ts/codegen/field.ts +++ b/packages/store/ts/codegen/field.ts @@ -19,9 +19,9 @@ export function renderFieldMethods(options: RenderTableOptions) { result += renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Get ${field.name}${_commentSuffix} */ - function get${field.methodNameSuffix}(${renderArguments([ + function ${_methodNamePrefix}get${field.methodNameSuffix}(${renderArguments([ _typedStore, _typedTableId, _typedKeyArgs, @@ -48,9 +48,9 @@ export function renderFieldMethods(options: RenderTableOptions) { result += renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Set ${field.name}${_commentSuffix} */ - function set${field.methodNameSuffix}(${renderArguments([ + function ${_methodNamePrefix}set${field.methodNameSuffix}(${renderArguments([ _typedStore, _typedTableId, _typedKeyArgs, @@ -67,9 +67,9 @@ export function renderFieldMethods(options: RenderTableOptions) { result += renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Get the length of ${field.name}${_commentSuffix} */ - function length${field.methodNameSuffix}(${renderArguments([ + function ${_methodNamePrefix}length${field.methodNameSuffix}(${renderArguments([ _typedStore, _typedTableId, _typedKeyArgs, @@ -85,12 +85,12 @@ export function renderFieldMethods(options: RenderTableOptions) { result += renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** * Get an item of ${field.name}${_commentSuffix} * (unchecked, returns invalid data if index overflows) */ - function getItem${field.methodNameSuffix}(${renderArguments([ + function ${_methodNamePrefix}getItem${field.methodNameSuffix}(${renderArguments([ _typedStore, _typedTableId, _typedKeyArgs, @@ -114,9 +114,9 @@ export function renderFieldMethods(options: RenderTableOptions) { result += renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Push ${portionData.title} to ${field.name}${_commentSuffix} */ - function push${field.methodNameSuffix}(${renderArguments([ + function ${_methodNamePrefix}push${field.methodNameSuffix}(${renderArguments([ _typedStore, _typedTableId, _typedKeyArgs, @@ -130,9 +130,9 @@ export function renderFieldMethods(options: RenderTableOptions) { result += renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Pop ${portionData.title} from ${field.name}${_commentSuffix} */ - function pop${field.methodNameSuffix}(${renderArguments([ + function ${_methodNamePrefix}pop${field.methodNameSuffix}(${renderArguments([ _typedStore, _typedTableId, _typedKeyArgs, @@ -145,12 +145,12 @@ export function renderFieldMethods(options: RenderTableOptions) { result += renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** * Update ${portionData.title} of ${field.name}${_commentSuffix} at \`_index\` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) */ - function update${field.methodNameSuffix}(${renderArguments([ + function ${_methodNamePrefix}update${field.methodNameSuffix}(${renderArguments([ _typedStore, _typedTableId, _typedKeyArgs, diff --git a/packages/store/ts/codegen/record.ts b/packages/store/ts/codegen/record.ts index 75277e463e..9b8b99bb99 100644 --- a/packages/store/ts/codegen/record.ts +++ b/packages/store/ts/codegen/record.ts @@ -14,13 +14,13 @@ export function renderRecordMethods(options: RenderTableOptions) { let result = renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Get the full data${_commentSuffix} */ - function get(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - ])}) internal view returns (${renderDecodedRecord(options)}) { + function ${_methodNamePrefix}get(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + ])}) internal view returns (${renderDecodedRecord(options)}) { ${_keyTupleDefinition} bytes memory _blob = ${_store}.getRecord(_tableId, _keyTuple, _fieldLayout); return decode(_blob); @@ -30,14 +30,14 @@ export function renderRecordMethods(options: RenderTableOptions) { result += renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Set the full data using individual values${_commentSuffix} */ - function set(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - renderArguments(options.fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`)), - ])}) internal { + function ${_methodNamePrefix}set(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + renderArguments(options.fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`)), + ])}) internal { ${renderRecordData(options)} ${_keyTupleDefinition} @@ -50,14 +50,14 @@ export function renderRecordMethods(options: RenderTableOptions) { if (structName !== undefined) { result += renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix, _untypedStore) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Set the full data using the data struct${_commentSuffix} */ - function set(${renderArguments([ - _typedStore, - _typedTableId, - _typedKeyArgs, - `${structName} memory _table`, - ])}) internal { + function ${_methodNamePrefix}set(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + `${structName} memory _table`, + ])}) internal { set(${renderArguments([ _untypedStore, _tableId, diff --git a/packages/store/ts/codegen/renderTable.ts b/packages/store/ts/codegen/renderTable.ts index e918822585..0d4c8e4b48 100644 --- a/packages/store/ts/codegen/renderTable.ts +++ b/packages/store/ts/codegen/renderTable.ts @@ -1,4 +1,5 @@ import { + RenderDynamicField, renderArguments, renderCommonData, renderList, @@ -7,7 +8,6 @@ import { renderTypeHelpers, renderWithStore, renderedSolidityHeader, - RenderDynamicField, RenderStaticField, } from "@latticexyz/common/codegen"; import { renderEphemeralMethods } from "./ephemeral"; @@ -113,9 +113,9 @@ export function renderTable(options: RenderTableOptions) { ${renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /** Register the table with its config${_commentSuffix} */ - function register(${renderArguments([_typedStore, _typedTableId])}) internal { + function ${_methodNamePrefix}register(${renderArguments([_typedStore, _typedTableId])}) internal { ${_store}.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } ` @@ -152,9 +152,13 @@ export function renderTable(options: RenderTableOptions) { shouldRenderDelete ? renderWithStore( storeArgument, - (_typedStore, _store, _commentSuffix) => ` + (_typedStore, _store, _commentSuffix, _untypedStore, _methodNamePrefix) => ` /* Delete all data for given keys${_commentSuffix} */ - function deleteRecord(${renderArguments([_typedStore, _typedTableId, _typedKeyArgs])}) internal { + function ${_methodNamePrefix}deleteRecord(${renderArguments([ + _typedStore, + _typedTableId, + _typedKeyArgs, + ])}) internal { ${_keyTupleDefinition} ${_store}.deleteRecord(_tableId, _keyTuple, _fieldLayout); } diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 1568db80f3..c28d505e3f 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -3,31 +3,31 @@ "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (cold)", - "gasUsed": 9514 + "gasUsed": 6924 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm, namespace only)", - "gasUsed": 1829 + "gasUsed": 1534 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm)", - "gasUsed": 3534 + "gasUsed": 2944 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (cold)", - "gasUsed": 9556 + "gasUsed": 6966 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (warm)", - "gasUsed": 3559 + "gasUsed": 2969 }, { "file": "test/AccessControl.t.sol", @@ -39,67 +39,67 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1425069 + "gasUsed": 1414535 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1425069 + "gasUsed": 1414535 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 161043 + "gasUsed": 158665 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1425069 + "gasUsed": 1414535 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1425069 + "gasUsed": 1414535 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 22513 + "gasUsed": 21917 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 178377 + "gasUsed": 170653 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1425069 + "gasUsed": 1414535 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 21235 + "gasUsed": 20639 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 91846 + "gasUsed": 87686 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 661189 + "gasUsed": 653818 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,79 +117,79 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 661189 + "gasUsed": 653818 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 136579 + "gasUsed": 134201 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 661189 + "gasUsed": 653818 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 106157 + "gasUsed": 103779 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 34216 + "gasUsed": 32729 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 661189 + "gasUsed": 653818 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 141193 + "gasUsed": 138815 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 105952 + "gasUsed": 103574 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 103370 + "gasUsed": 101600 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 52259 + "gasUsed": 51669 }, { "file": "test/query.t.sol", "test": "testCombinedHasNotQuery", "name": "CombinedHasNotQuery", - "gasUsed": 130426 + "gasUsed": 127476 }, { "file": "test/query.t.sol", "test": "testCombinedHasQuery", "name": "CombinedHasQuery", - "gasUsed": 83357 + "gasUsed": 80997 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 84121 + "gasUsed": 82351 }, { "file": "test/query.t.sol", @@ -201,19 +201,19 @@ "file": "test/query.t.sol", "test": "testHasQuery", "name": "HasQuery", - "gasUsed": 18578 + "gasUsed": 17988 }, { "file": "test/query.t.sol", "test": "testHasQuery1000Keys", "name": "HasQuery with 1000 keys", - "gasUsed": 5902151 + "gasUsed": 5901561 }, { "file": "test/query.t.sol", "test": "testHasQuery100Keys", "name": "HasQuery with 100 keys", - "gasUsed": 550845 + "gasUsed": 550255 }, { "file": "test/query.t.sol", @@ -225,156 +225,156 @@ "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 45855 + "gasUsed": 45265 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 116017 + "gasUsed": 113879 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 35016 + "gasUsed": 33481 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 110371 + "gasUsed": 108316 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 27946 + "gasUsed": 26692 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 693352 + "gasUsed": 677906 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 52577 + "gasUsed": 51083 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 680858 + "gasUsed": 667966 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 52577 + "gasUsed": 51083 }, { "file": "test/World.t.sol", "test": "testCall", "name": "call a system via the World", - "gasUsed": 13196 + "gasUsed": 12288 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 49345 + "gasUsed": 50163 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "call a system via an unlimited delegation", - "gasUsed": 13590 + "gasUsed": 12682 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 9343 + "gasUsed": 8747 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 88725 + "gasUsed": 88129 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 60882 + "gasUsed": 58788 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 54136 + "gasUsed": 52106 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 81476 + "gasUsed": 79382 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 127343 + "gasUsed": 122458 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 76054 + "gasUsed": 74024 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 648531 + "gasUsed": 641185 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 37631 + "gasUsed": 37035 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 35625 + "gasUsed": 35029 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 27929 + "gasUsed": 25333 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 15042 + "gasUsed": 14446 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 31284 + "gasUsed": 28688 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 18489 + "gasUsed": 17893 } ] diff --git a/packages/world/src/AccessControl.sol b/packages/world/src/AccessControl.sol index ca637f7c3f..d99fd415ef 100644 --- a/packages/world/src/AccessControl.sol +++ b/packages/world/src/AccessControl.sol @@ -16,8 +16,8 @@ library AccessControl { function hasAccess(bytes32 resourceSelector, address caller) internal view returns (bool) { return address(this) == caller || // First check if the World is calling itself - ResourceAccess.get(resourceSelector.getNamespace(), caller) || // Then check access based on the namespace - ResourceAccess.get(resourceSelector, caller); // If caller has no namespace access, check access on the name + ResourceAccess._get(resourceSelector.getNamespace(), caller) || // Then check access based on the namespace + ResourceAccess._get(resourceSelector, caller); // If caller has no namespace access, check access on the name } /** @@ -36,7 +36,7 @@ library AccessControl { * Reverts with AccessDenied if the check fails. */ function requireOwner(bytes32 resourceSelector, address caller) internal view { - if (NamespaceOwner.get(resourceSelector.getNamespace()) != caller) { + if (NamespaceOwner._get(resourceSelector.getNamespace()) != caller) { revert IWorldErrors.AccessDenied(resourceSelector.toString(), caller); } } diff --git a/packages/world/src/SystemCall.sol b/packages/world/src/SystemCall.sol index d5bdf7f53f..f2863b00c4 100644 --- a/packages/world/src/SystemCall.sol +++ b/packages/world/src/SystemCall.sol @@ -34,7 +34,7 @@ library SystemCall { bytes memory funcSelectorAndArgs ) internal returns (bool success, bytes memory data) { // Load the system data - (address systemAddress, bool publicAccess) = Systems.get(resourceSelector); + (address systemAddress, bool publicAccess) = Systems._get(resourceSelector); // Check if the system exists if (systemAddress == address(0)) revert IWorldErrors.ResourceNotFound(resourceSelector.toString()); @@ -45,8 +45,8 @@ library SystemCall { // If the msg.value is non-zero, update the namespace's balance if (value > 0) { bytes16 namespace = resourceSelector.getNamespace(); - uint256 currentBalance = Balances.get(namespace); - Balances.set(namespace, currentBalance + value); + uint256 currentBalance = Balances._get(namespace); + Balances._set(namespace, currentBalance + value); } // Call the system and forward any return data @@ -76,7 +76,7 @@ library SystemCall { uint256 value ) internal returns (bool success, bytes memory data) { // Get system hooks - bytes21[] memory hooks = SystemHooks.get(resourceSelector); + bytes21[] memory hooks = SystemHooks._get(resourceSelector); // Call onBeforeCallSystem hooks (before calling the system) for (uint256 i; i < hooks.length; i++) { diff --git a/packages/world/src/World.sol b/packages/world/src/World.sol index f813a96f46..bc3895dd1e 100644 --- a/packages/world/src/World.sol +++ b/packages/world/src/World.sol @@ -54,7 +54,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { } // The World can only be initialized once - if (InstalledModules.get(CORE_MODULE_NAME, keccak256("")) != address(0)) { + if (InstalledModules._get(CORE_MODULE_NAME, keccak256("")) != address(0)) { revert WorldAlreadyInitialized(); } @@ -84,7 +84,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { }); // Register the module in the InstalledModules table - InstalledModules.set(module.getName(), keccak256(args), address(module)); + InstalledModules._set(module.getName(), keccak256(args), address(module)); } /************************************************************************ @@ -229,7 +229,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { } // Check if there is an explicit authorization for this caller to perform actions on behalf of the delegator - Delegation explicitDelegation = Delegation.wrap(Delegations.get({ delegator: delegator, delegatee: msg.sender })); + Delegation explicitDelegation = Delegation.wrap(Delegations._get({ delegator: delegator, delegatee: msg.sender })); if (explicitDelegation.verify(delegator, msg.sender, resourceSelector, funcSelectorAndArgs)) { // forward the call as `delegator` @@ -237,7 +237,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { } // Check if the delegator has a fallback delegation control set - Delegation fallbackDelegation = Delegation.wrap(Delegations.get({ delegator: delegator, delegatee: address(0) })); + Delegation fallbackDelegation = Delegation.wrap(Delegations._get({ delegator: delegator, delegatee: address(0) })); if (fallbackDelegation.verify(delegator, msg.sender, resourceSelector, funcSelectorAndArgs)) { // forward the call with `from` as `msgSender` return SystemCall.callWithHooksOrRevert(delegator, resourceSelector, funcSelectorAndArgs, msg.value); @@ -256,15 +256,15 @@ contract World is StoreRead, IStoreData, IWorldKernel { * ETH sent to the World without calldata is added to the root namespace's balance */ receive() external payable { - uint256 rootBalance = Balances.get(ROOT_NAMESPACE); - Balances.set(ROOT_NAMESPACE, rootBalance + msg.value); + uint256 rootBalance = Balances._get(ROOT_NAMESPACE); + Balances._set(ROOT_NAMESPACE, rootBalance + msg.value); } /** * Fallback function to call registered function selectors */ fallback() external payable { - (bytes32 resourceSelector, bytes4 systemFunctionSelector) = FunctionSelectors.get(msg.sig); + (bytes32 resourceSelector, bytes4 systemFunctionSelector) = FunctionSelectors._get(msg.sig); if (resourceSelector == 0) revert FunctionSelectorNotFound(msg.sig); diff --git a/packages/world/src/modules/core/CoreModule.sol b/packages/world/src/modules/core/CoreModule.sol index aaf34ff19e..a9712b4576 100644 --- a/packages/world/src/modules/core/CoreModule.sol +++ b/packages/world/src/modules/core/CoreModule.sol @@ -76,9 +76,9 @@ contract CoreModule is Module { SystemRegistry.register(); ResourceType.register(); - NamespaceOwner.set(ROOT_NAMESPACE, _msgSender()); - ResourceAccess.set(ROOT_NAMESPACE, _msgSender(), true); - ResourceType.set(ROOT_NAMESPACE, Resource.NAMESPACE); + NamespaceOwner._set(ROOT_NAMESPACE, _msgSender()); + ResourceAccess._set(ROOT_NAMESPACE, _msgSender(), true); + ResourceType._set(ROOT_NAMESPACE, Resource.NAMESPACE); } /** diff --git a/packages/world/src/modules/core/implementations/AccessManagementSystem.sol b/packages/world/src/modules/core/implementations/AccessManagementSystem.sol index c29d693ac0..cff47dd2db 100644 --- a/packages/world/src/modules/core/implementations/AccessManagementSystem.sol +++ b/packages/world/src/modules/core/implementations/AccessManagementSystem.sol @@ -22,7 +22,7 @@ contract AccessManagementSystem is System { AccessControl.requireOwner(resourceSelector, _msgSender()); // Grant access to the given resource - ResourceAccess.set(resourceSelector, grantee, true); + ResourceAccess._set(resourceSelector, grantee, true); } /** @@ -34,7 +34,7 @@ contract AccessManagementSystem is System { AccessControl.requireOwner(resourceSelector, _msgSender()); // Revoke access from the given resource - ResourceAccess.deleteRecord(resourceSelector, grantee); + ResourceAccess._deleteRecord(resourceSelector, grantee); } /** @@ -47,12 +47,12 @@ contract AccessManagementSystem is System { AccessControl.requireOwner(namespace, _msgSender()); // Set namespace new owner - NamespaceOwner.set(namespace, newOwner); + NamespaceOwner._set(namespace, newOwner); // Revoke access from old owner - ResourceAccess.deleteRecord(namespace, _msgSender()); + ResourceAccess._deleteRecord(namespace, _msgSender()); // Grant access to new owner - ResourceAccess.set(namespace, newOwner, true); + ResourceAccess._set(namespace, newOwner, true); } } diff --git a/packages/world/src/modules/core/implementations/BalanceTransferSystem.sol b/packages/world/src/modules/core/implementations/BalanceTransferSystem.sol index d57cc82a6c..9f0fdde1cd 100644 --- a/packages/world/src/modules/core/implementations/BalanceTransferSystem.sol +++ b/packages/world/src/modules/core/implementations/BalanceTransferSystem.sol @@ -20,14 +20,14 @@ contract BalanceTransferSystem is System, IWorldErrors { AccessControl.requireAccess(fromNamespace, _msgSender()); // Get current namespace balance - uint256 balance = Balances.get(fromNamespace); + uint256 balance = Balances._get(fromNamespace); // Require the balance balance to be greater or equal to the amount to transfer if (amount > balance) revert InsufficientBalance(balance, amount); // Update the balances - Balances.set(fromNamespace, balance - amount); - Balances.set(toNamespace, Balances.get(toNamespace) + amount); + Balances._set(fromNamespace, balance - amount); + Balances._set(toNamespace, Balances._get(toNamespace) + amount); } /** @@ -38,13 +38,13 @@ contract BalanceTransferSystem is System, IWorldErrors { AccessControl.requireAccess(fromNamespace, _msgSender()); // Get current namespace balance - uint256 balance = Balances.get(fromNamespace); + uint256 balance = Balances._get(fromNamespace); // Require the balance balance to be greater or equal to the amount to transfer if (amount > balance) revert InsufficientBalance(balance, amount); // Update the balances - Balances.set(fromNamespace, balance - amount); + Balances._set(fromNamespace, balance - amount); // Transfer the balance to the given address, revert on failure (bool success, bytes memory data) = payable(toAddress).call{ value: amount }(""); diff --git a/packages/world/src/modules/core/implementations/ModuleInstallationSystem.sol b/packages/world/src/modules/core/implementations/ModuleInstallationSystem.sol index ebd21ed856..80a004975a 100644 --- a/packages/world/src/modules/core/implementations/ModuleInstallationSystem.sol +++ b/packages/world/src/modules/core/implementations/ModuleInstallationSystem.sol @@ -28,6 +28,6 @@ contract ModuleInstallationSystem is System { }); // Register the module in the InstalledModules table - InstalledModules.set(module.getName(), keccak256(args), address(module)); + InstalledModules._set(module.getName(), keccak256(args), address(module)); } } diff --git a/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol b/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol index 00a5d3017c..eacfff6087 100644 --- a/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol @@ -49,10 +49,10 @@ contract StoreRegistrationSystem is System, IWorldErrors { // If the namespace doesn't exist yet, register it bytes16 namespace = resourceSelector.getNamespace(); - if (ResourceType.get(namespace) == Resource.NONE) { + if (ResourceType._get(namespace) == Resource.NONE) { // We can't call IBaseWorld(this).registerNamespace directly because it would be handled like // an external call, so msg.sender would be the address of the World contract - (address systemAddress, ) = Systems.get(ResourceSelector.from(ROOT_NAMESPACE, CORE_SYSTEM_NAME)); + (address systemAddress, ) = Systems._get(ResourceSelector.from(ROOT_NAMESPACE, CORE_SYSTEM_NAME)); WorldContextProvider.delegatecallWithContextOrRevert({ msgSender: _msgSender(), msgValue: 0, @@ -65,12 +65,12 @@ contract StoreRegistrationSystem is System, IWorldErrors { } // Require no resource to exist at this selector yet - if (ResourceType.get(resourceSelector) != Resource.NONE) { + if (ResourceType._get(resourceSelector) != Resource.NONE) { revert ResourceExists(resourceSelector.toString()); } // Store the table resource type - ResourceType.set(resourceSelector, Resource.TABLE); + ResourceType._set(resourceSelector, Resource.TABLE); // Register the table StoreCore.registerTable(resourceSelector, fieldLayout, keySchema, valueSchema, keyNames, fieldNames); diff --git a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol index 2d018ae0fb..3502e5bd6c 100644 --- a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol @@ -39,16 +39,16 @@ contract WorldRegistrationSystem is System, IWorldErrors { bytes32 resourceSelector = ResourceSelector.from(namespace); // Require namespace to not exist yet - if (ResourceType.get(namespace) != Resource.NONE) revert ResourceExists(resourceSelector.toString()); + if (ResourceType._get(namespace) != Resource.NONE) revert ResourceExists(resourceSelector.toString()); // Register namespace resource - ResourceType.set(namespace, Resource.NAMESPACE); + ResourceType._set(namespace, Resource.NAMESPACE); // Register caller as the namespace owner - NamespaceOwner.set(namespace, _msgSender()); + NamespaceOwner._set(namespace, _msgSender()); // Give caller access to the new namespace - ResourceAccess.set(resourceSelector, _msgSender(), true); + ResourceAccess._set(resourceSelector, _msgSender(), true); } /** @@ -97,7 +97,7 @@ contract WorldRegistrationSystem is System, IWorldErrors { if (resourceSelector.getName() == ROOT_NAME) revert InvalidSelector(resourceSelector.toString()); // Require this system to not be registered at a different resource selector yet - bytes32 existingResourceSelector = SystemRegistry.get(address(system)); + bytes32 existingResourceSelector = SystemRegistry._get(address(system)); if (existingResourceSelector != 0 && existingResourceSelector != resourceSelector) { revert SystemExists(address(system)); } @@ -105,38 +105,38 @@ contract WorldRegistrationSystem is System, IWorldErrors { // If the namespace doesn't exist yet, register it // otherwise require caller to own the namespace bytes16 namespace = resourceSelector.getNamespace(); - if (ResourceType.get(namespace) == Resource.NONE) registerNamespace(namespace); + if (ResourceType._get(namespace) == Resource.NONE) registerNamespace(namespace); else AccessControl.requireOwner(namespace, _msgSender()); // Require no resource other than a system to exist at this selector yet - Resource resourceType = ResourceType.get(resourceSelector); + Resource resourceType = ResourceType._get(resourceSelector); if (resourceType != Resource.NONE && resourceType != Resource.SYSTEM) { revert ResourceExists(resourceSelector.toString()); } // Check if a system already exists at this resource selector - address existingSystem = Systems.getSystem(resourceSelector); + address existingSystem = Systems._getSystem(resourceSelector); // If there is an existing system with this resource selector, remove it if (existingSystem != address(0)) { // Remove the existing system from the system registry - SystemRegistry.deleteRecord(existingSystem); + SystemRegistry._deleteRecord(existingSystem); // Remove the existing system's access to its namespace - ResourceAccess.deleteRecord(namespace, existingSystem); + ResourceAccess._deleteRecord(namespace, existingSystem); } else { // Otherwise, this is a new system, so register its resource type - ResourceType.set(resourceSelector, Resource.SYSTEM); + ResourceType._set(resourceSelector, Resource.SYSTEM); } // Systems = mapping from resourceSelector to system address and publicAccess - Systems.set(resourceSelector, address(system), publicAccess); + Systems._set(resourceSelector, address(system), publicAccess); // SystemRegistry = mapping from system address to resourceSelector - SystemRegistry.set(address(system), resourceSelector); + SystemRegistry._set(address(system), resourceSelector); // Grant the system access to its namespace - ResourceAccess.set(namespace, address(system), true); + ResourceAccess._set(namespace, address(system), true); } /** @@ -162,7 +162,7 @@ contract WorldRegistrationSystem is System, IWorldErrors { ); // Require the function selector to be globally unique - bytes32 existingResourceSelector = FunctionSelectors.getResourceSelector(worldFunctionSelector); + bytes32 existingResourceSelector = FunctionSelectors._getResourceSelector(worldFunctionSelector); if (existingResourceSelector != 0) revert FunctionSelectorExists(worldFunctionSelector); @@ -171,7 +171,7 @@ contract WorldRegistrationSystem is System, IWorldErrors { bytes4 systemFunctionSelector = systemFunctionSignature.length == 0 ? bytes4(0) // Save gas by storing 0x0 for empty function signatures (= fallback function) : bytes4(keccak256(systemFunctionSignature)); - FunctionSelectors.set(worldFunctionSelector, resourceSelector, systemFunctionSelector); + FunctionSelectors._set(worldFunctionSelector, resourceSelector, systemFunctionSelector); } /** @@ -190,12 +190,12 @@ contract WorldRegistrationSystem is System, IWorldErrors { AccessControl.requireOwner(ROOT_NAMESPACE, _msgSender()); // Require the function selector to be globally unique - bytes32 existingResourceSelector = FunctionSelectors.getResourceSelector(worldFunctionSelector); + bytes32 existingResourceSelector = FunctionSelectors._getResourceSelector(worldFunctionSelector); if (existingResourceSelector != 0) revert FunctionSelectorExists(worldFunctionSelector); // Register the function selector - FunctionSelectors.set(worldFunctionSelector, resourceSelector, systemFunctionSelector); + FunctionSelectors._set(worldFunctionSelector, resourceSelector, systemFunctionSelector); return worldFunctionSelector; } @@ -214,7 +214,7 @@ contract WorldRegistrationSystem is System, IWorldErrors { // If the delegation is not unlimited... if (delegationControlId != UNLIMITED_DELEGATION && initFuncSelectorAndArgs.length > 0) { // Require the delegationControl contract to implement the IDelegationControl interface - (address delegationControl, ) = Systems.get(delegationControlId); + (address delegationControl, ) = Systems._get(delegationControlId); requireInterface(delegationControl, DELEGATION_CONTROL_INTERFACE_ID); // Call the delegation control contract's init function diff --git a/packages/world/src/modules/core/tables/Balances.sol b/packages/world/src/modules/core/tables/Balances.sol index 280b77ae71..e87221fb49 100644 --- a/packages/world/src/modules/core/tables/Balances.sol +++ b/packages/world/src/modules/core/tables/Balances.sol @@ -64,6 +64,11 @@ library Balances { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -78,6 +83,15 @@ library Balances { return (uint256(bytes32(_blob))); } + /** Get balance */ + function _get(bytes16 namespace) internal view returns (uint256 balance) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(namespace); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); + } + /** Get balance (using the specified store) */ function get(IStore _store, bytes16 namespace) internal view returns (uint256 balance) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -95,6 +109,14 @@ library Balances { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); } + /** Set balance */ + function _set(bytes16 namespace, uint256 balance) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(namespace); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((balance)), _fieldLayout); + } + /** Set balance (using the specified store) */ function set(IStore _store, bytes16 namespace, uint256 balance) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -134,6 +156,14 @@ library Balances { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes16 namespace) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(namespace); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes16 namespace) internal { bytes32[] memory _keyTuple = new bytes32[](1); diff --git a/packages/world/src/modules/core/tables/FunctionSelectors.sol b/packages/world/src/modules/core/tables/FunctionSelectors.sol index 28ee846849..036335865a 100644 --- a/packages/world/src/modules/core/tables/FunctionSelectors.sol +++ b/packages/world/src/modules/core/tables/FunctionSelectors.sol @@ -66,6 +66,11 @@ library FunctionSelectors { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -80,6 +85,15 @@ library FunctionSelectors { return (bytes32(_blob)); } + /** Get resourceSelector */ + function _getResourceSelector(bytes4 functionSelector) internal view returns (bytes32 resourceSelector) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(functionSelector); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); + } + /** Get resourceSelector (using the specified store) */ function getResourceSelector( IStore _store, @@ -100,6 +114,14 @@ library FunctionSelectors { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); } + /** Set resourceSelector */ + function _setResourceSelector(bytes4 functionSelector, bytes32 resourceSelector) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(functionSelector); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + } + /** Set resourceSelector (using the specified store) */ function setResourceSelector(IStore _store, bytes4 functionSelector, bytes32 resourceSelector) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -117,6 +139,15 @@ library FunctionSelectors { return (bytes4(_blob)); } + /** Get systemFunctionSelector */ + function _getSystemFunctionSelector(bytes4 functionSelector) internal view returns (bytes4 systemFunctionSelector) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(functionSelector); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (bytes4(_blob)); + } + /** Get systemFunctionSelector (using the specified store) */ function getSystemFunctionSelector( IStore _store, @@ -137,6 +168,14 @@ library FunctionSelectors { StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((systemFunctionSelector)), _fieldLayout); } + /** Set systemFunctionSelector */ + function _setSystemFunctionSelector(bytes4 functionSelector, bytes4 systemFunctionSelector) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(functionSelector); + + StoreCore.setField(_tableId, _keyTuple, 1, abi.encodePacked((systemFunctionSelector)), _fieldLayout); + } + /** Set systemFunctionSelector (using the specified store) */ function setSystemFunctionSelector(IStore _store, bytes4 functionSelector, bytes4 systemFunctionSelector) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -156,6 +195,17 @@ library FunctionSelectors { return decode(_blob); } + /** Get the full data */ + function _get( + bytes4 functionSelector + ) internal view returns (bytes32 resourceSelector, bytes4 systemFunctionSelector) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(functionSelector); + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get( IStore _store, @@ -181,6 +231,19 @@ library FunctionSelectors { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set(bytes4 functionSelector, bytes32 resourceSelector, bytes4 systemFunctionSelector) internal { + bytes memory _staticData = encodeStatic(resourceSelector, systemFunctionSelector); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(functionSelector); + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set( IStore _store, @@ -237,6 +300,14 @@ library FunctionSelectors { 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); diff --git a/packages/world/src/modules/core/tables/ResourceType.sol b/packages/world/src/modules/core/tables/ResourceType.sol index 4dd272567b..0fb6a1c293 100644 --- a/packages/world/src/modules/core/tables/ResourceType.sol +++ b/packages/world/src/modules/core/tables/ResourceType.sol @@ -67,6 +67,11 @@ library ResourceType { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -81,6 +86,15 @@ library ResourceType { return Resource(uint8(bytes1(_blob))); } + /** Get resourceType */ + function _get(bytes32 resourceSelector) internal view returns (Resource resourceType) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return Resource(uint8(bytes1(_blob))); + } + /** Get resourceType (using the specified store) */ function get(IStore _store, bytes32 resourceSelector) internal view returns (Resource resourceType) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -98,6 +112,14 @@ library ResourceType { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), _fieldLayout); } + /** Set resourceType */ + function _set(bytes32 resourceSelector, Resource resourceType) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked(uint8(resourceType)), _fieldLayout); + } + /** Set resourceType (using the specified store) */ function set(IStore _store, bytes32 resourceSelector, Resource resourceType) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -137,6 +159,14 @@ library ResourceType { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes32 resourceSelector) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes32 resourceSelector) internal { bytes32[] memory _keyTuple = new bytes32[](1); diff --git a/packages/world/src/modules/core/tables/SystemHooks.sol b/packages/world/src/modules/core/tables/SystemHooks.sol index 1314088f74..a322e22ced 100644 --- a/packages/world/src/modules/core/tables/SystemHooks.sol +++ b/packages/world/src/modules/core/tables/SystemHooks.sol @@ -64,6 +64,11 @@ library SystemHooks { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -78,6 +83,15 @@ library SystemHooks { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); } + /** Get value */ + function _get(bytes32 resourceSelector) internal view returns (bytes21[] memory value) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes21()); + } + /** Get value (using the specified store) */ function get(IStore _store, bytes32 resourceSelector) internal view returns (bytes21[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -95,6 +109,14 @@ library SystemHooks { StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } + /** Set value */ + function _set(bytes32 resourceSelector, bytes21[] memory value) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, bytes32 resourceSelector, bytes21[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -114,6 +136,17 @@ library SystemHooks { } } + /** Get the length of value */ + function _length(bytes32 resourceSelector) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); + unchecked { + return _byteLength / 21; + } + } + /** Get the length of value (using the specified store) */ function length(IStore _store, bytes32 resourceSelector) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -146,6 +179,27 @@ library SystemHooks { } } + /** + * Get an item of value + * (unchecked, returns invalid data if index overflows) + */ + function _getItem(bytes32 resourceSelector, uint256 _index) internal view returns (bytes21) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 0, + _fieldLayout, + _index * 21, + (_index + 1) * 21 + ); + return (bytes21(_blob)); + } + } + /** * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -168,6 +222,14 @@ library SystemHooks { StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to value */ + function _push(bytes32 resourceSelector, bytes21 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to value (using the specified store) */ function push(IStore _store, bytes32 resourceSelector, bytes21 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -184,6 +246,14 @@ library SystemHooks { StoreSwitch.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); } + /** Pop an element from value */ + function _pop(bytes32 resourceSelector) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + StoreCore.popFromField(_tableId, _keyTuple, 0, 21, _fieldLayout); + } + /** Pop an element from value (using the specified store) */ function pop(IStore _store, bytes32 resourceSelector) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -205,6 +275,19 @@ library SystemHooks { } } + /** + * Update an element of value at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _update(bytes32 resourceSelector, uint256 _index, bytes21 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 21, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -256,6 +339,14 @@ library SystemHooks { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes32 resourceSelector) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes32 resourceSelector) internal { bytes32[] memory _keyTuple = new bytes32[](1); diff --git a/packages/world/src/modules/core/tables/SystemRegistry.sol b/packages/world/src/modules/core/tables/SystemRegistry.sol index e27e2fdd95..42f7311644 100644 --- a/packages/world/src/modules/core/tables/SystemRegistry.sol +++ b/packages/world/src/modules/core/tables/SystemRegistry.sol @@ -64,6 +64,11 @@ library SystemRegistry { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -78,6 +83,15 @@ library SystemRegistry { return (bytes32(_blob)); } + /** Get resourceSelector */ + function _get(address system) internal view returns (bytes32 resourceSelector) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(uint160(system))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); + } + /** Get resourceSelector (using the specified store) */ function get(IStore _store, address system) internal view returns (bytes32 resourceSelector) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -95,6 +109,14 @@ library SystemRegistry { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); } + /** Set resourceSelector */ + function _set(address system, bytes32 resourceSelector) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(uint256(uint160(system))); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((resourceSelector)), _fieldLayout); + } + /** Set resourceSelector (using the specified store) */ function set(IStore _store, address system, bytes32 resourceSelector) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -134,6 +156,14 @@ library SystemRegistry { 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); diff --git a/packages/world/src/modules/core/tables/Systems.sol b/packages/world/src/modules/core/tables/Systems.sol index edffc1d222..f60421fce5 100644 --- a/packages/world/src/modules/core/tables/Systems.sol +++ b/packages/world/src/modules/core/tables/Systems.sol @@ -66,6 +66,11 @@ library Systems { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -80,6 +85,15 @@ library Systems { return (address(bytes20(_blob))); } + /** Get system */ + function _getSystem(bytes32 resourceSelector) internal view returns (address system) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (address(bytes20(_blob))); + } + /** Get system (using the specified store) */ function getSystem(IStore _store, bytes32 resourceSelector) internal view returns (address system) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -97,6 +111,14 @@ library Systems { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((system)), _fieldLayout); } + /** Set system */ + function _setSystem(bytes32 resourceSelector, address system) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((system)), _fieldLayout); + } + /** Set system (using the specified store) */ function setSystem(IStore _store, bytes32 resourceSelector, address system) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -114,6 +136,15 @@ library Systems { return (_toBool(uint8(bytes1(_blob)))); } + /** Get publicAccess */ + function _getPublicAccess(bytes32 resourceSelector) internal view returns (bool publicAccess) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + /** Get publicAccess (using the specified store) */ function getPublicAccess(IStore _store, bytes32 resourceSelector) internal view returns (bool publicAccess) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -131,6 +162,14 @@ library Systems { StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((publicAccess)), _fieldLayout); } + /** Set publicAccess */ + function _setPublicAccess(bytes32 resourceSelector, bool publicAccess) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + StoreCore.setField(_tableId, _keyTuple, 1, abi.encodePacked((publicAccess)), _fieldLayout); + } + /** Set publicAccess (using the specified store) */ function setPublicAccess(IStore _store, bytes32 resourceSelector, bool publicAccess) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -148,6 +187,15 @@ library Systems { return decode(_blob); } + /** Get the full data */ + function _get(bytes32 resourceSelector) internal view returns (address system, bool publicAccess) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, bytes32 resourceSelector) internal view returns (address system, bool publicAccess) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -170,6 +218,19 @@ library Systems { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set(bytes32 resourceSelector, address system, bool publicAccess) internal { + bytes memory _staticData = encodeStatic(system, publicAccess); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 resourceSelector, address system, bool publicAccess) internal { bytes memory _staticData = encodeStatic(system, publicAccess); @@ -221,6 +282,14 @@ library Systems { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes32 resourceSelector) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = resourceSelector; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes32 resourceSelector) internal { bytes32[] memory _keyTuple = new bytes32[](1); diff --git a/packages/world/src/modules/keysintable/tables/KeysInTable.sol b/packages/world/src/modules/keysintable/tables/KeysInTable.sol index c18a7915d5..5ba1921b92 100644 --- a/packages/world/src/modules/keysintable/tables/KeysInTable.sol +++ b/packages/world/src/modules/keysintable/tables/KeysInTable.sol @@ -80,6 +80,11 @@ library KeysInTable { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -94,6 +99,15 @@ library KeysInTable { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } + /** Get keys0 */ + function _getKeys0(bytes32 sourceTable) internal view returns (bytes32[] memory keys0) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); + } + /** Get keys0 (using the specified store) */ function getKeys0(IStore _store, bytes32 sourceTable) internal view returns (bytes32[] memory keys0) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -111,6 +125,14 @@ library KeysInTable { StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keys0)), _fieldLayout); } + /** Set keys0 */ + function _setKeys0(bytes32 sourceTable, bytes32[] memory keys0) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keys0)), _fieldLayout); + } + /** Set keys0 (using the specified store) */ function setKeys0(IStore _store, bytes32 sourceTable, bytes32[] memory keys0) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -130,6 +152,17 @@ library KeysInTable { } } + /** Get the length of keys0 */ + function _lengthKeys0(bytes32 sourceTable) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); + unchecked { + return _byteLength / 32; + } + } + /** Get the length of keys0 (using the specified store) */ function lengthKeys0(IStore _store, bytes32 sourceTable) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -162,6 +195,27 @@ library KeysInTable { } } + /** + * Get an item of keys0 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemKeys0(bytes32 sourceTable, uint256 _index) internal view returns (bytes32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 0, + _fieldLayout, + _index * 32, + (_index + 1) * 32 + ); + return (bytes32(_blob)); + } + } + /** * Get an item of keys0 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -184,6 +238,14 @@ library KeysInTable { StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to keys0 */ + function _pushKeys0(bytes32 sourceTable, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to keys0 (using the specified store) */ function pushKeys0(IStore _store, bytes32 sourceTable, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -200,6 +262,14 @@ library KeysInTable { StoreSwitch.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); } + /** Pop an element from keys0 */ + function _popKeys0(bytes32 sourceTable) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); + } + /** Pop an element from keys0 (using the specified store) */ function popKeys0(IStore _store, bytes32 sourceTable) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -221,6 +291,19 @@ library KeysInTable { } } + /** + * Update an element of keys0 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateKeys0(bytes32 sourceTable, uint256 _index, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of keys0 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -243,6 +326,15 @@ library KeysInTable { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } + /** Get keys1 */ + function _getKeys1(bytes32 sourceTable) internal view returns (bytes32[] memory keys1) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 1); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); + } + /** Get keys1 (using the specified store) */ function getKeys1(IStore _store, bytes32 sourceTable) internal view returns (bytes32[] memory keys1) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -260,6 +352,14 @@ library KeysInTable { StoreSwitch.setField(_tableId, _keyTuple, 1, EncodeArray.encode((keys1)), _fieldLayout); } + /** Set keys1 */ + function _setKeys1(bytes32 sourceTable, bytes32[] memory keys1) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.setField(_tableId, _keyTuple, 1, EncodeArray.encode((keys1)), _fieldLayout); + } + /** Set keys1 (using the specified store) */ function setKeys1(IStore _store, bytes32 sourceTable, bytes32[] memory keys1) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -279,6 +379,17 @@ library KeysInTable { } } + /** Get the length of keys1 */ + function _lengthKeys1(bytes32 sourceTable) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 1, _fieldLayout); + unchecked { + return _byteLength / 32; + } + } + /** Get the length of keys1 (using the specified store) */ function lengthKeys1(IStore _store, bytes32 sourceTable) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -311,6 +422,27 @@ library KeysInTable { } } + /** + * Get an item of keys1 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemKeys1(bytes32 sourceTable, uint256 _index) internal view returns (bytes32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 1, + _fieldLayout, + _index * 32, + (_index + 1) * 32 + ); + return (bytes32(_blob)); + } + } + /** * Get an item of keys1 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -333,6 +465,14 @@ library KeysInTable { StoreSwitch.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to keys1 */ + function _pushKeys1(bytes32 sourceTable, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.pushToField(_tableId, _keyTuple, 1, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to keys1 (using the specified store) */ function pushKeys1(IStore _store, bytes32 sourceTable, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -349,6 +489,14 @@ library KeysInTable { StoreSwitch.popFromField(_tableId, _keyTuple, 1, 32, _fieldLayout); } + /** Pop an element from keys1 */ + function _popKeys1(bytes32 sourceTable) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.popFromField(_tableId, _keyTuple, 1, 32, _fieldLayout); + } + /** Pop an element from keys1 (using the specified store) */ function popKeys1(IStore _store, bytes32 sourceTable) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -370,6 +518,19 @@ library KeysInTable { } } + /** + * Update an element of keys1 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateKeys1(bytes32 sourceTable, uint256 _index, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 1, _index * 32, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of keys1 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -392,6 +553,15 @@ library KeysInTable { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } + /** Get keys2 */ + function _getKeys2(bytes32 sourceTable) internal view returns (bytes32[] memory keys2) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 2); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); + } + /** Get keys2 (using the specified store) */ function getKeys2(IStore _store, bytes32 sourceTable) internal view returns (bytes32[] memory keys2) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -409,6 +579,14 @@ library KeysInTable { StoreSwitch.setField(_tableId, _keyTuple, 2, EncodeArray.encode((keys2)), _fieldLayout); } + /** Set keys2 */ + function _setKeys2(bytes32 sourceTable, bytes32[] memory keys2) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.setField(_tableId, _keyTuple, 2, EncodeArray.encode((keys2)), _fieldLayout); + } + /** Set keys2 (using the specified store) */ function setKeys2(IStore _store, bytes32 sourceTable, bytes32[] memory keys2) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -428,6 +606,17 @@ library KeysInTable { } } + /** Get the length of keys2 */ + function _lengthKeys2(bytes32 sourceTable) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 2, _fieldLayout); + unchecked { + return _byteLength / 32; + } + } + /** Get the length of keys2 (using the specified store) */ function lengthKeys2(IStore _store, bytes32 sourceTable) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -460,6 +649,27 @@ library KeysInTable { } } + /** + * Get an item of keys2 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemKeys2(bytes32 sourceTable, uint256 _index) internal view returns (bytes32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 2, + _fieldLayout, + _index * 32, + (_index + 1) * 32 + ); + return (bytes32(_blob)); + } + } + /** * Get an item of keys2 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -482,6 +692,14 @@ library KeysInTable { StoreSwitch.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to keys2 */ + function _pushKeys2(bytes32 sourceTable, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.pushToField(_tableId, _keyTuple, 2, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to keys2 (using the specified store) */ function pushKeys2(IStore _store, bytes32 sourceTable, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -498,6 +716,14 @@ library KeysInTable { StoreSwitch.popFromField(_tableId, _keyTuple, 2, 32, _fieldLayout); } + /** Pop an element from keys2 */ + function _popKeys2(bytes32 sourceTable) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.popFromField(_tableId, _keyTuple, 2, 32, _fieldLayout); + } + /** Pop an element from keys2 (using the specified store) */ function popKeys2(IStore _store, bytes32 sourceTable) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -519,6 +745,19 @@ library KeysInTable { } } + /** + * Update an element of keys2 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateKeys2(bytes32 sourceTable, uint256 _index, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 2, _index * 32, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of keys2 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -541,6 +780,15 @@ library KeysInTable { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } + /** Get keys3 */ + function _getKeys3(bytes32 sourceTable) internal view returns (bytes32[] memory keys3) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 3); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); + } + /** Get keys3 (using the specified store) */ function getKeys3(IStore _store, bytes32 sourceTable) internal view returns (bytes32[] memory keys3) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -558,6 +806,14 @@ library KeysInTable { StoreSwitch.setField(_tableId, _keyTuple, 3, EncodeArray.encode((keys3)), _fieldLayout); } + /** Set keys3 */ + function _setKeys3(bytes32 sourceTable, bytes32[] memory keys3) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.setField(_tableId, _keyTuple, 3, EncodeArray.encode((keys3)), _fieldLayout); + } + /** Set keys3 (using the specified store) */ function setKeys3(IStore _store, bytes32 sourceTable, bytes32[] memory keys3) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -577,6 +833,17 @@ library KeysInTable { } } + /** Get the length of keys3 */ + function _lengthKeys3(bytes32 sourceTable) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 3, _fieldLayout); + unchecked { + return _byteLength / 32; + } + } + /** Get the length of keys3 (using the specified store) */ function lengthKeys3(IStore _store, bytes32 sourceTable) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -609,6 +876,27 @@ library KeysInTable { } } + /** + * Get an item of keys3 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemKeys3(bytes32 sourceTable, uint256 _index) internal view returns (bytes32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 3, + _fieldLayout, + _index * 32, + (_index + 1) * 32 + ); + return (bytes32(_blob)); + } + } + /** * Get an item of keys3 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -631,6 +919,14 @@ library KeysInTable { StoreSwitch.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to keys3 */ + function _pushKeys3(bytes32 sourceTable, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.pushToField(_tableId, _keyTuple, 3, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to keys3 (using the specified store) */ function pushKeys3(IStore _store, bytes32 sourceTable, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -647,6 +943,14 @@ library KeysInTable { StoreSwitch.popFromField(_tableId, _keyTuple, 3, 32, _fieldLayout); } + /** Pop an element from keys3 */ + function _popKeys3(bytes32 sourceTable) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.popFromField(_tableId, _keyTuple, 3, 32, _fieldLayout); + } + /** Pop an element from keys3 (using the specified store) */ function popKeys3(IStore _store, bytes32 sourceTable) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -668,6 +972,19 @@ library KeysInTable { } } + /** + * Update an element of keys3 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateKeys3(bytes32 sourceTable, uint256 _index, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 3, _index * 32, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of keys3 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -690,6 +1007,15 @@ library KeysInTable { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } + /** Get keys4 */ + function _getKeys4(bytes32 sourceTable) internal view returns (bytes32[] memory keys4) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 4); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); + } + /** Get keys4 (using the specified store) */ function getKeys4(IStore _store, bytes32 sourceTable) internal view returns (bytes32[] memory keys4) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -707,6 +1033,14 @@ library KeysInTable { StoreSwitch.setField(_tableId, _keyTuple, 4, EncodeArray.encode((keys4)), _fieldLayout); } + /** Set keys4 */ + function _setKeys4(bytes32 sourceTable, bytes32[] memory keys4) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.setField(_tableId, _keyTuple, 4, EncodeArray.encode((keys4)), _fieldLayout); + } + /** Set keys4 (using the specified store) */ function setKeys4(IStore _store, bytes32 sourceTable, bytes32[] memory keys4) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -726,6 +1060,17 @@ library KeysInTable { } } + /** Get the length of keys4 */ + function _lengthKeys4(bytes32 sourceTable) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 4, _fieldLayout); + unchecked { + return _byteLength / 32; + } + } + /** Get the length of keys4 (using the specified store) */ function lengthKeys4(IStore _store, bytes32 sourceTable) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -758,6 +1103,27 @@ library KeysInTable { } } + /** + * Get an item of keys4 + * (unchecked, returns invalid data if index overflows) + */ + function _getItemKeys4(bytes32 sourceTable, uint256 _index) internal view returns (bytes32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 4, + _fieldLayout, + _index * 32, + (_index + 1) * 32 + ); + return (bytes32(_blob)); + } + } + /** * Get an item of keys4 (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -780,6 +1146,14 @@ library KeysInTable { StoreSwitch.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to keys4 */ + function _pushKeys4(bytes32 sourceTable, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.pushToField(_tableId, _keyTuple, 4, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to keys4 (using the specified store) */ function pushKeys4(IStore _store, bytes32 sourceTable, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -796,6 +1170,14 @@ library KeysInTable { StoreSwitch.popFromField(_tableId, _keyTuple, 4, 32, _fieldLayout); } + /** Pop an element from keys4 */ + function _popKeys4(bytes32 sourceTable) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.popFromField(_tableId, _keyTuple, 4, 32, _fieldLayout); + } + /** Pop an element from keys4 (using the specified store) */ function popKeys4(IStore _store, bytes32 sourceTable) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -817,6 +1199,19 @@ library KeysInTable { } } + /** + * Update an element of keys4 at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _updateKeys4(bytes32 sourceTable, uint256 _index, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 4, _index * 32, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of keys4 (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -839,6 +1234,15 @@ library KeysInTable { return decode(_blob); } + /** Get the full data */ + function _get(bytes32 sourceTable) internal view returns (KeysInTableData memory _table) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, bytes32 sourceTable) internal view returns (KeysInTableData memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -867,6 +1271,25 @@ library KeysInTable { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set( + bytes32 sourceTable, + bytes32[] memory keys0, + bytes32[] memory keys1, + bytes32[] memory keys2, + bytes32[] memory keys3, + bytes32[] memory keys4 + ) internal { + bytes memory _staticData; + PackedCounter _encodedLengths = encodeLengths(keys0, keys1, keys2, keys3, keys4); + bytes memory _dynamicData = encodeDynamic(keys0, keys1, keys2, keys3, keys4); + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = sourceTable; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set( IStore _store, @@ -892,6 +1315,11 @@ library KeysInTable { set(sourceTable, _table.keys0, _table.keys1, _table.keys2, _table.keys3, _table.keys4); } + /** Set the full data using the data struct */ + function _set(bytes32 sourceTable, KeysInTableData memory _table) internal { + set(sourceTable, _table.keys0, _table.keys1, _table.keys2, _table.keys3, _table.keys4); + } + /** Set the full data using the data struct (using the specified store) */ function set(IStore _store, bytes32 sourceTable, KeysInTableData memory _table) internal { set(_store, sourceTable, _table.keys0, _table.keys1, _table.keys2, _table.keys3, _table.keys4); @@ -1010,6 +1438,14 @@ library KeysInTable { 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); diff --git a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol index a0ab8dc9fd..c50753a03b 100644 --- a/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol +++ b/packages/world/src/modules/keysintable/tables/UsedKeysIndex.sol @@ -68,6 +68,11 @@ library UsedKeysIndex { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -83,6 +88,16 @@ library UsedKeysIndex { return (_toBool(uint8(bytes1(_blob)))); } + /** Get has */ + function _getHas(bytes32 sourceTable, bytes32 keysHash) internal view returns (bool has) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = sourceTable; + _keyTuple[1] = keysHash; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + /** Get has (using the specified store) */ function getHas(IStore _store, bytes32 sourceTable, bytes32 keysHash) internal view returns (bool has) { bytes32[] memory _keyTuple = new bytes32[](2); @@ -102,6 +117,15 @@ library UsedKeysIndex { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((has)), _fieldLayout); } + /** Set has */ + function _setHas(bytes32 sourceTable, bytes32 keysHash, bool has) internal { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = sourceTable; + _keyTuple[1] = keysHash; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((has)), _fieldLayout); + } + /** Set has (using the specified store) */ function setHas(IStore _store, bytes32 sourceTable, bytes32 keysHash, bool has) internal { bytes32[] memory _keyTuple = new bytes32[](2); @@ -121,6 +145,16 @@ library UsedKeysIndex { return (uint40(bytes5(_blob))); } + /** Get index */ + function _getIndex(bytes32 sourceTable, bytes32 keysHash) internal view returns (uint40 index) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = sourceTable; + _keyTuple[1] = keysHash; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint40(bytes5(_blob))); + } + /** Get index (using the specified store) */ function getIndex(IStore _store, bytes32 sourceTable, bytes32 keysHash) internal view returns (uint40 index) { bytes32[] memory _keyTuple = new bytes32[](2); @@ -140,6 +174,15 @@ library UsedKeysIndex { StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((index)), _fieldLayout); } + /** Set index */ + function _setIndex(bytes32 sourceTable, bytes32 keysHash, uint40 index) internal { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = sourceTable; + _keyTuple[1] = keysHash; + + StoreCore.setField(_tableId, _keyTuple, 1, abi.encodePacked((index)), _fieldLayout); + } + /** Set index (using the specified store) */ function setIndex(IStore _store, bytes32 sourceTable, bytes32 keysHash, uint40 index) internal { bytes32[] memory _keyTuple = new bytes32[](2); @@ -159,6 +202,16 @@ library UsedKeysIndex { return decode(_blob); } + /** Get the full data */ + function _get(bytes32 sourceTable, bytes32 keysHash) internal view returns (bool has, uint40 index) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = sourceTable; + _keyTuple[1] = keysHash; + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, bytes32 sourceTable, bytes32 keysHash) internal view returns (bool has, uint40 index) { bytes32[] memory _keyTuple = new bytes32[](2); @@ -183,6 +236,20 @@ library UsedKeysIndex { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set(bytes32 sourceTable, bytes32 keysHash, bool has, uint40 index) internal { + bytes memory _staticData = encodeStatic(has, index); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = sourceTable; + _keyTuple[1] = keysHash; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 sourceTable, bytes32 keysHash, bool has, uint40 index) internal { bytes memory _staticData = encodeStatic(has, index); @@ -237,6 +304,15 @@ library UsedKeysIndex { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes32 sourceTable, bytes32 keysHash) internal { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = sourceTable; + _keyTuple[1] = keysHash; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* 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); diff --git a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol index 9255f04f3f..76db05f36f 100644 --- a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol +++ b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol @@ -61,6 +61,11 @@ library KeysWithValue { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register(bytes32 _tableId) internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store, bytes32 _tableId) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -75,6 +80,15 @@ library KeysWithValue { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); } + /** Get keysWithValue */ + function _get(bytes32 _tableId, bytes32 valueHash) internal view returns (bytes32[] memory keysWithValue) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = valueHash; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); + } + /** Get keysWithValue (using the specified store) */ function get( IStore _store, @@ -96,6 +110,14 @@ library KeysWithValue { StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keysWithValue)), _fieldLayout); } + /** Set keysWithValue */ + function _set(bytes32 _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = valueHash; + + StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((keysWithValue)), _fieldLayout); + } + /** Set keysWithValue (using the specified store) */ function set(IStore _store, bytes32 _tableId, bytes32 valueHash, bytes32[] memory keysWithValue) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -115,6 +137,17 @@ library KeysWithValue { } } + /** Get the length of keysWithValue */ + function _length(bytes32 _tableId, bytes32 valueHash) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = valueHash; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); + unchecked { + return _byteLength / 32; + } + } + /** Get the length of keysWithValue (using the specified store) */ function length(IStore _store, bytes32 _tableId, bytes32 valueHash) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -147,6 +180,27 @@ library KeysWithValue { } } + /** + * Get an item of keysWithValue + * (unchecked, returns invalid data if index overflows) + */ + function _getItem(bytes32 _tableId, bytes32 valueHash, uint256 _index) internal view returns (bytes32) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = valueHash; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 0, + _fieldLayout, + _index * 32, + (_index + 1) * 32 + ); + return (bytes32(_blob)); + } + } + /** * Get an item of keysWithValue (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -169,6 +223,14 @@ library KeysWithValue { StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to keysWithValue */ + function _push(bytes32 _tableId, bytes32 valueHash, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = valueHash; + + StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to keysWithValue (using the specified store) */ function push(IStore _store, bytes32 _tableId, bytes32 valueHash, bytes32 _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -185,6 +247,14 @@ library KeysWithValue { StoreSwitch.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); } + /** Pop an element from keysWithValue */ + function _pop(bytes32 _tableId, bytes32 valueHash) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = valueHash; + + StoreCore.popFromField(_tableId, _keyTuple, 0, 32, _fieldLayout); + } + /** Pop an element from keysWithValue (using the specified store) */ function pop(IStore _store, bytes32 _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -206,6 +276,19 @@ library KeysWithValue { } } + /** + * Update an element of keysWithValue at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _update(bytes32 _tableId, bytes32 valueHash, uint256 _index, bytes32 _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = valueHash; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 32, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of keysWithValue (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -257,6 +340,14 @@ library KeysWithValue { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes32 _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, bytes32 _tableId, bytes32 valueHash) internal { bytes32[] memory _keyTuple = new bytes32[](1); diff --git a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol index 54d2f15682..f36c9e45b5 100644 --- a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol @@ -70,6 +70,11 @@ library CallboundDelegations { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -92,6 +97,23 @@ library CallboundDelegations { return (uint256(bytes32(_blob))); } + /** Get availableCalls */ + function _get( + address delegator, + address delegatee, + bytes32 resourceSelector, + bytes32 funcSelectorAndArgsHash + ) internal view returns (uint256 availableCalls) { + bytes32[] memory _keyTuple = new bytes32[](4); + _keyTuple[0] = bytes32(uint256(uint160(delegator))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + _keyTuple[2] = resourceSelector; + _keyTuple[3] = funcSelectorAndArgsHash; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); + } + /** Get availableCalls (using the specified store) */ function get( IStore _store, @@ -127,6 +149,23 @@ library CallboundDelegations { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); } + /** Set availableCalls */ + function _set( + address delegator, + address delegatee, + bytes32 resourceSelector, + bytes32 funcSelectorAndArgsHash, + uint256 availableCalls + ) internal { + bytes32[] memory _keyTuple = new bytes32[](4); + _keyTuple[0] = bytes32(uint256(uint160(delegator))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + _keyTuple[2] = resourceSelector; + _keyTuple[3] = funcSelectorAndArgsHash; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); + } + /** Set availableCalls (using the specified store) */ function set( IStore _store, @@ -192,6 +231,22 @@ library CallboundDelegations { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord( + address delegator, + address delegatee, + bytes32 resourceSelector, + bytes32 funcSelectorAndArgsHash + ) internal { + bytes32[] memory _keyTuple = new bytes32[](4); + _keyTuple[0] = bytes32(uint256(uint160(delegator))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + _keyTuple[2] = resourceSelector; + _keyTuple[3] = funcSelectorAndArgsHash; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* Delete all data for given keys (using the specified store) */ function deleteRecord( IStore _store, diff --git a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol index f751ad7f14..30a11520f3 100644 --- a/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/TimeboundDelegations.sol @@ -66,6 +66,11 @@ library TimeboundDelegations { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -81,6 +86,16 @@ library TimeboundDelegations { return (uint256(bytes32(_blob))); } + /** Get maxTimestamp */ + function _get(address delegator, address delegatee) internal view returns (uint256 maxTimestamp) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = bytes32(uint256(uint160(delegator))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); + } + /** Get maxTimestamp (using the specified store) */ function get(IStore _store, address delegator, address delegatee) internal view returns (uint256 maxTimestamp) { bytes32[] memory _keyTuple = new bytes32[](2); @@ -100,6 +115,15 @@ library TimeboundDelegations { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((maxTimestamp)), _fieldLayout); } + /** Set maxTimestamp */ + function _set(address delegator, address delegatee, uint256 maxTimestamp) internal { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = bytes32(uint256(uint160(delegator))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((maxTimestamp)), _fieldLayout); + } + /** Set maxTimestamp (using the specified store) */ function set(IStore _store, address delegator, address delegatee, uint256 maxTimestamp) internal { bytes32[] memory _keyTuple = new bytes32[](2); @@ -142,6 +166,15 @@ library TimeboundDelegations { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* 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))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* 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); diff --git a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol index a47b78e150..7c0fc191e7 100644 --- a/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol +++ b/packages/world/src/modules/uniqueentity/tables/UniqueEntity.sol @@ -59,6 +59,11 @@ library UniqueEntity { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register(bytes32 _tableId) internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store, bytes32 _tableId) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -72,6 +77,14 @@ library UniqueEntity { return (uint256(bytes32(_blob))); } + /** Get value */ + function _get(bytes32 _tableId) internal view returns (uint256 value) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); + } + /** Get value (using the specified store) */ function get(IStore _store, bytes32 _tableId) internal view returns (uint256 value) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -87,6 +100,13 @@ library UniqueEntity { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Set value */ + function _set(bytes32 _tableId, uint256 value) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, bytes32 _tableId, uint256 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -123,6 +143,13 @@ library UniqueEntity { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes32 _tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes32 _tableId) internal { bytes32[] memory _keyTuple = new bytes32[](0); diff --git a/packages/world/src/tables/Delegations.sol b/packages/world/src/tables/Delegations.sol index 2e0378a220..4226caa189 100644 --- a/packages/world/src/tables/Delegations.sol +++ b/packages/world/src/tables/Delegations.sol @@ -66,6 +66,11 @@ library Delegations { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -81,6 +86,16 @@ library Delegations { return (bytes32(_blob)); } + /** Get delegationControlId */ + function _get(address delegator, address delegatee) internal view returns (bytes32 delegationControlId) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = bytes32(uint256(uint160(delegator))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (bytes32(_blob)); + } + /** Get delegationControlId (using the specified store) */ function get( IStore _store, @@ -104,6 +119,15 @@ library Delegations { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((delegationControlId)), _fieldLayout); } + /** Set delegationControlId */ + function _set(address delegator, address delegatee, bytes32 delegationControlId) internal { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = bytes32(uint256(uint160(delegator))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((delegationControlId)), _fieldLayout); + } + /** Set delegationControlId (using the specified store) */ function set(IStore _store, address delegator, address delegatee, bytes32 delegationControlId) internal { bytes32[] memory _keyTuple = new bytes32[](2); @@ -146,6 +170,15 @@ library Delegations { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* 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))); + _keyTuple[1] = bytes32(uint256(uint160(delegatee))); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* 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); diff --git a/packages/world/src/tables/InstalledModules.sol b/packages/world/src/tables/InstalledModules.sol index b89b19bb88..530489f7a8 100644 --- a/packages/world/src/tables/InstalledModules.sol +++ b/packages/world/src/tables/InstalledModules.sol @@ -66,6 +66,11 @@ library InstalledModules { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -81,6 +86,16 @@ library InstalledModules { return (address(bytes20(_blob))); } + /** Get moduleAddress */ + function _get(bytes16 moduleName, bytes32 argumentsHash) internal view returns (address moduleAddress) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = bytes32(moduleName); + _keyTuple[1] = argumentsHash; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (address(bytes20(_blob))); + } + /** Get moduleAddress (using the specified store) */ function get(IStore _store, bytes16 moduleName, bytes32 argumentsHash) internal view returns (address moduleAddress) { bytes32[] memory _keyTuple = new bytes32[](2); @@ -100,6 +115,15 @@ library InstalledModules { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((moduleAddress)), _fieldLayout); } + /** Set moduleAddress */ + function _set(bytes16 moduleName, bytes32 argumentsHash, address moduleAddress) internal { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = bytes32(moduleName); + _keyTuple[1] = argumentsHash; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((moduleAddress)), _fieldLayout); + } + /** Set moduleAddress (using the specified store) */ function set(IStore _store, bytes16 moduleName, bytes32 argumentsHash, address moduleAddress) internal { bytes32[] memory _keyTuple = new bytes32[](2); @@ -142,6 +166,15 @@ library InstalledModules { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes16 moduleName, bytes32 argumentsHash) internal { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = bytes32(moduleName); + _keyTuple[1] = argumentsHash; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* 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); diff --git a/packages/world/src/tables/NamespaceOwner.sol b/packages/world/src/tables/NamespaceOwner.sol index 10f34300f2..5b7946f7a9 100644 --- a/packages/world/src/tables/NamespaceOwner.sol +++ b/packages/world/src/tables/NamespaceOwner.sol @@ -64,6 +64,11 @@ library NamespaceOwner { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -78,6 +83,15 @@ library NamespaceOwner { return (address(bytes20(_blob))); } + /** Get owner */ + function _get(bytes16 namespace) internal view returns (address owner) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(namespace); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (address(bytes20(_blob))); + } + /** Get owner (using the specified store) */ function get(IStore _store, bytes16 namespace) internal view returns (address owner) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -95,6 +109,14 @@ library NamespaceOwner { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); } + /** Set owner */ + function _set(bytes16 namespace, address owner) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(namespace); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((owner)), _fieldLayout); + } + /** Set owner (using the specified store) */ function set(IStore _store, bytes16 namespace, address owner) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -134,6 +156,14 @@ library NamespaceOwner { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes16 namespace) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(namespace); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes16 namespace) internal { bytes32[] memory _keyTuple = new bytes32[](1); diff --git a/packages/world/src/tables/ResourceAccess.sol b/packages/world/src/tables/ResourceAccess.sol index 56ce7e7616..9d591d49ef 100644 --- a/packages/world/src/tables/ResourceAccess.sol +++ b/packages/world/src/tables/ResourceAccess.sol @@ -66,6 +66,11 @@ library ResourceAccess { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -81,6 +86,16 @@ library ResourceAccess { return (_toBool(uint8(bytes1(_blob)))); } + /** Get access */ + function _get(bytes32 resourceSelector, address caller) internal view returns (bool access) { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = resourceSelector; + _keyTuple[1] = bytes32(uint256(uint160(caller))); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + /** Get access (using the specified store) */ function get(IStore _store, bytes32 resourceSelector, address caller) internal view returns (bool access) { bytes32[] memory _keyTuple = new bytes32[](2); @@ -100,6 +115,15 @@ library ResourceAccess { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); } + /** Set access */ + function _set(bytes32 resourceSelector, address caller, bool access) internal { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = resourceSelector; + _keyTuple[1] = bytes32(uint256(uint160(caller))); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((access)), _fieldLayout); + } + /** Set access (using the specified store) */ function set(IStore _store, bytes32 resourceSelector, address caller, bool access) internal { bytes32[] memory _keyTuple = new bytes32[](2); @@ -142,6 +166,15 @@ library ResourceAccess { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes32 resourceSelector, address caller) internal { + bytes32[] memory _keyTuple = new bytes32[](2); + _keyTuple[0] = resourceSelector; + _keyTuple[1] = bytes32(uint256(uint160(caller))); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes32 resourceSelector, address caller) internal { bytes32[] memory _keyTuple = new bytes32[](2); diff --git a/packages/world/test/tables/AddressArray.sol b/packages/world/test/tables/AddressArray.sol index 32a0e2131e..e2b29648b8 100644 --- a/packages/world/test/tables/AddressArray.sol +++ b/packages/world/test/tables/AddressArray.sol @@ -61,6 +61,11 @@ library AddressArray { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register(bytes32 _tableId) internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store, bytes32 _tableId) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -75,6 +80,15 @@ library AddressArray { return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); } + /** Get value */ + function _get(bytes32 _tableId, bytes32 key) internal view returns (address[] memory value) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); + } + /** Get value (using the specified store) */ function get(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (address[] memory value) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -92,6 +106,14 @@ library AddressArray { StoreSwitch.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); } + /** Set value */ + function _set(bytes32 _tableId, bytes32 key, address[] memory value) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 0, EncodeArray.encode((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, bytes32 _tableId, bytes32 key, address[] memory value) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -111,6 +133,17 @@ library AddressArray { } } + /** Get the length of value */ + function _length(bytes32 _tableId, bytes32 key) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + uint256 _byteLength = StoreCore.getFieldLength(_tableId, _keyTuple, 0, _fieldLayout); + unchecked { + return _byteLength / 20; + } + } + /** Get the length of value (using the specified store) */ function length(IStore _store, bytes32 _tableId, bytes32 key) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -143,6 +176,27 @@ library AddressArray { } } + /** + * Get an item of value + * (unchecked, returns invalid data if index overflows) + */ + function _getItem(bytes32 _tableId, bytes32 key, uint256 _index) internal view returns (address) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + bytes memory _blob = StoreCore.getFieldSlice( + _tableId, + _keyTuple, + 0, + _fieldLayout, + _index * 20, + (_index + 1) * 20 + ); + return (address(bytes20(_blob))); + } + } + /** * Get an item of value (using the specified store) * (unchecked, returns invalid data if index overflows) @@ -165,6 +219,14 @@ library AddressArray { StoreSwitch.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); } + /** Push an element to value */ + function _push(bytes32 _tableId, bytes32 key, address _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.pushToField(_tableId, _keyTuple, 0, abi.encodePacked((_element)), _fieldLayout); + } + /** Push an element to value (using the specified store) */ function push(IStore _store, bytes32 _tableId, bytes32 key, address _element) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -181,6 +243,14 @@ library AddressArray { StoreSwitch.popFromField(_tableId, _keyTuple, 0, 20, _fieldLayout); } + /** Pop an element from value */ + function _pop(bytes32 _tableId, bytes32 key) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.popFromField(_tableId, _keyTuple, 0, 20, _fieldLayout); + } + /** Pop an element from value (using the specified store) */ function pop(IStore _store, bytes32 _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -202,6 +272,19 @@ library AddressArray { } } + /** + * Update an element of value at `_index` + * (checked only to prevent modifying other tables; can corrupt own data if index overflows) + */ + function _update(bytes32 _tableId, bytes32 key, uint256 _index, address _element) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + unchecked { + StoreCore.updateInField(_tableId, _keyTuple, 0, _index * 20, abi.encodePacked((_element)), _fieldLayout); + } + } + /** * Update an element of value (using the specified store) at `_index` * (checked only to prevent modifying other tables; can corrupt own data if index overflows) @@ -253,6 +336,14 @@ library AddressArray { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes32 _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, bytes32 _tableId, bytes32 key) internal { bytes32[] memory _keyTuple = new bytes32[](1); diff --git a/packages/world/test/tables/Bool.sol b/packages/world/test/tables/Bool.sol index 87b9f6e209..6605ccc924 100644 --- a/packages/world/test/tables/Bool.sol +++ b/packages/world/test/tables/Bool.sol @@ -59,6 +59,11 @@ library Bool { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register(bytes32 _tableId) internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store, bytes32 _tableId) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -72,6 +77,14 @@ library Bool { return (_toBool(uint8(bytes1(_blob)))); } + /** Get value */ + function _get(bytes32 _tableId) internal view returns (bool value) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + /** Get value (using the specified store) */ function get(IStore _store, bytes32 _tableId) internal view returns (bool value) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -87,6 +100,13 @@ library Bool { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Set value */ + function _set(bytes32 _tableId, bool value) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, bytes32 _tableId, bool value) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -123,6 +143,13 @@ library Bool { StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } + /* Delete all data for given keys */ + function _deleteRecord(bytes32 _tableId) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + /* Delete all data for given keys (using the specified store) */ function deleteRecord(IStore _store, bytes32 _tableId) internal { bytes32[] memory _keyTuple = new bytes32[](0); diff --git a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol index 77ca8cd102..24ba4c5d0f 100644 --- a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol @@ -62,6 +62,11 @@ library Counter { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -75,6 +80,14 @@ library Counter { return (uint32(bytes4(_blob))); } + /** Get value */ + function _get() internal view returns (uint32 value) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); + } + /** Get value (using the specified store) */ function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -90,6 +103,13 @@ library Counter { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Set value */ + function _set(uint32 value) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -126,6 +146,13 @@ library Counter { 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); diff --git a/templates/react/packages/contracts/src/codegen/tables/Counter.sol b/templates/react/packages/contracts/src/codegen/tables/Counter.sol index 77ca8cd102..24ba4c5d0f 100644 --- a/templates/react/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/react/packages/contracts/src/codegen/tables/Counter.sol @@ -62,6 +62,11 @@ library Counter { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -75,6 +80,14 @@ library Counter { return (uint32(bytes4(_blob))); } + /** Get value */ + function _get() internal view returns (uint32 value) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); + } + /** Get value (using the specified store) */ function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -90,6 +103,13 @@ library Counter { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Set value */ + function _set(uint32 value) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -126,6 +146,13 @@ library Counter { 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); diff --git a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol index f757dc4c9f..1ea72f6f0b 100644 --- a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol +++ b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol @@ -74,6 +74,11 @@ library Position { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -88,6 +93,15 @@ library Position { return (int32(uint32(bytes4(_blob)))); } + /** Get x */ + function _getX(bytes32 key) internal view returns (int32 x) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); + } + /** Get x (using the specified store) */ function getX(IStore _store, bytes32 key) internal view returns (int32 x) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -105,6 +119,14 @@ library Position { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } + /** Set x */ + function _setX(bytes32 key, int32 x) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); + } + /** Set x (using the specified store) */ function setX(IStore _store, bytes32 key, int32 x) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -122,6 +144,15 @@ library Position { return (int32(uint32(bytes4(_blob)))); } + /** Get y */ + function _getY(bytes32 key) internal view returns (int32 y) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); + } + /** Get y (using the specified store) */ function getY(IStore _store, bytes32 key) internal view returns (int32 y) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -139,6 +170,14 @@ library Position { StoreSwitch.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } + /** Set y */ + function _setY(bytes32 key, int32 y) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); + } + /** Set y (using the specified store) */ function setY(IStore _store, bytes32 key, int32 y) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -156,6 +195,15 @@ library Position { return (int32(uint32(bytes4(_blob)))); } + /** Get z */ + function _getZ(bytes32 key) internal view returns (int32 z) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); + return (int32(uint32(bytes4(_blob)))); + } + /** Get z (using the specified store) */ function getZ(IStore _store, bytes32 key) internal view returns (int32 z) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -173,6 +221,14 @@ library Position { StoreSwitch.setField(_tableId, _keyTuple, 2, abi.encodePacked((z)), _fieldLayout); } + /** Set z */ + function _setZ(bytes32 key, int32 z) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setField(_tableId, _keyTuple, 2, abi.encodePacked((z)), _fieldLayout); + } + /** Set z (using the specified store) */ function setZ(IStore _store, bytes32 key, int32 z) internal { bytes32[] memory _keyTuple = new bytes32[](1); @@ -190,6 +246,15 @@ library Position { return decode(_blob); } + /** Get the full data */ + function _get(bytes32 key) internal view returns (PositionData memory _table) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); + return decode(_blob); + } + /** Get the full data (using the specified store) */ function get(IStore _store, bytes32 key) internal view returns (PositionData memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); @@ -212,6 +277,19 @@ library Position { StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** Set the full data using individual values */ + function _set(bytes32 key, int32 x, int32 y, int32 z) internal { + bytes memory _staticData = encodeStatic(x, y, z); + + PackedCounter _encodedLengths; + bytes memory _dynamicData; + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = key; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + /** Set the full data using individual values (using the specified store) */ function set(IStore _store, bytes32 key, int32 x, int32 y, int32 z) internal { bytes memory _staticData = encodeStatic(x, y, z); @@ -230,6 +308,11 @@ library Position { set(key, _table.x, _table.y, _table.z); } + /** Set the full data using the data struct */ + function _set(bytes32 key, PositionData memory _table) internal { + set(key, _table.x, _table.y, _table.z); + } + /** Set the full data using the data struct (using the specified store) */ function set(IStore _store, bytes32 key, PositionData memory _table) internal { set(_store, key, _table.x, _table.y, _table.z); @@ -275,6 +358,14 @@ library Position { 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); diff --git a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol index 77ca8cd102..24ba4c5d0f 100644 --- a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol @@ -62,6 +62,11 @@ library Counter { StoreSwitch.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); } + /** Register the table with its config */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); + } + /** Register the table with its config (using the specified store) */ function register(IStore _store) internal { _store.registerTable(_tableId, _fieldLayout, getKeySchema(), getValueSchema(), getKeyNames(), getFieldNames()); @@ -75,6 +80,14 @@ library Counter { return (uint32(bytes4(_blob))); } + /** Get value */ + function _get() internal view returns (uint32 value) { + bytes32[] memory _keyTuple = new bytes32[](0); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint32(bytes4(_blob))); + } + /** Get value (using the specified store) */ function get(IStore _store) internal view returns (uint32 value) { bytes32[] memory _keyTuple = new bytes32[](0); @@ -90,6 +103,13 @@ library Counter { StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); } + /** Set value */ + function _set(uint32 value) internal { + bytes32[] memory _keyTuple = new bytes32[](0); + + StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((value)), _fieldLayout); + } + /** Set value (using the specified store) */ function set(IStore _store, uint32 value) internal { bytes32[] memory _keyTuple = new bytes32[](0); @@ -126,6 +146,13 @@ library Counter { 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); From 99ab9cd6fff1a732b47d63ead894292661682380 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Sat, 16 Sep 2023 23:19:18 +0100 Subject: [PATCH 08/17] feat(store): indexed `tableId` in store events (#1520) --- .changeset/stale-worms-hunt.md | 5 + .changeset/thin-terms-lay.md | 2 - .gitattributes | 1 + .../src/postgres/postgresStorage.test.ts | 8 +- .../src/sqlite/sqliteStorage.test.ts | 8 +- packages/store/gas-report.json | 90 +-- packages/store/src/IStore.sol | 17 +- packages/store/src/StoreCore.sol | 16 +- packages/store/ts/storeEvents.ts | 10 +- packages/store/ts/storeEventsAbi.test.ts | 17 +- packages/world/gas-report.json | 82 +-- test-data/world-logs.json | 660 ++++++++++-------- 12 files changed, 496 insertions(+), 420 deletions(-) create mode 100644 .changeset/stale-worms-hunt.md diff --git a/.changeset/stale-worms-hunt.md b/.changeset/stale-worms-hunt.md new file mode 100644 index 0000000000..07e7c2fb16 --- /dev/null +++ b/.changeset/stale-worms-hunt.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store": major +--- + +Store events now use an `indexed` `tableId`. This adds ~100 gas per write, but means we our sync stack can filter events by table. diff --git a/.changeset/thin-terms-lay.md b/.changeset/thin-terms-lay.md index 31999bcaa5..5f71ab8524 100644 --- a/.changeset/thin-terms-lay.md +++ b/.changeset/thin-terms-lay.md @@ -11,7 +11,6 @@ This saves gas for use cases where the functionality to dynamically determine wh We decided to continue to always generate a set of functions that dynamically decide which `Store` to use, so that the generated table libraries can still be imported by non-root systems. ```solidity - library Counter { // Dynamically determine which store to write to based on the context function set(uint32 value) internal; @@ -21,5 +20,4 @@ library Counter { // ... equivalent functions for all other Store methods } - ``` diff --git a/.gitattributes b/.gitattributes index a21dceecec..ee7e869fad 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ # suppress diffs for codegen in PRs **/codegen/**/*.sol linguist-generated=true +**/test-data/**/*.json linguist-generated=true diff --git a/packages/store-sync/src/postgres/postgresStorage.test.ts b/packages/store-sync/src/postgres/postgresStorage.test.ts index 341546978a..8aa0548082 100644 --- a/packages/store-sync/src/postgres/postgresStorage.test.ts +++ b/packages/store-sync/src/postgres/postgresStorage.test.ts @@ -56,7 +56,7 @@ describe("postgresStorage", async () => { { "chainId": 31337, "lastError": null, - "lastUpdatedBlockNumber": 6n, + "lastUpdatedBlockNumber": 5n, "schemaVersion": 1, }, ] @@ -74,7 +74,7 @@ describe("postgresStorage", async () => { "key": "0x5FbDB2315678afecb367f032d93F642f64180aa3::NumberList", "keySchema": {}, "lastError": null, - "lastUpdatedBlockNumber": 6n, + "lastUpdatedBlockNumber": 5n, "name": "NumberList", "namespace": "", "schemaVersion": 1, @@ -92,7 +92,7 @@ describe("postgresStorage", async () => { { "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", "keySchema": {}, - "lastUpdatedBlockNumber": 6n, + "lastUpdatedBlockNumber": 5n, "name": "NumberList", "namespace": "", "tableId": "0x000000000000000000000000000000004e756d6265724c697374000000000000", @@ -111,7 +111,7 @@ describe("postgresStorage", async () => { "__encodedLengths": "0x0000000000000000000000000000000000000000000000000800000000000008", "__isDeleted": false, "__key": "0x", - "__lastUpdatedBlockNumber": 6n, + "__lastUpdatedBlockNumber": 5n, "__staticData": null, "value": [ 420, diff --git a/packages/store-sync/src/sqlite/sqliteStorage.test.ts b/packages/store-sync/src/sqlite/sqliteStorage.test.ts index 2834fa73eb..1c8845f37c 100644 --- a/packages/store-sync/src/sqlite/sqliteStorage.test.ts +++ b/packages/store-sync/src/sqlite/sqliteStorage.test.ts @@ -64,7 +64,7 @@ describe("sqliteStorage", async () => { { "chainId": 31337, "lastError": null, - "lastUpdatedBlockNumber": 6n, + "lastUpdatedBlockNumber": 5n, "schemaVersion": 1, }, ] @@ -77,7 +77,7 @@ describe("sqliteStorage", async () => { "id": "0x5FbDB2315678afecb367f032d93F642f64180aa3____NumberList", "keySchema": {}, "lastError": null, - "lastUpdatedBlockNumber": 6n, + "lastUpdatedBlockNumber": 5n, "name": "NumberList", "namespace": "", "schemaVersion": 1, @@ -96,7 +96,7 @@ describe("sqliteStorage", async () => { "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", "id": "0x5FbDB2315678afecb367f032d93F642f64180aa3____NumberList", "keySchema": {}, - "lastUpdatedBlockNumber": 6n, + "lastUpdatedBlockNumber": 5n, "name": "NumberList", "namespace": "", "tableId": "0x000000000000000000000000000000004e756d6265724c697374000000000000", @@ -115,7 +115,7 @@ describe("sqliteStorage", async () => { "__encodedLengths": "0x0000000000000000000000000000000000000000000000000800000000000008", "__isDeleted": false, "__key": "0x", - "__lastUpdatedBlockNumber": 6n, + "__lastUpdatedBlockNumber": 5n, "__staticData": null, "value": [ 420, diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 9f301b4105..2aa0f2ab67 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": 687695 + "gasUsed": 687791 }, { "file": "test/Mixed.t.sol", @@ -363,13 +363,13 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Mixed table", - "gasUsed": 549513 + "gasUsed": 549609 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 103812 + "gasUsed": 103911 }, { "file": "test/Mixed.t.sol", @@ -609,25 +609,25 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 20143 + "gasUsed": 20239 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 14155 + "gasUsed": 14250 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 22339 + "gasUsed": 22434 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 14351 + "gasUsed": 14446 }, { "file": "test/StoreCoreGas.t.sol", @@ -663,7 +663,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 6592 + "gasUsed": 6691 }, { "file": "test/StoreCoreGas.t.sol", @@ -681,67 +681,67 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 60314 + "gasUsed": 60413 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 70846 + "gasUsed": 71044 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 20625 + "gasUsed": 20820 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 16217 + "gasUsed": 16415 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 60314 + "gasUsed": 60413 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 163968 + "gasUsed": 164166 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 23825 + "gasUsed": 24020 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 17202 + "gasUsed": 17400 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 11899 + "gasUsed": 11994 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 34653 + "gasUsed": 34748 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 609664 + "gasUsed": 609744 }, { "file": "test/StoreCoreGas.t.sol", @@ -765,7 +765,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 101732 + "gasUsed": 101831 }, { "file": "test/StoreCoreGas.t.sol", @@ -807,7 +807,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 31454 + "gasUsed": 31550 }, { "file": "test/StoreCoreGas.t.sol", @@ -819,7 +819,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 30094 + "gasUsed": 30190 }, { "file": "test/StoreCoreGas.t.sol", @@ -831,7 +831,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 52979 + "gasUsed": 53074 }, { "file": "test/StoreCoreGas.t.sol", @@ -843,7 +843,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 31206 + "gasUsed": 31300 }, { "file": "test/StoreCoreGas.t.sol", @@ -855,7 +855,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 32038 + "gasUsed": 32137 }, { "file": "test/StoreCoreGas.t.sol", @@ -867,7 +867,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 54542 + "gasUsed": 54641 }, { "file": "test/StoreCoreGas.t.sol", @@ -879,13 +879,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 12937 + "gasUsed": 13032 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 13739 + "gasUsed": 13834 }, { "file": "test/StoreHook.t.sol", @@ -933,7 +933,7 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 56047 + "gasUsed": 56142 }, { "file": "test/tables/Callbacks.t.sol", @@ -945,19 +945,19 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 34957 + "gasUsed": 35052 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 58052 + "gasUsed": 58148 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 58052 + "gasUsed": 58147 }, { "file": "test/tables/StoreHooks.t.sol", @@ -969,55 +969,55 @@ "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 15051 + "gasUsed": 15147 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 11606 + "gasUsed": 11702 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 13077 + "gasUsed": 13172 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 34175 + "gasUsed": 34269 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 7003 + "gasUsed": 7102 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 30214 + "gasUsed": 30308 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 80743 + "gasUsed": 80838 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 80654 + "gasUsed": 80750 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 15868 + "gasUsed": 15967 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", @@ -1041,13 +1041,13 @@ "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 22092 + "gasUsed": 22188 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 24228 + "gasUsed": 24324 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -1101,13 +1101,13 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 410936 + "gasUsed": 411032 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 32941 + "gasUsed": 33040 }, { "file": "test/Vector2.t.sol", diff --git a/packages/store/src/IStore.sol b/packages/store/src/IStore.sol index 052195b0bc..b13097f3a4 100644 --- a/packages/store/src/IStore.sol +++ b/packages/store/src/IStore.sol @@ -81,23 +81,28 @@ interface IStoreRead { interface IStoreWrite { event StoreSetRecord( - bytes32 tableId, + bytes32 indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData ); - - event StoreSpliceStaticData(bytes32 tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data); + event StoreSpliceStaticData( + bytes32 indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data + ); event StoreSpliceDynamicData( - bytes32 tableId, + bytes32 indexed tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data, bytes32 encodedLengths ); - event StoreDeleteRecord(bytes32 tableId, bytes32[] keyTuple); + event StoreDeleteRecord(bytes32 indexed tableId, bytes32[] keyTuple); // Set full record (including full dynamic data) function setRecord( @@ -152,7 +157,7 @@ interface IStoreWrite { interface IStoreEphemeral { event StoreEphemeralRecord( - bytes32 tableId, + bytes32 indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 004c4a5170..8b95cebd92 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -18,24 +18,30 @@ import { StoreHookLib, StoreHookType } from "./StoreHook.sol"; library StoreCore { // note: the preimage of the tuple of keys used to index is part of the event, so it can be used by indexers event StoreSetRecord( - bytes32 tableId, + bytes32 indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData ); - event StoreSpliceStaticData(bytes32 tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data); + event StoreSpliceStaticData( + bytes32 indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data + ); event StoreSpliceDynamicData( - bytes32 tableId, + bytes32 indexed tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data, bytes32 encodedLengths ); - event StoreDeleteRecord(bytes32 tableId, bytes32[] keyTuple); + event StoreDeleteRecord(bytes32 indexed tableId, bytes32[] keyTuple); event StoreEphemeralRecord( - bytes32 tableId, + bytes32 indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, diff --git a/packages/store/ts/storeEvents.ts b/packages/store/ts/storeEvents.ts index 4148e5cd68..5f1d1a23a9 100644 --- a/packages/store/ts/storeEvents.ts +++ b/packages/store/ts/storeEvents.ts @@ -1,7 +1,7 @@ export const storeEvents = [ - "event StoreSetRecord(bytes32 tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData)", - "event StoreSpliceStaticData(bytes32 tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data)", - "event StoreSpliceDynamicData(bytes32 tableId, bytes32[] keyTuple, uint48 start, uint40 deleteCount, bytes data, bytes32 encodedLengths)", - "event StoreEphemeralRecord(bytes32 tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData)", - "event StoreDeleteRecord(bytes32 tableId, bytes32[] keyTuple)", + "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/store/ts/storeEventsAbi.test.ts b/packages/store/ts/storeEventsAbi.test.ts index 37242457f6..be25f2cd8a 100644 --- a/packages/store/ts/storeEventsAbi.test.ts +++ b/packages/store/ts/storeEventsAbi.test.ts @@ -1,22 +1,23 @@ import { describe, expect, it } from "vitest"; import { storeEventsAbi } from "./storeEventsAbi"; import IStoreAbi from "../out/IStore.sol/IStore.abi.json"; +import { AbiEvent } from "abitype"; // Make sure `storeEvents` stays in sync with Solidity definition/events describe("storeEventsAbi", () => { it("should match the store ABI", () => { - const expectedAbi = IStoreAbi.filter((item) => item.type === "event") + const expectedEvents = IStoreAbi.filter((item) => item.type === "event") as readonly AbiEvent[]; + const expectedAbi = expectedEvents .map((item) => ({ - // just return data that abitype cares about + // return data in a shape that matches abitype's parseAbi type: item.type, name: item.name, - inputs: [ - ...item.inputs.map((input) => ({ - name: input.name, - type: input.type, - })), - ], + inputs: item.inputs.map((input) => ({ + name: input.name, + type: input.type, + ...(input.indexed ? { indexed: true } : null), + })), })) .sort((a, b) => a.name.localeCompare(b.name)); diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index c28d505e3f..35515f840a 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": 1414535 + "gasUsed": 1415306 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1414535 + "gasUsed": 1415306 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 158665 + "gasUsed": 158959 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1414535 + "gasUsed": 1415306 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1414535 + "gasUsed": 1415306 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 21917 + "gasUsed": 22016 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 170653 + "gasUsed": 171520 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1414535 + "gasUsed": 1415306 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 20639 + "gasUsed": 20738 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 87686 + "gasUsed": 88171 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 653818 + "gasUsed": 654597 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,49 +117,49 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 653818 + "gasUsed": 654597 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 134201 + "gasUsed": 134495 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 653818 + "gasUsed": 654597 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 103779 + "gasUsed": 104070 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 32729 + "gasUsed": 32927 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 653818 + "gasUsed": 654597 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 138815 + "gasUsed": 139109 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 103574 + "gasUsed": 103868 }, { "file": "test/query.t.sol", @@ -231,19 +231,19 @@ "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 113879 + "gasUsed": 114074 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 33481 + "gasUsed": 33580 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 108316 + "gasUsed": 108511 }, { "file": "test/StandardDelegationsModule.t.sol", @@ -255,25 +255,25 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 677906 + "gasUsed": 678986 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 51083 + "gasUsed": 51179 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 667966 + "gasUsed": 669045 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 51083 + "gasUsed": 51179 }, { "file": "test/World.t.sol", @@ -285,7 +285,7 @@ "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 50163 + "gasUsed": 50259 }, { "file": "test/World.t.sol", @@ -297,84 +297,84 @@ "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 8747 + "gasUsed": 8846 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 88129 + "gasUsed": 88225 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 58788 + "gasUsed": 58887 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 52106 + "gasUsed": 52205 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 79382 + "gasUsed": 79481 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 122458 + "gasUsed": 122752 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 74024 + "gasUsed": 74123 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 641185 + "gasUsed": 641673 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 37035 + "gasUsed": 37131 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 35029 + "gasUsed": 35125 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 25333 + "gasUsed": 25429 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 14446 + "gasUsed": 14541 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 28688 + "gasUsed": 28784 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 17893 + "gasUsed": 17989 } ] diff --git a/test-data/world-logs.json b/test-data/world-logs.json index 15e99ba751..01c17d0650 100644 --- a/test-data/world-logs.json +++ b/test-data/world-logs.json @@ -2,12 +2,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000022000000000a0000000000002c0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000016d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000600060030220202000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000006003025f5f5fc4c4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000077461626c654964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000b6669656c644c61796f757400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096b6579536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76616c7565536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012616269456e636f6465644b65794e616d657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014616269456e636f6465644669656c644e616d6573000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000022000000000a0000000000002c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000016d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000600060030220202000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000006003025f5f5fc4c4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000077461626c654964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000b6669656c644c61796f757400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096b6579536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76616c7565536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012616269456e636f6465644b65794e616d657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014616269456e636f6465644669656c644e616d6573000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x0", "transactionLogIndex": "0x0", @@ -16,12 +17,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000016d756473746f7265000000000000000053746f7265486f6f6b7300000000000000000000000000000000000000000000000000000000000000000000000000600000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000016d756473746f7265000000000000000053746f7265486f6f6b7300000000000000000000000000000000000000000000000000000000000000000000000000600000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x1", "transactionLogIndex": "0x1", @@ -30,12 +32,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e616d6573706163654f776e6572000000000000000000000000000000000000000000000000000000000000000000600014010014000000000000000000000000000000000000000000000000000000001001004f0000000000000000000000000000000000000000000000000000000014010061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e616d657370616365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000056f776e6572000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e616d6573706163654f776e6572000000000000000000000000000000000000000000000000000000000000000000600014010014000000000000000000000000000000000000000000000000000000001001004f0000000000000000000000000000000000000000000000000000000014010061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e616d657370616365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000056f776e6572000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x2", "transactionLogIndex": "0x2", @@ -44,12 +47,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000042616c616e636573000000000000000000000000000000000000000000000000000000000000000000000000000000600020010020000000000000000000000000000000000000000000000000000000001001004f000000000000000000000000000000000000000000000000000000002001001f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e616d6573706163650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000762616c616e636500000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000042616c616e636573000000000000000000000000000000000000000000000000000000000000000000000000000000600020010020000000000000000000000000000000000000000000000000000000001001004f000000000000000000000000000000000000000000000000000000002001001f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e616d6573706163650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000762616c616e636500000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x3", "transactionLogIndex": "0x3", @@ -58,12 +62,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a00000000100000000000001a00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e7374616c6c65644d6f64756c657300000000000000000000000000000000000000000000000000000000000000600014010014000000000000000000000000000000000000000000000000000000003002004f5f0000000000000000000000000000000000000000000000000000001401006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000a6d6f64756c654e616d6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d617267756d656e74734861736800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d6d6f64756c654164647265737300000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000100000000000001a00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e7374616c6c65644d6f64756c657300000000000000000000000000000000000000000000000000000000000000600014010014000000000000000000000000000000000000000000000000000000003002004f5f0000000000000000000000000000000000000000000000000000001401006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000a6d6f64756c654e616d6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d617267756d656e74734861736800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d6d6f64756c654164647265737300000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x4", "transactionLogIndex": "0x4", @@ -72,12 +77,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a00000000100000000000001a0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000044656c65676174696f6e730000000000000000000000000000000000000000000000000000000000000000000000006000200100200000000000000000000000000000000000000000000000000000000028020061610000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000964656c656761746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964656c6567617465650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001364656c65676174696f6e436f6e74726f6c496400000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000100000000000001a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000044656c65676174696f6e730000000000000000000000000000000000000000000000000000000000000000000000006000200100200000000000000000000000000000000000000000000000000000000028020061610000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000964656c656761746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964656c6567617465650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001364656c65676174696f6e436f6e74726f6c496400000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x5", "transactionLogIndex": "0x5", @@ -86,12 +92,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a00000000100000000000001a000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000600001010001000000000000000000000000000000000000000000000000000000003402005f610000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000663616c6c6572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000066163636573730000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000100000000000001a000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000600001010001000000000000000000000000000000000000000000000000000000003402005f610000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000663616c6c6572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000066163636573730000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x6", "transactionLogIndex": "0x6", @@ -100,12 +107,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000600015020014010000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000001502006160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f72000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000673797374656d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7075626c69634163636573730000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000600015020014010000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000001502006160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f72000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000673797374656d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7075626c69634163636573730000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x7", "transactionLogIndex": "0x7", @@ -114,12 +122,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000240200200400000000000000000000000000000000000000000000000000000004010043000000000000000000000000000000000000000000000000000000002402005f43000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001066756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001673797374656d46756e6374696f6e53656c6563746f7200000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000000a0000000000001a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000046756e6374696f6e53656c6563746f72000000000000000000000000000000000000000000000000000000000000006000240200200400000000000000000000000000000000000000000000000000000004010043000000000000000000000000000000000000000000000000000000002402005f43000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001066756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001673797374656d46756e6374696f6e53656c6563746f7200000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x8", "transactionLogIndex": "0x8", @@ -128,12 +137,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d486f6f6b73000000000000000000000000000000000000000000000000000000000000000000000000600000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d486f6f6b73000000000000000000000000000000000000000000000000000000000000000000000000600000000100000000000000000000000000000000000000000000000000000000002001005f00000000000000000000000000000000000000000000000000000000000001b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x9", "transactionLogIndex": "0x9", @@ -142,12 +152,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d52656769737472790000000000000000000000000000000000000000000000000000000000000000006000200100200000000000000000000000000000000000000000000000000000000014010061000000000000000000000000000000000000000000000000000000002001005f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000673797374656d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000053797374656d52656769737472790000000000000000000000000000000000000000000000000000000000000000006000200100200000000000000000000000000000000000000000000000000000000014010061000000000000000000000000000000000000000000000000000000002001005f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000673797374656d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0xa", "transactionLogIndex": "0xa", @@ -156,12 +167,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000600001010001000000000000000000000000000000000000000000000000000000002001005f0000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c7265736f75726365547970650000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000600001010001000000000000000000000000000000000000000000000000000000002001005f0000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000107265736f7572636553656c6563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c7265736f75726365547970650000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0xb", "transactionLogIndex": "0xb", @@ -170,12 +182,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000004e616d6573706163654f776e65720000" ], - "data": "0x000000000000000000000000000000004e616d6573706163654f776e6572000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0xc", "transactionLogIndex": "0xc", @@ -184,12 +197,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263654163636573730000" ], - "data": "0x000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0xd", "transactionLogIndex": "0xd", @@ -198,12 +212,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263655479706500000000" ], - "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0xe", "transactionLogIndex": "0xe", @@ -212,12 +227,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263655479706500000000" ], - "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000636f72652e730000000000000000000000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000636f72652e730000000000000000000000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0xf", "transactionLogIndex": "0xf", @@ -226,12 +242,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000053797374656d73000000000000000000" ], - "data": "0x0000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000636f72652e73000000000000000000000000000000000000000000000000000000000000000000000000000000000015cafac3dd18ac6c6e92c921884f9e4176737c052c0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000636f72652e73000000000000000000000000000000000000000000000000000000000000000000000000000000000015cafac3dd18ac6c6e92c921884f9e4176737c052c0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x10", "transactionLogIndex": "0x10", @@ -240,12 +257,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x0000000000000000000000000000000053797374656d52656769737472790000" ], - "data": "0x0000000000000000000000000000000053797374656d5265676973747279000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000636f72652e7300000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000636f72652e7300000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x11", "transactionLogIndex": "0x11", @@ -254,12 +272,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263654163636573730000" ], - "data": "0x000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cafac3dd18ac6c6e92c921884f9e4176737c052c00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x12", "transactionLogIndex": "0x12", @@ -268,12 +287,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000140554c3a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000040554c3a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000140554c3a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000040554c3a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x13", "transactionLogIndex": "0x13", @@ -282,12 +302,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000018d53b20800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008d53b208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000018d53b20800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008d53b208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x14", "transactionLogIndex": "0x14", @@ -296,12 +317,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000125f6221000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000025f62210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000125f6221000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000025f62210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x15", "transactionLogIndex": "0x15", @@ -310,12 +332,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000012bfaa27400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000002bfaa274000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000012bfaa27400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000002bfaa274000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x16", "transactionLogIndex": "0x16", @@ -324,12 +347,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000121293ca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000021293ca0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000121293ca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000021293ca0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x17", "transactionLogIndex": "0x17", @@ -338,12 +362,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000013ea8492200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003ea84922000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000013ea8492200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003ea84922000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x18", "transactionLogIndex": "0x18", @@ -352,12 +377,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000018da798da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008da798da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000018da798da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000008da798da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x19", "transactionLogIndex": "0x19", @@ -366,12 +392,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010ba51f4900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000000ba51f49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010ba51f4900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000000ba51f49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x1a", "transactionLogIndex": "0x1a", @@ -380,12 +407,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001530f4b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000530f4b60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001530f4b6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000530f4b60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x1b", "transactionLogIndex": "0x1b", @@ -394,12 +422,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010560912900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000005609129000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010560912900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e730000000000000000000005609129000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x1c", "transactionLogIndex": "0x1c", @@ -408,12 +437,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001a886545e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000a886545e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001a886545e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000a886545e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x1d", "transactionLogIndex": "0x1d", @@ -422,12 +452,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001d5f8337f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000d5f8337f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001d5f8337f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000d5f8337f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x1e", "transactionLogIndex": "0x1e", @@ -436,12 +467,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001a92813ad00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000a92813ad000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001a92813ad00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000a92813ad000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x1f", "transactionLogIndex": "0x1f", @@ -450,12 +482,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000013350b6a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003350b6a9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000013350b6a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003350b6a9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x20", "transactionLogIndex": "0x20", @@ -464,12 +497,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000013c03a51c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003c03a51c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000013c03a51c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000003c03a51c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x21", "transactionLogIndex": "0x21", @@ -478,12 +512,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001b7a3c75600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000b7a3c756000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001b7a3c75600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e7300000000000000000000b7a3c756000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x22", "transactionLogIndex": "0x22", @@ -492,12 +527,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000011d2257ba00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000001d2257ba000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000011d2257ba00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000636f72652e73000000000000000000001d2257ba000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x23", "transactionLogIndex": "0x23", @@ -506,12 +542,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x00000000000000000000000000000000496e7374616c6c65644d6f64756c6573" ], - "data": "0x00000000000000000000000000000000496e7374616c6c65644d6f64756c657300000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000002636f72652e6d0000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000014e7f1725e7734ce288f8367e1bb143e90bb3f0512000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x73080a3dddb1f96bc5a4d0b9b7a7f00555b7c11e68683d796252c9a71de6fdfc", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000002636f72652e6d0000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000014e7f1725e7734ce288f8367e1bb143e90bb3f0512000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa4f8502ae902c2b982a75bee37ad2c52b7456d38cb4fdd2288dbda0d53b5db23", "transactionIndex": "0x0", "logIndex": "0x24", "transactionLogIndex": "0x24", @@ -520,12 +557,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263655479706500000000" ], - "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265720000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x607b94e53ff6d14c8af149f742239040a26773006b3916fca7403ab56bc1addf", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265720000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x63c9c3f365b40de92c07c06e86f096433bfb2e968c3caec07df00fa2cd1a46d1", "transactionIndex": "0x1", "logIndex": "0x25", "transactionLogIndex": "0x0", @@ -534,12 +572,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d626572000000000000000000000000000000000000000000000000000000000000000000000000000000000060000401000400000000000000000000000000000000000000000000000000000000040100030000000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x607b94e53ff6d14c8af149f742239040a26773006b3916fca7403ab56bc1addf", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a000000000a00000000000014000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d626572000000000000000000000000000000000000000000000000000000000000000000000000000000000060000401000400000000000000000000000000000000000000000000000000000000040100030000000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b65790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x63c9c3f365b40de92c07c06e86f096433bfb2e968c3caec07df00fa2cd1a46d1", "transactionIndex": "0x1", "logIndex": "0x26", "transactionLogIndex": "0x1", @@ -548,12 +587,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263655479706500000000" ], - "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000566563746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x5a88a5686556db275ec64403ada8ee92a761403bfd712f21b6746aabb0029f12", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000566563746f720000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xe1f1a922f753965be316f50e3c51c91c436aff6091710ba37cd2c2b932625a6d", "transactionIndex": "0x2", "logIndex": "0x27", "transactionLogIndex": "0x0", @@ -562,12 +602,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000010000000000a0000000000001a00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000566563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000006000080200040400000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000802002323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b6579000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017900000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x5a88a5686556db275ec64403ada8ee92a761403bfd712f21b6746aabb0029f12", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000000a0000000000001a00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000566563746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000006000080200040400000000000000000000000000000000000000000000000000000004010003000000000000000000000000000000000000000000000000000000000802002323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000036b6579000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017900000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xe1f1a922f753965be316f50e3c51c91c436aff6091710ba37cd2c2b932625a6d", "transactionIndex": "0x2", "logIndex": "0x28", "transactionLogIndex": "0x1", @@ -576,12 +617,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263655479706500000000" ], - "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737400000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0xaed15d9b279865d827e86039036fcc9d86c5467e36441834ba1f78991785229d", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737400000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x2a33d478b71e83b3075ae06f08da8260132fc8c0f8bb4e316b7c8c36b37a1fb8", "transactionIndex": "0x3", "logIndex": "0x29", "transactionLogIndex": "0x0", @@ -590,12 +632,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000a00000000040000000000000e000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c697374000000000000000000000000000000000000000000000000000000000000000000000000006000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0xaed15d9b279865d827e86039036fcc9d86c5467e36441834ba1f78991785229d", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000a00000000040000000000000e000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c697374000000000000000000000000000000000000000000000000000000000000000000000000006000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x2a33d478b71e83b3075ae06f08da8260132fc8c0f8bb4e316b7c8c36b37a1fb8", "transactionIndex": "0x3", "logIndex": "0x2a", "transactionLogIndex": "0x1", @@ -604,12 +647,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263655479706500000000" ], - "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004d756c7469000000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x126a9b9fbea2e94295dfd3b380c2f43f4fc96fe1ee732e4d3df29b2433ac5dc1", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004d756c7469000000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x7f5154e28a5640217c214a2007641ccb776e5b9609101919e28aead1d8eb6352", "transactionIndex": "0x4", "logIndex": "0x2b", "transactionLogIndex": "0x0", @@ -618,12 +662,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x6d756473746f726500000000000000005461626c657300000000000000000000" ], - "data": "0x6d756473746f726500000000000000005461626c65730000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000010000000001c0000000000002c000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004d756c74690000000000000000000000000000000000000000000000000000000000000000000000000000000000006000210200200100000000000000000000000000000000000000000000000000000034040003601f2e000000000000000000000000000000000000000000000000002102003f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000036e756d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x126a9b9fbea2e94295dfd3b380c2f43f4fc96fe1ee732e4d3df29b2433ac5dc1", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000010000000001c0000000000002c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004d756c74690000000000000000000000000000000000000000000000000000000000000000000000000000000000006000210200200100000000000000000000000000000000000000000000000000000034040003601f2e000000000000000000000000000000000000000000000000002102003f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000036e756d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x7f5154e28a5640217c214a2007641ccb776e5b9609101919e28aead1d8eb6352", "transactionIndex": "0x4", "logIndex": "0x2c", "transactionLogIndex": "0x1", @@ -632,12 +677,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263655479706500000000" ], - "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0xfb5bf0734dca864b8b13107223cb02facd6803ef1a03f39b325cd96a5ab4fd02", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x9522e814b8b7aa55524257cfb693c2fdcb6fe1afd7aae7f0daf68c426afcbac9", "transactionIndex": "0x5", "logIndex": "0x2d", "transactionLogIndex": "0x0", @@ -646,12 +692,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000053797374656d73000000000000000000" ], - "data": "0x0000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000155fc8d32690cc91d4c39d9d3abcbd16989f8757070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0xfb5bf0734dca864b8b13107223cb02facd6803ef1a03f39b325cd96a5ab4fd02", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000437573746f6d4572726f72735379737400000000000000000000000000000000000000000000000000000000000000155fc8d32690cc91d4c39d9d3abcbd16989f8757070100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x9522e814b8b7aa55524257cfb693c2fdcb6fe1afd7aae7f0daf68c426afcbac9", "transactionIndex": "0x5", "logIndex": "0x2e", "transactionLogIndex": "0x1", @@ -660,12 +707,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x0000000000000000000000000000000053797374656d52656769737472790000" ], - "data": "0x0000000000000000000000000000000053797374656d5265676973747279000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f875707000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000437573746f6d4572726f727353797374", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0xfb5bf0734dca864b8b13107223cb02facd6803ef1a03f39b325cd96a5ab4fd02", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f875707000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000437573746f6d4572726f727353797374", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x9522e814b8b7aa55524257cfb693c2fdcb6fe1afd7aae7f0daf68c426afcbac9", "transactionIndex": "0x5", "logIndex": "0x2f", "transactionLogIndex": "0x2", @@ -674,12 +722,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263654163636573730000" ], - "data": "0x000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570700000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0xfb5bf0734dca864b8b13107223cb02facd6803ef1a03f39b325cd96a5ab4fd02", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570700000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x9522e814b8b7aa55524257cfb693c2fdcb6fe1afd7aae7f0daf68c426afcbac9", "transactionIndex": "0x5", "logIndex": "0x30", "transactionLogIndex": "0x3", @@ -688,12 +737,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263655479706500000000" ], - "data": "0x000000000000000000000000000000005265736f75726365547970650000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x3a45c7867bdaafbebbfe02dc2eb9c7dedd4b6fd27f2540febb2fb49c8caa6ea5", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x21d2bdc995fad3ad12bc649405f9c25522526bf04a2ba379fd5cb4056e9368f3", "transactionIndex": "0x6", "logIndex": "0x31", "transactionLogIndex": "0x0", @@ -702,12 +752,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000053797374656d73000000000000000000" ], - "data": "0x0000000000000000000000000000000053797374656d7300000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000150165878a594ca255338adfa4d48449f69242eb8f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x3a45c7867bdaafbebbfe02dc2eb9c7dedd4b6fd27f2540febb2fb49c8caa6ea5", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000004e756d6265724c69737453797374656d00000000000000000000000000000000000000000000000000000000000000150165878a594ca255338adfa4d48449f69242eb8f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x21d2bdc995fad3ad12bc649405f9c25522526bf04a2ba379fd5cb4056e9368f3", "transactionIndex": "0x6", "logIndex": "0x32", "transactionLogIndex": "0x1", @@ -716,12 +767,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x0000000000000000000000000000000053797374656d52656769737472790000" ], - "data": "0x0000000000000000000000000000000053797374656d5265676973747279000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000004e756d6265724c69737453797374656d", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x3a45c7867bdaafbebbfe02dc2eb9c7dedd4b6fd27f2540febb2fb49c8caa6ea5", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000004e756d6265724c69737453797374656d", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x21d2bdc995fad3ad12bc649405f9c25522526bf04a2ba379fd5cb4056e9368f3", "transactionIndex": "0x6", "logIndex": "0x33", "transactionLogIndex": "0x2", @@ -730,12 +782,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735" + "0xe7b614a59a30dff5ea0536e50c4019312e856b636126e1b2d19a7c2872798735", + "0x000000000000000000000000000000005265736f757263654163636573730000" ], - "data": "0x000000000000000000000000000000005265736f75726365416363657373000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x3a45c7867bdaafbebbfe02dc2eb9c7dedd4b6fd27f2540febb2fb49c8caa6ea5", + "data": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f00000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x21d2bdc995fad3ad12bc649405f9c25522526bf04a2ba379fd5cb4056e9368f3", "transactionIndex": "0x6", "logIndex": "0x34", "transactionLogIndex": "0x3", @@ -744,12 +797,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000015f644e3c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000437573746f6d4572726f7273537973745f644e3c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x99183c2ecbd4300f807d9903e3a0048eb27d80386fd655ff4b3bdf4aea5d5208", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000015f644e3c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000437573746f6d4572726f7273537973745f644e3c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xa7b13684919b9c2f639041255d439afd3468db01f44f2699e159704399a11d5c", "transactionIndex": "0x7", "logIndex": "0x35", "transactionLogIndex": "0x0", @@ -758,12 +812,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001a4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656da4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0xa96d498c47174e6315617f6ef8e0fd6e93974a63c77152d173803f070f8023a6", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001a4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656da4ece52c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xd06d889514df379529e4231e85b2d241559dc810b765152c17047ae767b51cf0", "transactionIndex": "0x8", "logIndex": "0x36", "transactionLogIndex": "0x0", @@ -772,12 +827,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001f7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656df7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x77b03de8eef7f084dea0958f5f69c881d3ff3ae5df88d32110e9095536640b66", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001f7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656df7f0e440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0x08304f1f19f128d652cf1f5b599e1c8b87e5b8164e3046e7041aabc886b7227f", "transactionIndex": "0x9", "logIndex": "0x37", "transactionLogIndex": "0x0", @@ -786,12 +842,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656d306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0x6be14198e38f5635f834446da7a3594826ce7a404ae5e238b24c5a9cac751a74", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656d306d61a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xab1ec3ac7ebed007e57666d5fbb7c5ba174c9695ea87d9cd5025f1323d5cd573", "transactionIndex": "0xa", "logIndex": "0x38", "transactionLogIndex": "0x0", @@ -800,12 +857,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f" + "0xc851f86da4b2f7d69c86fc8dc136b05aa9805e49c225918a8856af392597a34f", + "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72" ], - "data": "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f7200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001b8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656db8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc67f4cbf009a2ede672e0fff1e8bcc4b1e46db4145886d6942308d0d3b985941", - "blockNumber": "0x5", - "transactionHash": "0xbe213a215bd71f17f867b8129a24630241f970e1cf5231f8a3bb2ba412b68a70", + "data": "0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001b8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000004e756d6265724c69737453797374656db8a44c7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x26210b5307d8f2e8f7ce8c759d3563b48fad64b1021b2fb6100d83cd7f55a3cd", + "blockNumber": "0x4", + "transactionHash": "0xef2202fbaac567d90f4790707035892d554dc226c0d481ffe667f1818774ad7b", "transactionIndex": "0xb", "logIndex": "0x39", "transactionLogIndex": "0x0", @@ -814,12 +872,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x5599f2052ade9808af7738adc73853c23894a2f1e944c827f7f6b8e948c4e885" + "0x5599f2052ade9808af7738adc73853c23894a2f1e944c827f7f6b8e948c4e885", + "0x000000000000000000000000000000004e756d6265724c697374000000000000" ], - "data": "0x000000000000000000000000000000004e756d6265724c69737400000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000040000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000001a400000000000000000000000000000000000000000000000000000000", - "blockHash": "0xbca51e861d5bfa7243f5c4b4dd5bf4e38874df40b4489bd87e14e0dca7fb434d", - "blockNumber": "0x6", - "transactionHash": "0x913934c3603cedb30d6ec5131ca347ce5f3906f6146f7fdfe39ad6008e6e0a94", + "data": "0x00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000040000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000001a400000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf77983f832702b99ab5712e6c94615f2125f82e1b279f966c49fd8c8d8bd03f1", + "blockNumber": "0x5", + "transactionHash": "0xe373575d25699927fbfcd0fb9eb2b48ebaed83b87d3ca1e0a30478ac2ae2be4f", "transactionIndex": "0x0", "logIndex": "0x0", "transactionLogIndex": "0x0", @@ -828,12 +887,13 @@ { "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", "topics": [ - "0x5599f2052ade9808af7738adc73853c23894a2f1e944c827f7f6b8e948c4e885" + "0x5599f2052ade9808af7738adc73853c23894a2f1e944c827f7f6b8e948c4e885", + "0x000000000000000000000000000000004e756d6265724c697374000000000000" ], - "data": "0x000000000000000000000000000000004e756d6265724c69737400000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000800000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000004500000000000000000000000000000000000000000000000000000000", - "blockHash": "0xbca51e861d5bfa7243f5c4b4dd5bf4e38874df40b4489bd87e14e0dca7fb434d", - "blockNumber": "0x6", - "transactionHash": "0xa5e0a4df59ae785eb7f2abc61ab104cbd97db921a61ad3a5a34b7a959d543ca6", + "data": "0x00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000800000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000004500000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf77983f832702b99ab5712e6c94615f2125f82e1b279f966c49fd8c8d8bd03f1", + "blockNumber": "0x5", + "transactionHash": "0xfec9e0db2f68f31109c2f8fb678f398807407b88deb1b9644f1638e0012fac7c", "transactionIndex": "0x1", "logIndex": "0x1", "transactionLogIndex": "0x0", From 9940fdb3e036e03aa8ede1ca80cd44d86d3b85b7 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Sat, 16 Sep 2023 23:30:29 +0100 Subject: [PATCH 09/17] feat(faucet): add faucet service (#1517) --- .changeset/chilled-cougars-smash.md | 23 ++++++++ Dockerfile | 4 ++ .../packages/client-react/package.json | 1 + .../client-react/src/mud/setupNetwork.ts | 31 ++++------ examples/minimal/packages/contracts/.env | 2 + .../minimal/packages/contracts/package.json | 2 + examples/minimal/pnpm-lock.yaml | 6 ++ packages/faucet/.eslintrc | 6 ++ packages/faucet/.gitignore | 1 + packages/faucet/.npmignore | 6 ++ packages/faucet/bin/faucet-server.ts | 56 +++++++++++++++++++ packages/faucet/package.json | 50 +++++++++++++++++ packages/faucet/src/createAppRouter.ts | 42 ++++++++++++++ packages/faucet/src/createClient.ts | 21 +++++++ packages/faucet/src/debug.ts | 3 + packages/faucet/src/index.ts | 2 + packages/faucet/tsconfig.json | 14 +++++ packages/faucet/tsup.config.ts | 11 ++++ pnpm-lock.yaml | 40 +++++++++++++ 19 files changed, 302 insertions(+), 19 deletions(-) create mode 100644 .changeset/chilled-cougars-smash.md create mode 100644 packages/faucet/.eslintrc create mode 100644 packages/faucet/.gitignore create mode 100644 packages/faucet/.npmignore create mode 100644 packages/faucet/bin/faucet-server.ts create mode 100644 packages/faucet/package.json create mode 100644 packages/faucet/src/createAppRouter.ts create mode 100644 packages/faucet/src/createClient.ts create mode 100644 packages/faucet/src/debug.ts create mode 100644 packages/faucet/src/index.ts create mode 100644 packages/faucet/tsconfig.json create mode 100644 packages/faucet/tsup.config.ts diff --git a/.changeset/chilled-cougars-smash.md b/.changeset/chilled-cougars-smash.md new file mode 100644 index 0000000000..0356ce2c82 --- /dev/null +++ b/.changeset/chilled-cougars-smash.md @@ -0,0 +1,23 @@ +--- +"@latticexyz/faucet": minor +--- + +New package to run your own faucet service. We'll use this soon for our testnet in place of `@latticexyz/services`. + +To run the faucet server: + +- Add the package with `pnpm add @latticexyz/faucet` +- Add a `.env` file that has a `RPC_HTTP_URL` and `FAUCET_PRIVATE_KEY` (or pass the environment variables into the next command) +- Run `pnpm faucet-server` to start the server + +You can also adjust the server's `HOST` (defaults to `0.0.0.0`) and `PORT` (defaults to `3002`). The tRPC routes are accessible under `/trpc`. + +To connect a tRPC client, add the package with `pnpm add @latticexyz/faucet` and then use `createClient`: + +```ts +import { createClient } from "@latticexyz/faucet"; + +const faucet = createClient({ url: "http://localhost:3002/trpc" }); + +await faucet.mutate.drip({ address: burnerAccount.address }); +``` diff --git a/Dockerfile b/Dockerfile index 6b4a5ef2c8..31e8acc9eb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -50,3 +50,7 @@ RUN pnpm run -r build FROM mud AS store-indexer WORKDIR /app/packages/store-indexer EXPOSE 3001 + +FROM mud AS faucet +WORKDIR /app/packages/faucet +EXPOSE 3002 diff --git a/examples/minimal/packages/client-react/package.json b/examples/minimal/packages/client-react/package.json index cbbce8e319..0b69a60485 100644 --- a/examples/minimal/packages/client-react/package.json +++ b/examples/minimal/packages/client-react/package.json @@ -13,6 +13,7 @@ "@improbable-eng/grpc-web": "^0.15.0", "@latticexyz/common": "link:../../../../packages/common", "@latticexyz/dev-tools": "link:../../../../packages/dev-tools", + "@latticexyz/faucet": "link:../../../../packages/faucet", "@latticexyz/react": "link:../../../../packages/react", "@latticexyz/recs": "link:../../../../packages/recs", "@latticexyz/schema-type": "link:../../../../packages/schema-type", diff --git a/examples/minimal/packages/client-react/src/mud/setupNetwork.ts b/examples/minimal/packages/client-react/src/mud/setupNetwork.ts index d11cd48e24..895bf70553 100644 --- a/examples/minimal/packages/client-react/src/mud/setupNetwork.ts +++ b/examples/minimal/packages/client-react/src/mud/setupNetwork.ts @@ -7,6 +7,7 @@ import IWorldAbi from "contracts/out/IWorld.sol/IWorld.abi.json"; import { ContractWrite, createBurnerAccount, createContract, transportObserver } from "@latticexyz/common"; import { Subject, share } from "rxjs"; import mudConfig from "contracts/mud.config"; +import { createClient as createFaucetClient } from "@latticexyz/faucet"; export type SetupNetworkResult = Awaited>; @@ -44,28 +45,20 @@ export async function setupNetwork() { startBlock: BigInt(networkConfig.initialBlockNumber), }); - // Request drip from faucet - if (networkConfig.faucetServiceUrl) { - const address = burnerAccount.address; - console.info("[Dev Faucet]: Player address -> ", address); + try { + console.log("creating faucet client"); + const faucet = createFaucetClient({ url: "http://localhost:3002/trpc" }); - const faucet = createFaucetService(networkConfig.faucetServiceUrl); - - const requestDrip = async () => { - const balance = await publicClient.getBalance({ address }); - console.info(`[Dev Faucet]: Player balance -> ${balance}`); - const lowBalance = balance < parseEther("1"); - if (lowBalance) { - console.info("[Dev Faucet]: Balance is low, dripping funds to player"); - // Double drip - await faucet.dripDev({ address }); - await faucet.dripDev({ address }); - } + const drip = async () => { + console.log("dripping"); + const tx = await faucet.drip.mutate({ address: burnerAccount.address }); + console.log("got drip", tx); }; - requestDrip(); - // Request a drip every 20 seconds - setInterval(requestDrip, 20000); + drip(); + setInterval(drip, 20_000); + } catch (e) { + console.error(e); } return { diff --git a/examples/minimal/packages/contracts/.env b/examples/minimal/packages/contracts/.env index 0f8cc4a305..0c925aa484 100644 --- a/examples/minimal/packages/contracts/.env +++ b/examples/minimal/packages/contracts/.env @@ -6,3 +6,5 @@ # # Anvil default private key: PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +FAUCET_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +RPC_HTTP_URL=http://127.0.0.1:8545 diff --git a/examples/minimal/packages/contracts/package.json b/examples/minimal/packages/contracts/package.json index 642f4a17b9..5acf110bed 100644 --- a/examples/minimal/packages/contracts/package.json +++ b/examples/minimal/packages/contracts/package.json @@ -11,6 +11,7 @@ "deploy:local": "pnpm run build && mud deploy", "deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet", "dev": "pnpm mud dev-contracts", + "faucet": "DEBUG=mud:faucet pnpm faucet-server", "lint": "pnpm run prettier && pnpm run solhint", "prettier": "prettier --write 'src/**/*.sol'", "solhint": "solhint --config ./.solhint.json 'src/**/*.sol' --fix", @@ -19,6 +20,7 @@ "devDependencies": { "@latticexyz/cli": "link:../../../../packages/cli", "@latticexyz/config": "link:../../../../packages/config", + "@latticexyz/faucet": "link:../../../../packages/faucet", "@latticexyz/schema-type": "link:../../../../packages/schema-type", "@latticexyz/store": "link:../../../../packages/store", "@latticexyz/world": "link:../../../../packages/world", diff --git a/examples/minimal/pnpm-lock.yaml b/examples/minimal/pnpm-lock.yaml index b0e57b5a9d..7f09b57e02 100644 --- a/examples/minimal/pnpm-lock.yaml +++ b/examples/minimal/pnpm-lock.yaml @@ -147,6 +147,9 @@ importers: '@latticexyz/dev-tools': specifier: link:../../../../packages/dev-tools version: link:../../../../packages/dev-tools + '@latticexyz/faucet': + specifier: link:../../../../packages/faucet + version: link:../../../../packages/faucet '@latticexyz/react': specifier: link:../../../../packages/react version: link:../../../../packages/react @@ -305,6 +308,9 @@ importers: '@latticexyz/config': specifier: link:../../../../packages/config version: link:../../../../packages/config + '@latticexyz/faucet': + specifier: link:../../../../packages/faucet + version: link:../../../../packages/faucet '@latticexyz/schema-type': specifier: link:../../../../packages/schema-type version: link:../../../../packages/schema-type diff --git a/packages/faucet/.eslintrc b/packages/faucet/.eslintrc new file mode 100644 index 0000000000..6db0063ad7 --- /dev/null +++ b/packages/faucet/.eslintrc @@ -0,0 +1,6 @@ +{ + "extends": ["../../.eslintrc"], + "rules": { + "@typescript-eslint/explicit-function-return-type": "error" + } +} diff --git a/packages/faucet/.gitignore b/packages/faucet/.gitignore new file mode 100644 index 0000000000..1521c8b765 --- /dev/null +++ b/packages/faucet/.gitignore @@ -0,0 +1 @@ +dist diff --git a/packages/faucet/.npmignore b/packages/faucet/.npmignore new file mode 100644 index 0000000000..84815f1eba --- /dev/null +++ b/packages/faucet/.npmignore @@ -0,0 +1,6 @@ +* + +!dist/** +!src/** +!package.json +!README.md diff --git a/packages/faucet/bin/faucet-server.ts b/packages/faucet/bin/faucet-server.ts new file mode 100644 index 0000000000..f6a6327a3d --- /dev/null +++ b/packages/faucet/bin/faucet-server.ts @@ -0,0 +1,56 @@ +#!/usr/bin/env node +import "dotenv/config"; +import { z } from "zod"; +import fastify from "fastify"; +import { fastifyTRPCPlugin } from "@trpc/server/adapters/fastify"; +import { ClientConfig, http, parseEther, isHex, createClient } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { AppRouter, createAppRouter } from "../src/createAppRouter"; +import { getChainId } from "viem/actions"; + +// TODO: refine zod type to be either CHAIN_ID or RPC_HTTP_URL/RPC_WS_URL +const env = z + .object({ + HOST: z.string().default("0.0.0.0"), + PORT: z.coerce.number().positive().default(3002), + RPC_HTTP_URL: z.string(), + FAUCET_PRIVATE_KEY: z.string().refine(isHex), + DRIP_AMOUNT_ETHER: z + .string() + .default("1") + .transform((ether) => parseEther(ether)), + }) + .parse(process.env, { + errorMap: (issue) => ({ + message: `Missing or invalid environment variable: ${issue.path.join(".")}`, + }), + }); + +const client = createClient({ + transport: http(env.RPC_HTTP_URL), +}); + +const faucetAccount = privateKeyToAccount(env.FAUCET_PRIVATE_KEY); + +// @see https://fastify.dev/docs/latest/ +const server = fastify({ + maxParamLength: 5000, +}); + +await server.register(import("@fastify/cors")); + +// @see https://trpc.io/docs/server/adapters/fastify +server.register(fastifyTRPCPlugin, { + prefix: "/trpc", + trpcOptions: { + router: createAppRouter(), + createContext: async () => ({ + client, + faucetAccount, + dripAmount: env.DRIP_AMOUNT_ETHER, + }), + }, +}); + +await server.listen({ host: env.HOST, port: env.PORT }); +console.log(`faucet server listening on http://${env.HOST}:${env.PORT}`); diff --git a/packages/faucet/package.json b/packages/faucet/package.json new file mode 100644 index 0000000000..9bf3daa1e7 --- /dev/null +++ b/packages/faucet/package.json @@ -0,0 +1,50 @@ +{ + "name": "@latticexyz/faucet", + "version": "2.0.0-next.8", + "description": "Faucet API for Lattice testnet", + "repository": { + "type": "git", + "url": "https://github.com/latticexyz/mud.git", + "directory": "packages/faucet" + }, + "license": "MIT", + "type": "module", + "exports": { + ".": "./dist/src/index.js" + }, + "types": "src/index.ts", + "bin": { + "faucet-server": "./dist/bin/faucet-server.js" + }, + "scripts": { + "build": "pnpm run build:js", + "build:js": "tsup", + "clean": "pnpm run clean:js", + "clean:js": "rimraf dist", + "dev": "tsup --watch", + "lint": "eslint .", + "start": "tsx bin/server", + "test": "tsc --noEmit --skipLibCheck", + "test:ci": "pnpm run test" + }, + "dependencies": { + "@fastify/cors": "^8.3.0", + "@trpc/client": "10.34.0", + "@trpc/server": "10.34.0", + "debug": "^4.3.4", + "dotenv": "^16.0.3", + "fastify": "^4.21.0", + "viem": "1.6.0", + "zod": "^3.21.4" + }, + "devDependencies": { + "@types/debug": "^4.1.7", + "tsup": "^6.7.0", + "tsx": "^3.12.6", + "vitest": "0.31.4" + }, + "publishConfig": { + "access": "public" + }, + "gitHead": "914a1e0ae4a573d685841ca2ea921435057deb8f" +} diff --git a/packages/faucet/src/createAppRouter.ts b/packages/faucet/src/createAppRouter.ts new file mode 100644 index 0000000000..6bbe28000d --- /dev/null +++ b/packages/faucet/src/createAppRouter.ts @@ -0,0 +1,42 @@ +import { z } from "zod"; +import { initTRPC } from "@trpc/server"; +import { Client, Hex, LocalAccount, formatEther, isHex } from "viem"; +import { sendTransaction } from "viem/actions"; +import { debug } from "./debug"; + +export type AppContext = { + client: Client; + faucetAccount: LocalAccount; + dripAmount: bigint; +}; + +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export function createAppRouter() { + const t = initTRPC.context().create(); + + return t.router({ + drip: t.procedure + .input( + z.object({ + address: z.string().refine(isHex), + }) + ) + .mutation(async (opts): Promise => { + const { client, faucetAccount, dripAmount } = opts.ctx; + + const { address } = opts.input; + const tx = await sendTransaction(client, { + chain: null, + account: faucetAccount, + to: address, + value: dripAmount, + }); + + debug(`Dripped ${formatEther(dripAmount)} ETH from ${faucetAccount.address} to ${address} (tx ${tx})`); + + return tx; + }), + }); +} + +export type AppRouter = ReturnType; diff --git a/packages/faucet/src/createClient.ts b/packages/faucet/src/createClient.ts new file mode 100644 index 0000000000..661d987035 --- /dev/null +++ b/packages/faucet/src/createClient.ts @@ -0,0 +1,21 @@ +import { createTRPCProxyClient, httpBatchLink, CreateTRPCProxyClient } from "@trpc/client"; +import type { AppRouter } from "./createAppRouter"; + +type CreateClientOptions = { + /** + * tRPC endpoint URL like `https://faucet.dev.linfra.xyz/trpc`. + */ + url: string; +}; + +/** + * Creates a tRPC client to talk to a MUD faucet. + * + * @param {CreateClientOptions} options See `CreateClientOptions`. + * @returns {CreateTRPCProxyClient} A typed tRPC client. + */ +export function createClient({ url }: CreateClientOptions): CreateTRPCProxyClient { + return createTRPCProxyClient({ + links: [httpBatchLink({ url })], + }); +} diff --git a/packages/faucet/src/debug.ts b/packages/faucet/src/debug.ts new file mode 100644 index 0000000000..a6dd8eec29 --- /dev/null +++ b/packages/faucet/src/debug.ts @@ -0,0 +1,3 @@ +import createDebug from "debug"; + +export const debug = createDebug("mud:faucet"); diff --git a/packages/faucet/src/index.ts b/packages/faucet/src/index.ts new file mode 100644 index 0000000000..03493d8de2 --- /dev/null +++ b/packages/faucet/src/index.ts @@ -0,0 +1,2 @@ +export * from "./createAppRouter"; +export * from "./createClient"; diff --git a/packages/faucet/tsconfig.json b/packages/faucet/tsconfig.json new file mode 100644 index 0000000000..e590f0c026 --- /dev/null +++ b/packages/faucet/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es2021", + "module": "esnext", + "moduleResolution": "node", + "declaration": true, + "sourceMap": true, + "outDir": "dist", + "isolatedModules": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true + } +} diff --git a/packages/faucet/tsup.config.ts b/packages/faucet/tsup.config.ts new file mode 100644 index 0000000000..385f3fc274 --- /dev/null +++ b/packages/faucet/tsup.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts", "bin/faucet-server.ts"], + target: "esnext", + format: ["esm"], + dts: false, + sourcemap: true, + clean: true, + minify: true, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cedd484c9e..b1dec75481 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -405,6 +405,46 @@ importers: packages/ecs-browser: {} + packages/faucet: + dependencies: + '@fastify/cors': + specifier: ^8.3.0 + version: 8.3.0 + '@trpc/client': + specifier: 10.34.0 + version: 10.34.0(@trpc/server@10.34.0) + '@trpc/server': + specifier: 10.34.0 + version: 10.34.0 + debug: + specifier: ^4.3.4 + version: 4.3.4(supports-color@8.1.1) + dotenv: + specifier: ^16.0.3 + version: 16.0.3 + fastify: + specifier: ^4.21.0 + version: 4.21.0 + viem: + specifier: 1.6.0 + version: 1.6.0(typescript@5.1.6)(zod@3.21.4) + zod: + specifier: ^3.21.4 + version: 3.21.4 + devDependencies: + '@types/debug': + specifier: ^4.1.7 + version: 4.1.7 + tsup: + specifier: ^6.7.0 + version: 6.7.0(postcss@8.4.23)(typescript@5.1.6) + tsx: + specifier: ^3.12.6 + version: 3.12.6 + vitest: + specifier: 0.31.4 + version: 0.31.4(jsdom@22.1.0) + packages/gas-report: dependencies: chalk: From 2b585afc8bf706e3d7669c853041c2dba3beca49 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Sat, 16 Sep 2023 23:32:00 +0100 Subject: [PATCH 10/17] build: call docker workflow after each release step (#1516) --- .github/workflows/docker.yml | 9 ++------- .github/workflows/prerelease.yml | 7 +++++-- .github/workflows/release.yml | 5 ++++- .github/workflows/snapshot.yml | 4 ++++ 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3934bb9ce7..31ba84fd42 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,13 +1,7 @@ name: Docker on: - push: - branches: - - main - tags: - # only target a single package tag to avoid running this task for every package on a version release - # in the metadata step, we parse out the specific version used in the tag (e.g. `2.0.0-next.5` and `next`) - - "@latticexyz/common@*" + workflow_call: workflow_dispatch: jobs: @@ -37,6 +31,7 @@ jobs: id: meta uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 with: + # If this doesn't tag properly within the context of `workflow_call`, try `context: git` images: ${{ matrix.image }} tags: | type=raw,value=latest,enable={{is_default_branch}} diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index 6032d2fbaa..9ce49b86b0 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -33,7 +33,7 @@ jobs: run: npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - + - name: Check for pre.json file existence id: check_files uses: andstor/file-existence-action@v2.0.0 @@ -47,10 +47,13 @@ jobs: run: npx changeset pre enter next - name: Create next version PR or publish 🚀 - uses: changesets/action@v1 + uses: changesets/action@v1 with: version: pnpm release:version publish: pnpm release:publish env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + docker: + uses: ./.github/workflows/docker.yml + needs: prerelease diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a0d192c7c3..4a81b3b260 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: - name: "Setup" uses: ./.github/actions/setup - + - name: Clean shell: bash run: pnpm turbo run clean --force --concurrency 10 @@ -60,3 +60,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + docker: + uses: ./.github/workflows/docker.yml + needs: version diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 4837cd0d09..13d4df3c8c 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -48,3 +48,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + docker: + uses: ./.github/workflows/docker.yml + needs: release-snapshot From 9b43029c3c888f8e82b146312f5c2e92321c28a7 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Sat, 16 Sep 2023 23:36:07 +0100 Subject: [PATCH 11/17] feat(store,world): emit Store/World versions (#1511) Co-authored-by: alvrs --- .changeset/soft-fans-wink.md | 16 +++++++ packages/store/gas-report.json | 4 +- packages/store/src/IStore.sol | 4 ++ packages/store/src/StoreCore.sol | 5 +- packages/store/src/StoreRead.sol | 5 ++ packages/store/src/version.sol | 4 ++ packages/store/test/StoreMock.t.sol | 19 ++++++++ packages/store/ts/storeEventsAbi.test.ts | 5 +- packages/world/gas-report.json | 48 +++++++++---------- packages/world/src/World.sol | 7 ++- .../world/src/interfaces/IWorldKernel.sol | 7 ++- packages/world/src/version.sol | 4 ++ packages/world/test/Factories.t.sol | 7 +-- packages/world/test/World.t.sol | 5 +- 14 files changed, 105 insertions(+), 35 deletions(-) create mode 100644 .changeset/soft-fans-wink.md create mode 100644 packages/store/src/version.sol create mode 100644 packages/store/test/StoreMock.t.sol create mode 100644 packages/world/src/version.sol diff --git a/.changeset/soft-fans-wink.md b/.changeset/soft-fans-wink.md new file mode 100644 index 0000000000..add3beb520 --- /dev/null +++ b/.changeset/soft-fans-wink.md @@ -0,0 +1,16 @@ +--- +"@latticexyz/store": minor +"@latticexyz/world": minor +--- + +Add protocol version with corresponding getter and event on deploy + +```solidity +world.worldVersion(); +world.storeVersion(); // a World is also a Store +``` + +```solidity +event HelloWorld(bytes32 indexed worldVersion); +event HelloStore(bytes32 indexed storeVersion); +``` diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 2aa0f2ab67..3a701079a4 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -699,7 +699,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 16415 + "gasUsed": 16438 }, { "file": "test/StoreCoreGas.t.sol", @@ -723,7 +723,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 17400 + "gasUsed": 17423 }, { "file": "test/StoreCoreGas.t.sol", diff --git a/packages/store/src/IStore.sol b/packages/store/src/IStore.sol index b13097f3a4..767ec27b7b 100644 --- a/packages/store/src/IStore.sol +++ b/packages/store/src/IStore.sol @@ -8,6 +8,10 @@ import { Schema } from "./Schema.sol"; import { IStoreHook } from "./IStoreHook.sol"; interface IStoreRead { + event HelloStore(bytes32 indexed storeVersion); + + function storeVersion() external view returns (bytes32); + function getFieldLayout(bytes32 tableId) external view returns (FieldLayout fieldLayout); function getValueSchema(bytes32 tableId) external view returns (Schema valueSchema); diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 8b95cebd92..5c2b974148 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; +import { STORE_VERSION } from "./version.sol"; import { Bytes } from "./Bytes.sol"; import { Storage } from "./Storage.sol"; import { Memory } from "./Memory.sol"; @@ -16,7 +17,7 @@ import { Hook, HookLib } from "./Hook.sol"; import { StoreHookLib, StoreHookType } from "./StoreHook.sol"; library StoreCore { - // note: the preimage of the tuple of keys used to index is part of the event, so it can be used by indexers + event HelloStore(bytes32 indexed version); event StoreSetRecord( bytes32 indexed tableId, bytes32[] keyTuple, @@ -53,6 +54,8 @@ library StoreCore { * Consumers must call this function in their constructor. */ function initialize() internal { + emit HelloStore(STORE_VERSION); + // StoreSwitch uses the storeAddress to decide where to write data to. // If StoreSwitch is called in the context of a Store contract (storeAddress == address(this)), // StoreSwitch uses internal methods to write data instead of external calls. diff --git a/packages/store/src/StoreRead.sol b/packages/store/src/StoreRead.sol index 3017f1510f..82ea6e30fe 100644 --- a/packages/store/src/StoreRead.sol +++ b/packages/store/src/StoreRead.sol @@ -1,12 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; +import { STORE_VERSION } from "./version.sol"; import { IStoreRead } from "./IStore.sol"; import { StoreCore } from "./StoreCore.sol"; import { FieldLayout } from "./FieldLayout.sol"; import { Schema } from "./Schema.sol"; contract StoreRead is IStoreRead { + function storeVersion() public pure returns (bytes32) { + return STORE_VERSION; + } + function getFieldLayout(bytes32 tableId) public view virtual returns (FieldLayout fieldLayout) { fieldLayout = StoreCore.getFieldLayout(tableId); } diff --git a/packages/store/src/version.sol b/packages/store/src/version.sol new file mode 100644 index 0000000000..9f024319ad --- /dev/null +++ b/packages/store/src/version.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +bytes32 constant STORE_VERSION = "0.0.0"; diff --git a/packages/store/test/StoreMock.t.sol b/packages/store/test/StoreMock.t.sol new file mode 100644 index 0000000000..641ff8f528 --- /dev/null +++ b/packages/store/test/StoreMock.t.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import { Test } from "forge-std/Test.sol"; +import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; +import { STORE_VERSION } from "../src/version.sol"; +import { StoreCore } from "../src/StoreCore.sol"; +import { StoreMock } from "../test/StoreMock.sol"; +import { StoreSwitch } from "../src/StoreSwitch.sol"; + +contract StoreMockTest is Test { + event HelloStore(bytes32 indexed storeVersion); + + function testStoreMockConstrctor() public { + vm.expectEmit(true, true, true, true); + emit HelloStore(STORE_VERSION); + new StoreMock(); + } +} diff --git a/packages/store/ts/storeEventsAbi.test.ts b/packages/store/ts/storeEventsAbi.test.ts index be25f2cd8a..17b704d341 100644 --- a/packages/store/ts/storeEventsAbi.test.ts +++ b/packages/store/ts/storeEventsAbi.test.ts @@ -7,7 +7,10 @@ import { AbiEvent } from "abitype"; describe("storeEventsAbi", () => { it("should match the store ABI", () => { - const expectedEvents = IStoreAbi.filter((item) => item.type === "event") as readonly AbiEvent[]; + const expectedEvents = IStoreAbi.filter((item) => item.type === "event").filter( + (item) => item.name !== "HelloStore" + ) as readonly AbiEvent[]; + const expectedAbi = expectedEvents .map((item) => ({ // return data in a shape that matches abitype's parseAbi diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 35515f840a..cb6c335b40 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": 1415306 + "gasUsed": 1415308 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1415306 + "gasUsed": 1415308 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 158959 + "gasUsed": 158915 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1415306 + "gasUsed": 1415308 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1415306 + "gasUsed": 1415308 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 22016 + "gasUsed": 21994 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 171520 + "gasUsed": 171498 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1415306 + "gasUsed": 1415308 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 20738 + "gasUsed": 20716 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 88171 + "gasUsed": 88149 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 654597 + "gasUsed": 654598 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,49 +117,49 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 654597 + "gasUsed": 654598 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 134495 + "gasUsed": 134451 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 654597 + "gasUsed": 654598 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 104070 + "gasUsed": 104026 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 32927 + "gasUsed": 32905 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 654597 + "gasUsed": 654598 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 139109 + "gasUsed": 139065 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 103868 + "gasUsed": 103824 }, { "file": "test/query.t.sol", @@ -255,7 +255,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 678986 + "gasUsed": 678987 }, { "file": "test/UniqueEntityModule.t.sol", @@ -267,7 +267,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 669045 + "gasUsed": 669046 }, { "file": "test/UniqueEntityModule.t.sol", @@ -279,7 +279,7 @@ "file": "test/World.t.sol", "test": "testCall", "name": "call a system via the World", - "gasUsed": 12288 + "gasUsed": 12333 }, { "file": "test/World.t.sol", @@ -309,7 +309,7 @@ "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 58887 + "gasUsed": 58888 }, { "file": "test/World.t.sol", @@ -321,7 +321,7 @@ "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 79481 + "gasUsed": 79482 }, { "file": "test/World.t.sol", diff --git a/packages/world/src/World.sol b/packages/world/src/World.sol index bc3895dd1e..88265fa063 100644 --- a/packages/world/src/World.sol +++ b/packages/world/src/World.sol @@ -10,6 +10,7 @@ import { Schema } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; +import { WORLD_VERSION } from "./version.sol"; import { System } from "./System.sol"; import { ResourceSelector } from "./ResourceSelector.sol"; import { ROOT_NAMESPACE, ROOT_NAME } from "./constants.sol"; @@ -38,10 +39,14 @@ contract World is StoreRead, IStoreData, IWorldKernel { using ResourceSelector for bytes32; address public immutable creator; + function worldVersion() public pure returns (bytes32) { + return WORLD_VERSION; + } + constructor() { creator = msg.sender; StoreCore.initialize(); - emit HelloWorld(); + emit HelloWorld(WORLD_VERSION); } /** diff --git a/packages/world/src/interfaces/IWorldKernel.sol b/packages/world/src/interfaces/IWorldKernel.sol index 1dc9f602ad..d5b1c5cec4 100644 --- a/packages/world/src/interfaces/IWorldKernel.sol +++ b/packages/world/src/interfaces/IWorldKernel.sol @@ -39,7 +39,12 @@ interface IWorldCall { * registered functions selectors from the `CoreModule`. */ interface IWorldKernel is IWorldModuleInstallation, IWorldCall, IWorldErrors { - event HelloWorld(); + event HelloWorld(bytes32 indexed worldVersion); + + /** + * The version of the World. + */ + function worldVersion() external view returns (bytes32); /** * The immutable original deployer of the World. diff --git a/packages/world/src/version.sol b/packages/world/src/version.sol new file mode 100644 index 0000000000..bd7a91f4d6 --- /dev/null +++ b/packages/world/src/version.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +bytes32 constant WORLD_VERSION = "0.0.0"; diff --git a/packages/world/test/Factories.t.sol b/packages/world/test/Factories.t.sol index 9cc72f6a3d..5887d42ddb 100644 --- a/packages/world/test/Factories.t.sol +++ b/packages/world/test/Factories.t.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.0; import { Test, console } from "forge-std/Test.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; +import { WORLD_VERSION } from "../src/version.sol"; import { World } from "../src/World.sol"; import { CoreModule } from "../src/modules/core/CoreModule.sol"; import { Create2Factory } from "../src/factories/Create2Factory.sol"; @@ -16,7 +17,7 @@ import { ROOT_NAMESPACE } from "../src/constants.sol"; contract FactoriesTest is Test { event ContractDeployed(address addr, uint256 salt); event WorldDeployed(address indexed newContract); - event HelloWorld(); + event HelloWorld(bytes32 indexed version); function calculateAddress( address deployingAddress, @@ -58,8 +59,8 @@ contract FactoriesTest is Test { address calculatedAddress = calculateAddress(worldFactoryAddress, bytes32(0), type(World).creationCode); // Check for HelloWorld event from World - vm.expectEmit(true, false, false, false); - emit HelloWorld(); + vm.expectEmit(true, true, true, true); + emit HelloWorld(WORLD_VERSION); // Check for WorldDeployed event from Factory vm.expectEmit(true, false, false, false); diff --git a/packages/world/test/World.t.sol b/packages/world/test/World.t.sol index 9d651d3ef2..6a3406fe63 100644 --- a/packages/world/test/World.t.sol +++ b/packages/world/test/World.t.sol @@ -20,6 +20,7 @@ import { StoreHookLib } from "@latticexyz/store/src/StoreHook.sol"; import { RevertSubscriber } from "@latticexyz/store/test/RevertSubscriber.sol"; import { EchoSubscriber } from "@latticexyz/store/test/EchoSubscriber.sol"; +import { WORLD_VERSION } from "../src/version.sol"; import { World } from "../src/World.sol"; import { System } from "../src/System.sol"; import { ResourceSelector } from "../src/ResourceSelector.sol"; @@ -158,7 +159,7 @@ contract RevertSystemHook is SystemHook { contract WorldTest is Test, GasReporter { using ResourceSelector for bytes32; - event HelloWorld(); + event HelloWorld(bytes32 indexed worldVersion); event HookCalled(bytes data); event SystemHookCalled(bytes data); event WorldTestSystemLog(string log); @@ -196,7 +197,7 @@ contract WorldTest is Test, GasReporter { CoreModule coreModule = new CoreModule(); vm.expectEmit(true, true, true, true); - emit HelloWorld(); + emit HelloWorld(WORLD_VERSION); IBaseWorld newWorld = IBaseWorld(address(new World())); // Expect the creator to be the original deployer From ed07018b86046fec20786f4752ac98a4175eb5eb Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Sat, 16 Sep 2023 23:43:25 +0100 Subject: [PATCH 12/17] fix(store-indexer): subscribe postgres indexer to stream (#1514) --- .changeset/chilled-kangaroos-dream.md | 5 +++++ packages/store-indexer/bin/postgres-indexer.ts | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 .changeset/chilled-kangaroos-dream.md diff --git a/.changeset/chilled-kangaroos-dream.md b/.changeset/chilled-kangaroos-dream.md new file mode 100644 index 0000000000..a1edaf3719 --- /dev/null +++ b/.changeset/chilled-kangaroos-dream.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store-indexer": patch +--- + +Fixes postgres indexer stopping sync after it catches up to the latest block. diff --git a/packages/store-indexer/bin/postgres-indexer.ts b/packages/store-indexer/bin/postgres-indexer.ts index 8370b10338..64cc564f24 100644 --- a/packages/store-indexer/bin/postgres-indexer.ts +++ b/packages/store-indexer/bin/postgres-indexer.ts @@ -105,6 +105,8 @@ const { latestBlockNumber$, storedBlockLogs$ } = await createStoreSync({ maxBlockRange: env.MAX_BLOCK_RANGE, }); +storedBlockLogs$.subscribe(); + combineLatest([latestBlockNumber$, storedBlockLogs$]) .pipe( filter( From 759514d8b980fa5fe49a4ef919d8008b215f2af8 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Sun, 17 Sep 2023 14:55:05 +0100 Subject: [PATCH 13/17] feat(store,world): move hooks to bit flags (#1527) Co-authored-by: alvarius --- .changeset/few-jars-turn.md | 42 +++ packages/store/gas-report.json | 30 +- packages/store/src/Hook.sol | 5 +- packages/store/src/StoreCore.sol | 28 +- packages/store/src/StoreHook.sol | 40 --- packages/store/src/storeHookTypes.sol | 10 + packages/store/test/Hook.t.sol | 56 ++-- packages/store/test/StoreCore.t.sol | 56 +--- packages/store/test/StoreCoreGas.t.sol | 28 +- packages/store/test/StoreHook.t.sol | 272 ++++-------------- packages/world/gas-report.json | 38 +-- packages/world/src/SystemCall.sol | 6 +- packages/world/src/SystemHook.sol | 25 -- .../WorldRegistrationSystem.sol | 3 +- .../modules/keysintable/KeysInTableModule.sol | 15 +- .../keyswithvalue/KeysWithValueModule.sol | 15 +- packages/world/src/systemHookTypes.sol | 5 + packages/world/test/SystemHook.t.sol | 62 ++-- packages/world/test/World.t.sol | 81 ++---- 19 files changed, 266 insertions(+), 551 deletions(-) create mode 100644 .changeset/few-jars-turn.md create mode 100644 packages/store/src/storeHookTypes.sol create mode 100644 packages/world/src/systemHookTypes.sol diff --git a/.changeset/few-jars-turn.md b/.changeset/few-jars-turn.md new file mode 100644 index 0000000000..93c3488d5f --- /dev/null +++ b/.changeset/few-jars-turn.md @@ -0,0 +1,42 @@ +--- +"@latticexyz/store": major +"@latticexyz/world": major +--- + +Moved the registration of store hooks and systems hooks to bitmaps with bitwise operator instead of a struct. + +```diff +- import { StoreHookLib } from "@latticexyz/src/StoreHook.sol"; ++ import { ++ BEFORE_SET_RECORD, ++ BEFORE_SET_FIELD, ++ BEFORE_DELETE_RECORD ++ } from "@latticexyz/store/storeHookTypes.sol"; + + StoreCore.registerStoreHook( + tableId, + subscriber, +- StoreHookLib.encodeBitmap({ +- onBeforeSetRecord: true, +- onAfterSetRecord: false, +- onBeforeSetField: true, +- onAfterSetField: false, +- onBeforeDeleteRecord: true, +- onAfterDeleteRecord: false +- }) ++ BEFORE_SET_RECORD | BEFORE_SET_FIELD | BEFORE_DELETE_RECORD + ); +``` + +```diff +- import { SystemHookLib } from "../src/SystemHook.sol"; ++ import { BEFORE_CALL_SYSTEM, AFTER_CALL_SYSTEM } from "../src/systemHookTypes.sol"; + + world.registerSystemHook( + systemId, + subscriber, +- SystemHookLib.encodeBitmap({ onBeforeCallSystem: true, onAfterCallSystem: true }) ++ BEFORE_CALL_SYSTEM | AFTER_CALL_SYSTEM + ); + +``` diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 3a701079a4..839855935a 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -345,7 +345,7 @@ "file": "test/Hook.t.sol", "test": "testIsEnabled", "name": "check if hook is enabled", - "gasUsed": 114 + "gasUsed": 108 }, { "file": "test/KeyEncoding.t.sol", @@ -681,49 +681,49 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 60413 + "gasUsed": 60150 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 71044 + "gasUsed": 71004 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 20820 + "gasUsed": 20780 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 16438 + "gasUsed": 16398 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 60413 + "gasUsed": 60150 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 164166 + "gasUsed": 164126 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 24020 + "gasUsed": 23980 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 17423 + "gasUsed": 17383 }, { "file": "test/StoreCoreGas.t.sol", @@ -891,13 +891,13 @@ "file": "test/StoreHook.t.sol", "test": "testCallHook", "name": "call an enabled hook", - "gasUsed": 14598 + "gasUsed": 14588 }, { "file": "test/StoreHook.t.sol", "test": "testCallHook", "name": "call a disabled hook", - "gasUsed": 133 + "gasUsed": 123 }, { "file": "test/StoreHook.t.sol", @@ -905,17 +905,11 @@ "name": "get store hook address", "gasUsed": 1 }, - { - "file": "test/StoreHook.t.sol", - "test": "testGetBitmap", - "name": "get store hook bitmap", - "gasUsed": 1 - }, { "file": "test/StoreHook.t.sol", "test": "testIsEnabled", "name": "check if store hook is enabled", - "gasUsed": 129 + "gasUsed": 108 }, { "file": "test/StoreSwitch.t.sol", diff --git a/packages/store/src/Hook.sol b/packages/store/src/Hook.sol index 2d7da97a6f..d7511d4dc2 100644 --- a/packages/store/src/Hook.sol +++ b/packages/store/src/Hook.sol @@ -52,9 +52,8 @@ library HookInstance { /** * Check if the given hook type is enabled in the hook */ - function isEnabled(Hook self, uint8 hookType) internal pure returns (bool) { - // Pick the bitmap encoded in the rightmost byte from the hook and check if the bit at the given hook type is set - return (getBitmap(self) & (1 << uint8(hookType))) != 0; + function isEnabled(Hook self, uint8 hookTypes) internal pure returns (bool) { + return (getBitmap(self) & hookTypes) == hookTypes; } /** diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 5c2b974148..0d7e48548a 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -14,7 +14,7 @@ import { IStoreErrors } from "./IStoreErrors.sol"; import { IStoreHook } from "./IStoreHook.sol"; import { StoreSwitch } from "./StoreSwitch.sol"; import { Hook, HookLib } from "./Hook.sol"; -import { StoreHookLib, StoreHookType } from "./StoreHook.sol"; +import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SET_FIELD, AFTER_SET_FIELD, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "./storeHookTypes.sol"; library StoreCore { event HelloStore(bytes32 indexed version); @@ -176,7 +176,7 @@ library StoreCore { * Register hooks to be called when a record or field is set or deleted */ function registerStoreHook(bytes32 tableId, IStoreHook hookAddress, uint8 enabledHooksBitmap) internal { - StoreHooks.push(tableId, Hook.unwrap(StoreHookLib.encode(hookAddress, enabledHooksBitmap))); + StoreHooks.push(tableId, Hook.unwrap(HookLib.encode(address(hookAddress), enabledHooksBitmap))); } /** @@ -216,7 +216,7 @@ library StoreCore { bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_RECORD))) { + if (hook.isEnabled(BEFORE_SET_RECORD)) { IStoreHook(hook.getAddress()).onBeforeSetRecord( tableId, keyTuple, @@ -269,7 +269,7 @@ library StoreCore { // Call onAfterSetRecord hooks (after modifying the state) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.AFTER_SET_RECORD))) { + if (hook.isEnabled(AFTER_SET_RECORD)) { IStoreHook(hook.getAddress()).onAfterSetRecord( tableId, keyTuple, @@ -296,7 +296,7 @@ library StoreCore { bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { + if (hook.isEnabled(BEFORE_SET_FIELD)) { IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, fieldIndex, data, fieldLayout); } } @@ -310,7 +310,7 @@ library StoreCore { // Call onAfterSetField hooks (after modifying the state) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.AFTER_SET_FIELD))) { + if (hook.isEnabled(AFTER_SET_FIELD)) { IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, fieldIndex, data, fieldLayout); } } @@ -327,7 +327,7 @@ library StoreCore { bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.BEFORE_DELETE_RECORD))) { + if (hook.isEnabled(BEFORE_DELETE_RECORD)) { IStoreHook(hook.getAddress()).onBeforeDeleteRecord(tableId, keyTuple, fieldLayout); } } @@ -345,7 +345,7 @@ library StoreCore { // Call onAfterDeleteRecord hooks for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.AFTER_DELETE_RECORD))) { + if (hook.isEnabled(AFTER_DELETE_RECORD)) { IStoreHook(hook.getAddress()).onAfterDeleteRecord(tableId, keyTuple, fieldLayout); } } @@ -375,7 +375,7 @@ library StoreCore { bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { + if (hook.isEnabled(BEFORE_SET_FIELD)) { IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } @@ -385,7 +385,7 @@ library StoreCore { // Call onAfterSetField hooks (after modifying the state) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.AFTER_SET_FIELD))) { + if (hook.isEnabled(AFTER_SET_FIELD)) { IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } @@ -416,7 +416,7 @@ library StoreCore { bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { + if (hook.isEnabled(BEFORE_SET_FIELD)) { IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } @@ -426,7 +426,7 @@ library StoreCore { // Call onAfterSetField hooks (after modifying the state) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.AFTER_SET_FIELD))) { + if (hook.isEnabled(AFTER_SET_FIELD)) { IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } @@ -468,7 +468,7 @@ library StoreCore { bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD))) { + if (hook.isEnabled(BEFORE_SET_FIELD)) { IStoreHook(hook.getAddress()).onBeforeSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } @@ -478,7 +478,7 @@ library StoreCore { // Call onAfterSetField hooks (after modifying the state) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(StoreHookType.AFTER_SET_FIELD))) { + if (hook.isEnabled(AFTER_SET_FIELD)) { IStoreHook(hook.getAddress()).onAfterSetField(tableId, keyTuple, fieldIndex, fullData, fieldLayout); } } diff --git a/packages/store/src/StoreHook.sol b/packages/store/src/StoreHook.sol index 0d7de0f899..0fff2ce06e 100644 --- a/packages/store/src/StoreHook.sol +++ b/packages/store/src/StoreHook.sol @@ -1,49 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import { Hook, HookLib } from "./Hook.sol"; import { IStoreHook, STORE_HOOK_INTERFACE_ID } from "./IStoreHook.sol"; import { ERC165_INTERFACE_ID } from "./IERC165.sol"; -enum StoreHookType { - BEFORE_SET_RECORD, - AFTER_SET_RECORD, - BEFORE_SET_FIELD, - AFTER_SET_FIELD, - BEFORE_DELETE_RECORD, - AFTER_DELETE_RECORD -} - -library StoreHookLib { - /** - * Encode the bitmap into a single byte - */ - function encodeBitmap( - bool onBeforeSetRecord, - bool onAfterSetRecord, - bool onBeforeSetField, - bool onAfterSetField, - bool onBeforeDeleteRecord, - bool onAfterDeleteRecord - ) internal pure returns (uint8) { - uint256 bitmap = 0; - if (onBeforeSetRecord) bitmap |= 1 << uint8(StoreHookType.BEFORE_SET_RECORD); - if (onAfterSetRecord) bitmap |= 1 << uint8(StoreHookType.AFTER_SET_RECORD); - if (onBeforeSetField) bitmap |= 1 << uint8(StoreHookType.BEFORE_SET_FIELD); - if (onAfterSetField) bitmap |= 1 << uint8(StoreHookType.AFTER_SET_FIELD); - if (onBeforeDeleteRecord) bitmap |= 1 << uint8(StoreHookType.BEFORE_DELETE_RECORD); - if (onAfterDeleteRecord) bitmap |= 1 << uint8(StoreHookType.AFTER_DELETE_RECORD); - return uint8(bitmap); - } - - /** - * Encode enabled hooks into a bitmap with 1 bit per hook, and pack the bitmap with the store hook address into a bytes21 value - */ - function encode(IStoreHook storeHook, uint8 enabledHooksBitmap) internal pure returns (Hook) { - return HookLib.encode(address(storeHook), enabledHooksBitmap); - } -} - abstract contract StoreHook is IStoreHook { // ERC-165 supportsInterface (see https://eips.ethereum.org/EIPS/eip-165) function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) { diff --git a/packages/store/src/storeHookTypes.sol b/packages/store/src/storeHookTypes.sol new file mode 100644 index 0000000000..e6a9f00718 --- /dev/null +++ b/packages/store/src/storeHookTypes.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +uint8 constant BEFORE_SET_RECORD = 1 << 0; +uint8 constant AFTER_SET_RECORD = 1 << 1; +// TODO: do we need to differentiate between static and dynamic set field? +uint8 constant BEFORE_SET_FIELD = 1 << 2; +uint8 constant AFTER_SET_FIELD = 1 << 3; +uint8 constant BEFORE_DELETE_RECORD = 1 << 4; +uint8 constant AFTER_DELETE_RECORD = 1 << 5; diff --git a/packages/store/test/Hook.t.sol b/packages/store/test/Hook.t.sol index c328d701d4..d3c87e4060 100644 --- a/packages/store/test/Hook.t.sol +++ b/packages/store/test/Hook.t.sol @@ -6,15 +6,15 @@ import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { Hook, HookLib } from "../src/Hook.sol"; contract HookTest is Test, GasReporter { - uint8 public NONE = 0x00; // 0b00000000 - uint8 public FIRST = 0x01; // 0b00000001 - uint8 public SECOND = 0x02; // 0b00000010 - uint8 public THIRD = 0x04; // 0b00000100 - uint8 public FOURTH = 0x08; // 0b00001000 - uint8 public FIFTH = 0x10; // 0b00010000 - uint8 public SIXTH = 0x20; // 0b00100000 - uint8 public SEVENTH = 0x40; // 0b01000000 - uint8 public EIGHTH = 0x80; // 0b10000000 + uint8 public constant NONE = 0; // 0b00000000 + uint8 public constant FIRST = 1 << 0; // 0b00000001 + uint8 public constant SECOND = 1 << 1; // 0b00000010 + uint8 public constant THIRD = 1 << 2; // 0b00000100 + uint8 public constant FOURTH = 1 << 3; // 0b00001000 + uint8 public constant FIFTH = 1 << 4; // 0b00010000 + uint8 public constant SIXTH = 1 << 5; // 0b00100000 + uint8 public constant SEVENTH = 1 << 6; // 0b01000000 + uint8 public constant EIGHTH = 1 << 7; // 0b10000000 function testFuzzEncode(address hookAddress, uint8 encodedHooks) public { assertEq( @@ -24,20 +24,20 @@ contract HookTest is Test, GasReporter { } function testIsEnabled() public { - Hook hook = HookLib.encode(address(0), THIRD); + Hook hook = HookLib.encode(address(0), THIRD | FIFTH); startGasReport("check if hook is enabled"); - hook.isEnabled(0); + hook.isEnabled(EIGHTH); endGasReport(); - assertFalse(hook.isEnabled(0)); - assertFalse(hook.isEnabled(1)); - assertTrue(hook.isEnabled(2)); - assertFalse(hook.isEnabled(3)); - assertFalse(hook.isEnabled(4)); - assertFalse(hook.isEnabled(5)); - assertFalse(hook.isEnabled(6)); - assertFalse(hook.isEnabled(7)); + assertFalse(hook.isEnabled(FIRST), "FIRST"); + assertFalse(hook.isEnabled(SECOND), "SECOND"); + assertTrue(hook.isEnabled(THIRD), "THIRD"); + assertFalse(hook.isEnabled(FOURTH), "FOURTH"); + assertTrue(hook.isEnabled(FIFTH), "FIFTH"); + assertFalse(hook.isEnabled(SIXTH), "SIXTH"); + assertFalse(hook.isEnabled(SEVENTH), "SEVENTH"); + assertFalse(hook.isEnabled(EIGHTH), "EIGHTH"); } function testFuzzIsEnabled( @@ -51,7 +51,7 @@ contract HookTest is Test, GasReporter { bool seventh, bool eighth ) public { - uint8 encodedHooks = 0x00; + uint8 encodedHooks = 0; if (first) encodedHooks |= FIRST; if (second) encodedHooks |= SECOND; if (third) encodedHooks |= THIRD; @@ -63,14 +63,14 @@ contract HookTest is Test, GasReporter { Hook hook = HookLib.encode(hookAddress, encodedHooks); - assertEq(hook.isEnabled(0), first); - assertEq(hook.isEnabled(1), second); - assertEq(hook.isEnabled(2), third); - assertEq(hook.isEnabled(3), fourth); - assertEq(hook.isEnabled(4), fifth); - assertEq(hook.isEnabled(5), sixth); - assertEq(hook.isEnabled(6), seventh); - assertEq(hook.isEnabled(7), eighth); + assertEq(hook.isEnabled(FIRST), first, "FIRST"); + assertEq(hook.isEnabled(SECOND), second, "SECOND"); + assertEq(hook.isEnabled(THIRD), third, "THIRD"); + assertEq(hook.isEnabled(FOURTH), fourth, "FOURTH"); + assertEq(hook.isEnabled(FIFTH), fifth, "FIFTH"); + assertEq(hook.isEnabled(SIXTH), sixth, "SIXTH"); + assertEq(hook.isEnabled(SEVENTH), seventh, "SEVENTH"); + assertEq(hook.isEnabled(EIGHTH), eighth, "EIGHTH"); } function testFuzzGetAddressAndBitmap(address hookAddress, uint8 encodedHooks) public { diff --git a/packages/store/test/StoreCore.t.sol b/packages/store/test/StoreCore.t.sol index fc1f25134e..5228db737d 100644 --- a/packages/store/test/StoreCore.t.sol +++ b/packages/store/test/StoreCore.t.sol @@ -16,7 +16,7 @@ import { IStore } from "../src/IStore.sol"; import { StoreSwitch } from "../src/StoreSwitch.sol"; import { Tables, TablesTableId } from "../src/codegen/Tables.sol"; import { FieldLayoutEncodeHelper } from "./FieldLayoutEncodeHelper.sol"; -import { StoreHookLib } from "../src/StoreHook.sol"; +import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SET_FIELD, AFTER_SET_FIELD, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "../src/storeHookTypes.sol"; import { SchemaEncodeHelper } from "./SchemaEncodeHelper.sol"; import { StoreMock } from "./StoreMock.sol"; import { MirrorSubscriber, indexerTableId } from "./MirrorSubscriber.sol"; @@ -977,18 +977,7 @@ contract StoreCoreTest is Test, StoreMock { new string[](1) ); - IStore(this).registerStoreHook( - tableId, - subscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: false, - onBeforeSetField: true, - onAfterSetField: false, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: false - }) - ); + IStore(this).registerStoreHook(tableId, subscriber, BEFORE_SET_RECORD | BEFORE_SET_FIELD | BEFORE_DELETE_RECORD); bytes memory staticData = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); @@ -1031,27 +1020,23 @@ contract StoreCoreTest is Test, StoreMock { IStore(this).registerStoreHook( tableId, revertSubscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: true, - onBeforeSetField: true, - onAfterSetField: true, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: true - }) + BEFORE_SET_RECORD | + AFTER_SET_RECORD | + BEFORE_SET_FIELD | + AFTER_SET_FIELD | + BEFORE_DELETE_RECORD | + AFTER_DELETE_RECORD ); // Register both subscribers IStore(this).registerStoreHook( tableId, echoSubscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: true, - onBeforeSetField: true, - onAfterSetField: true, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: true - }) + BEFORE_SET_RECORD | + AFTER_SET_RECORD | + BEFORE_SET_FIELD | + AFTER_SET_FIELD | + BEFORE_DELETE_RECORD | + AFTER_DELETE_RECORD ); bytes memory data = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); @@ -1122,18 +1107,7 @@ contract StoreCoreTest is Test, StoreMock { new string[](2) ); - IStore(this).registerStoreHook( - tableId, - subscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: false, - onBeforeSetField: true, - onAfterSetField: false, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: false - }) - ); + IStore(this).registerStoreHook(tableId, subscriber, BEFORE_SET_RECORD | BEFORE_SET_FIELD | BEFORE_DELETE_RECORD); uint32[] memory arrayData = new uint32[](1); arrayData[0] = 0x01020304; diff --git a/packages/store/test/StoreCoreGas.t.sol b/packages/store/test/StoreCoreGas.t.sol index 5c30514ccd..cd8227872d 100644 --- a/packages/store/test/StoreCoreGas.t.sol +++ b/packages/store/test/StoreCoreGas.t.sol @@ -15,10 +15,10 @@ import { StoreMock } from "../test/StoreMock.sol"; import { IStoreErrors } from "../src/IStoreErrors.sol"; import { IStore } from "../src/IStore.sol"; import { FieldLayoutEncodeHelper } from "./FieldLayoutEncodeHelper.sol"; -import { StoreHookLib } from "../src/StoreHook.sol"; import { SchemaEncodeHelper } from "./SchemaEncodeHelper.sol"; import { StoreMock } from "./StoreMock.sol"; import { MirrorSubscriber } from "./MirrorSubscriber.sol"; +import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SET_FIELD, AFTER_SET_FIELD, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "../src/storeHookTypes.sol"; struct TestStruct { uint128 firstData; @@ -612,18 +612,7 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { ); startGasReport("register subscriber"); - StoreCore.registerStoreHook( - tableId, - subscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: false, - onBeforeSetField: true, - onAfterSetField: false, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: false - }) - ); + StoreCore.registerStoreHook(tableId, subscriber, BEFORE_SET_RECORD | BEFORE_SET_FIELD | BEFORE_DELETE_RECORD); endGasReport(); bytes memory staticData = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); @@ -665,18 +654,7 @@ contract StoreCoreGasTest is Test, GasReporter, StoreMock { ); startGasReport("register subscriber"); - StoreCore.registerStoreHook( - tableId, - subscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: false, - onBeforeSetField: true, - onAfterSetField: false, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: false - }) - ); + StoreCore.registerStoreHook(tableId, subscriber, BEFORE_SET_RECORD | BEFORE_SET_FIELD | BEFORE_DELETE_RECORD); endGasReport(); uint32[] memory arrayData = new uint32[](1); diff --git a/packages/store/test/StoreHook.t.sol b/packages/store/test/StoreHook.t.sol index 311dcbc90a..e8264e5aef 100644 --- a/packages/store/test/StoreHook.t.sol +++ b/packages/store/test/StoreHook.t.sol @@ -7,12 +7,11 @@ import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { EchoSubscriber } from "./EchoSubscriber.sol"; import { RevertSubscriber } from "./RevertSubscriber.sol"; -import { Hook } from "../src/Hook.sol"; -import { StoreHookType } from "../src/StoreHook.sol"; -import { StoreHookLib } from "../src/StoreHook.sol"; +import { Hook, HookLib } from "../src/Hook.sol"; import { IStoreHook } from "../src/IStore.sol"; import { PackedCounter } from "../src/PackedCounter.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; +import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SET_FIELD, AFTER_SET_FIELD, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "../src/storeHookTypes.sol"; contract StoreHookTest is Test, GasReporter { event HookCalled(bytes); @@ -29,106 +28,20 @@ contract StoreHookTest is Test, GasReporter { FieldLayout private fieldLayout = FieldLayout.wrap(0); function testEncodeBitmap() public { - assertEq( - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: false, - onAfterSetRecord: false, - onBeforeSetField: false, - onAfterSetField: false, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: false - }), - uint8(0x00), - "0b00000000" - ); - - assertEq( - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: false, - onBeforeSetField: false, - onAfterSetField: false, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: false - }), - uint8(0x01), - "0b00000001" - ); - - assertEq( - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: false, - onAfterSetRecord: true, - onBeforeSetField: false, - onAfterSetField: false, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: false - }), - uint8(0x02), - "0b00000010" - ); - - assertEq( - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: false, - onAfterSetRecord: false, - onBeforeSetField: true, - onAfterSetField: false, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: false - }), - uint8(0x04), - "0b00000100" - ); - - assertEq( - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: false, - onAfterSetRecord: false, - onBeforeSetField: false, - onAfterSetField: true, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: false - }), - uint8(0x08), - "0b00001000" - ); - - assertEq( - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: false, - onAfterSetRecord: false, - onBeforeSetField: false, - onAfterSetField: false, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: false - }), - uint8(0x10), - "0b00010000" - ); + assertEq(BEFORE_SET_RECORD, uint8(0x01), "0b00000001"); + assertEq(AFTER_SET_RECORD, uint8(0x02), "0b00000010"); + assertEq(BEFORE_SET_FIELD, uint8(0x04), "0b00000100"); + assertEq(AFTER_SET_FIELD, uint8(0x08), "0b00001000"); + assertEq(BEFORE_DELETE_RECORD, uint8(0x10), "0b00010000"); + assertEq(AFTER_DELETE_RECORD, uint8(0x20), "0b00100000"); assertEq( - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: false, - onAfterSetRecord: false, - onBeforeSetField: false, - onAfterSetField: false, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: true - }), - uint8(0x20), - "0b00100000" - ); - - assertEq( - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: true, - onBeforeSetField: true, - onAfterSetField: true, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: true - }), + BEFORE_SET_RECORD | + AFTER_SET_RECORD | + BEFORE_SET_FIELD | + AFTER_SET_FIELD | + BEFORE_DELETE_RECORD | + AFTER_DELETE_RECORD, uint8(0x3f), "0b00111111" ); @@ -137,16 +50,14 @@ contract StoreHookTest is Test, GasReporter { function testEncode() public { assertEq( Hook.unwrap( - StoreHookLib.encode( - echoSubscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: true, - onBeforeSetField: true, - onAfterSetField: true, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: true - }) + HookLib.encode( + address(echoSubscriber), + BEFORE_SET_RECORD | + AFTER_SET_RECORD | + BEFORE_SET_FIELD | + AFTER_SET_FIELD | + BEFORE_DELETE_RECORD | + AFTER_DELETE_RECORD ) ), bytes21(abi.encodePacked(echoSubscriber, uint8(0x3f))) @@ -162,43 +73,33 @@ contract StoreHookTest is Test, GasReporter { bool enableBeforeDeleteRecord, bool enableAfterDeleteRecord ) public { - uint8 encodedBitmap = StoreHookLib.encodeBitmap({ - onBeforeSetRecord: enableBeforeSetRecord, - onAfterSetRecord: enableAfterSetRecord, - onBeforeSetField: enableBeforeSetField, - onAfterSetField: enableAfterSetField, - onBeforeDeleteRecord: enableBeforeDeleteRecord, - onAfterDeleteRecord: enableAfterDeleteRecord - }); + uint8 enabledHooks = 0; + if (enableBeforeSetRecord) enabledHooks |= BEFORE_SET_RECORD; + if (enableAfterSetRecord) enabledHooks |= AFTER_SET_RECORD; + if (enableBeforeSetField) enabledHooks |= BEFORE_SET_FIELD; + if (enableAfterSetField) enabledHooks |= AFTER_SET_FIELD; + if (enableBeforeDeleteRecord) enabledHooks |= BEFORE_DELETE_RECORD; + if (enableAfterDeleteRecord) enabledHooks |= AFTER_DELETE_RECORD; + assertEq( - Hook.unwrap(StoreHookLib.encode(IStoreHook(hookAddress), encodedBitmap)), - bytes21(abi.encodePacked(hookAddress, encodedBitmap)) + Hook.unwrap(HookLib.encode(hookAddress, enabledHooks)), + bytes21(abi.encodePacked(hookAddress, enabledHooks)) ); } function testIsEnabled() public { - Hook storeHook = StoreHookLib.encode( - echoSubscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: false, - onAfterSetRecord: false, - onBeforeSetField: true, - onAfterSetField: false, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: false - }) - ); + Hook storeHook = HookLib.encode(address(echoSubscriber), BEFORE_SET_FIELD | AFTER_DELETE_RECORD); startGasReport("check if store hook is enabled"); - storeHook.isEnabled(uint8(StoreHookType.BEFORE_SET_RECORD)); + storeHook.isEnabled(BEFORE_SET_RECORD); endGasReport(); - assertEq(storeHook.isEnabled(uint8(StoreHookType.BEFORE_SET_RECORD)), false); - assertEq(storeHook.isEnabled(uint8(StoreHookType.AFTER_SET_RECORD)), false); - assertEq(storeHook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD)), true); - assertEq(storeHook.isEnabled(uint8(StoreHookType.AFTER_SET_FIELD)), false); - assertEq(storeHook.isEnabled(uint8(StoreHookType.BEFORE_DELETE_RECORD)), false); - assertEq(storeHook.isEnabled(uint8(StoreHookType.AFTER_DELETE_RECORD)), false); + assertFalse(storeHook.isEnabled(BEFORE_SET_RECORD), "BEFORE_SET_RECORD"); + assertFalse(storeHook.isEnabled(AFTER_SET_RECORD), "AFTER_SET_RECORD"); + assertTrue(storeHook.isEnabled(BEFORE_SET_FIELD), "BEFORE_SET_FIELD"); + assertFalse(storeHook.isEnabled(AFTER_SET_FIELD), "AFTER_SET_FIELD"); + assertFalse(storeHook.isEnabled(BEFORE_DELETE_RECORD), "BEFORE_DELETE_RECORD"); + assertTrue(storeHook.isEnabled(AFTER_DELETE_RECORD), "AFTER_DELETE_RECORD"); } function testFuzzIsEnabled( @@ -210,38 +111,26 @@ contract StoreHookTest is Test, GasReporter { bool enableBeforeDeleteRecord, bool enableAfterDeleteRecord ) public { - Hook storeHook = StoreHookLib.encode( - IStoreHook(hookAddress), - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: enableBeforeSetRecord, - onAfterSetRecord: enableAfterSetRecord, - onBeforeSetField: enableBeforeSetField, - onAfterSetField: enableAfterSetField, - onBeforeDeleteRecord: enableBeforeDeleteRecord, - onAfterDeleteRecord: enableAfterDeleteRecord - }) - ); - - assertEq(storeHook.isEnabled(uint8(StoreHookType.BEFORE_SET_RECORD)), enableBeforeSetRecord); - assertEq(storeHook.isEnabled(uint8(StoreHookType.AFTER_SET_RECORD)), enableAfterSetRecord); - assertEq(storeHook.isEnabled(uint8(StoreHookType.BEFORE_SET_FIELD)), enableBeforeSetField); - assertEq(storeHook.isEnabled(uint8(StoreHookType.AFTER_SET_FIELD)), enableAfterSetField); - assertEq(storeHook.isEnabled(uint8(StoreHookType.BEFORE_DELETE_RECORD)), enableBeforeDeleteRecord); - assertEq(storeHook.isEnabled(uint8(StoreHookType.AFTER_DELETE_RECORD)), enableAfterDeleteRecord); + uint8 enabledHooks = 0; + if (enableBeforeSetRecord) enabledHooks |= BEFORE_SET_RECORD; + if (enableAfterSetRecord) enabledHooks |= AFTER_SET_RECORD; + if (enableBeforeSetField) enabledHooks |= BEFORE_SET_FIELD; + if (enableAfterSetField) enabledHooks |= AFTER_SET_FIELD; + if (enableBeforeDeleteRecord) enabledHooks |= BEFORE_DELETE_RECORD; + if (enableAfterDeleteRecord) enabledHooks |= AFTER_DELETE_RECORD; + + Hook storeHook = HookLib.encode(hookAddress, enabledHooks); + + assertEq(storeHook.isEnabled(BEFORE_SET_RECORD), enableBeforeSetRecord); + assertEq(storeHook.isEnabled(AFTER_SET_RECORD), enableAfterSetRecord); + assertEq(storeHook.isEnabled(BEFORE_SET_FIELD), enableBeforeSetField); + assertEq(storeHook.isEnabled(AFTER_SET_FIELD), enableAfterSetField); + assertEq(storeHook.isEnabled(BEFORE_DELETE_RECORD), enableBeforeDeleteRecord); + assertEq(storeHook.isEnabled(AFTER_DELETE_RECORD), enableAfterDeleteRecord); } function testGetAddress() public { - Hook storeHook = StoreHookLib.encode( - echoSubscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: false, - onAfterSetRecord: false, - onBeforeSetField: true, - onAfterSetField: false, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: false - }) - ); + Hook storeHook = HookLib.encode(address(echoSubscriber), BEFORE_SET_FIELD); startGasReport("get store hook address"); storeHook.getAddress(); @@ -250,37 +139,8 @@ contract StoreHookTest is Test, GasReporter { assertEq(storeHook.getAddress(), address(echoSubscriber)); } - function testGetBitmap() public { - uint8 encodedBitmap = StoreHookLib.encodeBitmap({ - onBeforeSetRecord: false, - onAfterSetRecord: false, - onBeforeSetField: true, - onAfterSetField: false, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: false - }); - - Hook storeHook = StoreHookLib.encode(echoSubscriber, encodedBitmap); - - startGasReport("get store hook bitmap"); - storeHook.getBitmap(); - endGasReport(); - - assertEq(storeHook.getBitmap(), encodedBitmap); - } - function testCallHook() public { - Hook storeHook = StoreHookLib.encode( - echoSubscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: false, - onBeforeSetField: false, - onAfterSetField: false, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: false - }) - ); + Hook storeHook = HookLib.encode(address(echoSubscriber), BEFORE_SET_RECORD); // TODO temporary variable until https://github.com/foundry-rs/foundry/issues/5811 is fixed bytes memory emptyDynamicData = new bytes(0); @@ -288,7 +148,7 @@ contract StoreHookTest is Test, GasReporter { vm.expectEmit(true, true, true, true); emit HookCalled(abi.encode(tableId, key, staticData, encodedLengths, emptyDynamicData, fieldLayout)); startGasReport("call an enabled hook"); - if (storeHook.isEnabled(uint8(StoreHookType.BEFORE_SET_RECORD))) { + if (storeHook.isEnabled(BEFORE_SET_RECORD)) { IStoreHook(storeHook.getAddress()).onBeforeSetRecord( tableId, key, @@ -300,21 +160,11 @@ contract StoreHookTest is Test, GasReporter { } endGasReport(); - Hook revertHook = StoreHookLib.encode( - revertSubscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: false, - onAfterSetRecord: false, - onBeforeSetField: false, - onAfterSetField: false, - onBeforeDeleteRecord: false, - onAfterDeleteRecord: false - }) - ); + Hook revertHook = HookLib.encode(address(revertSubscriber), 0); // Expect the to not be called - otherwise the test will fail with a revert startGasReport("call a disabled hook"); - if (revertHook.isEnabled(uint8(StoreHookType.BEFORE_SET_RECORD))) { + if (revertHook.isEnabled(BEFORE_SET_RECORD)) { IStoreHook(revertHook.getAddress()).onBeforeSetRecord( tableId, key, diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index cb6c335b40..24a569c163 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": 1415308 + "gasUsed": 1415019 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1415308 + "gasUsed": 1415019 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 158915 + "gasUsed": 158881 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1415308 + "gasUsed": 1415019 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1415308 + "gasUsed": 1415019 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 21994 + "gasUsed": 21960 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 171498 + "gasUsed": 171464 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1415308 + "gasUsed": 1415019 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 20716 + "gasUsed": 20682 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 88149 + "gasUsed": 88115 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 654598 + "gasUsed": 654303 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,49 +117,49 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 654598 + "gasUsed": 654303 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 134451 + "gasUsed": 134417 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 654598 + "gasUsed": 654303 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 104026 + "gasUsed": 103992 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 32905 + "gasUsed": 32871 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 654598 + "gasUsed": 654303 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 139065 + "gasUsed": 139031 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 103824 + "gasUsed": 103790 }, { "file": "test/query.t.sol", diff --git a/packages/world/src/SystemCall.sol b/packages/world/src/SystemCall.sol index f2863b00c4..e6ec08e28f 100644 --- a/packages/world/src/SystemCall.sol +++ b/packages/world/src/SystemCall.sol @@ -10,7 +10,7 @@ import { ResourceSelector } from "./ResourceSelector.sol"; import { ROOT_NAMESPACE } from "./constants.sol"; import { WorldContextProvider } from "./WorldContext.sol"; import { revertWithBytes } from "./revertWithBytes.sol"; -import { SystemHookType } from "./SystemHook.sol"; +import { BEFORE_CALL_SYSTEM, AFTER_CALL_SYSTEM } from "./systemHookTypes.sol"; import { IWorldErrors } from "./interfaces/IWorldErrors.sol"; import { ISystemHook } from "./interfaces/ISystemHook.sol"; @@ -81,7 +81,7 @@ library SystemCall { // Call onBeforeCallSystem hooks (before calling the system) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(SystemHookType.BEFORE_CALL_SYSTEM))) { + if (hook.isEnabled(BEFORE_CALL_SYSTEM)) { ISystemHook(hook.getAddress()).onBeforeCallSystem(caller, resourceSelector, funcSelectorAndArgs); } } @@ -97,7 +97,7 @@ library SystemCall { // Call onAfterCallSystem hooks (after calling the system) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(uint8(SystemHookType.AFTER_CALL_SYSTEM))) { + if (hook.isEnabled(AFTER_CALL_SYSTEM)) { ISystemHook(hook.getAddress()).onAfterCallSystem(caller, resourceSelector, funcSelectorAndArgs); } } diff --git a/packages/world/src/SystemHook.sol b/packages/world/src/SystemHook.sol index f663b9b8f7..ef8af9587c 100644 --- a/packages/world/src/SystemHook.sol +++ b/packages/world/src/SystemHook.sol @@ -1,34 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import { Hook, HookLib } from "@latticexyz/store/src/Hook.sol"; import { ISystemHook, SYSTEM_HOOK_INTERFACE_ID } from "./interfaces/ISystemHook.sol"; import { ERC165_INTERFACE_ID } from "./interfaces/IERC165.sol"; -enum SystemHookType { - BEFORE_CALL_SYSTEM, - AFTER_CALL_SYSTEM -} - -library SystemHookLib { - /** - * Encode the bitmap into a single byte - */ - function encodeBitmap(bool onBeforeCallSystem, bool onAfterCallSystem) internal pure returns (uint8) { - uint256 bitmap = 0; - if (onBeforeCallSystem) bitmap |= 1 << uint8(SystemHookType.BEFORE_CALL_SYSTEM); - if (onAfterCallSystem) bitmap |= 1 << uint8(SystemHookType.AFTER_CALL_SYSTEM); - return uint8(bitmap); - } - - /** - * Encode enabled hooks into a bitmap with 1 bit per hook, and pack the bitmap with the system hook address into a bytes21 value - */ - function encode(ISystemHook systemHook, uint8 enabledHooksBitmap) internal pure returns (Hook) { - return HookLib.encode(address(systemHook), enabledHooksBitmap); - } -} - abstract contract SystemHook is ISystemHook { // ERC-165 supportsInterface (see https://eips.ethereum.org/EIPS/eip-165) function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { diff --git a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol index 3502e5bd6c..03cd41a7ec 100644 --- a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol @@ -8,7 +8,6 @@ import { WorldContextConsumer, WORLD_CONTEXT_CONSUMER_INTERFACE_ID } from "../.. import { ResourceSelector } from "../../../ResourceSelector.sol"; import { Resource } from "../../../Types.sol"; import { SystemCall } from "../../../SystemCall.sol"; -import { SystemHookLib } from "../../../SystemHook.sol"; import { ROOT_NAMESPACE, ROOT_NAME, UNLIMITED_DELEGATION } from "../../../constants.sol"; import { AccessControl } from "../../../AccessControl.sol"; import { requireInterface } from "../../../requireInterface.sol"; @@ -66,7 +65,7 @@ contract WorldRegistrationSystem is System, IWorldErrors { AccessControl.requireOwner(resourceSelector, _msgSender()); // Register the hook - SystemHooks.push(resourceSelector, Hook.unwrap(SystemHookLib.encode(hookAddress, enabledHooksBitmap))); + SystemHooks.push(resourceSelector, Hook.unwrap(HookLib.encode(address(hookAddress), enabledHooksBitmap))); } /** diff --git a/packages/world/src/modules/keysintable/KeysInTableModule.sol b/packages/world/src/modules/keysintable/KeysInTableModule.sol index f04834d110..b5c64cb8af 100644 --- a/packages/world/src/modules/keysintable/KeysInTableModule.sol +++ b/packages/world/src/modules/keysintable/KeysInTableModule.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import { StoreHookLib } from "@latticexyz/store/src/StoreHook.sol"; +import { BEFORE_SET_RECORD, AFTER_SET_FIELD, BEFORE_DELETE_RECORD } from "@latticexyz/store/src/storeHookTypes.sol"; import { ResourceType } from "../core/tables/ResourceType.sol"; import { Resource } from "../../Types.sol"; @@ -95,18 +95,7 @@ contract KeysInTableModule is Module { (success, returnData) = address(world).delegatecall( abi.encodeCall( world.registerStoreHook, - ( - sourceTableId, - hook, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: false, - onBeforeSetField: false, - onAfterSetField: true, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: false - }) - ) + (sourceTableId, hook, BEFORE_SET_RECORD | AFTER_SET_FIELD | BEFORE_DELETE_RECORD) ) ); } diff --git a/packages/world/src/modules/keyswithvalue/KeysWithValueModule.sol b/packages/world/src/modules/keyswithvalue/KeysWithValueModule.sol index a2b3c6a388..453450cfaf 100644 --- a/packages/world/src/modules/keyswithvalue/KeysWithValueModule.sol +++ b/packages/world/src/modules/keyswithvalue/KeysWithValueModule.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; -import { StoreHookLib } from "@latticexyz/store/src/StoreHook.sol"; +import { BEFORE_SET_RECORD, BEFORE_SET_FIELD, AFTER_SET_FIELD, BEFORE_DELETE_RECORD } from "@latticexyz/store/src/storeHookTypes.sol"; import { Module } from "../../Module.sol"; import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; @@ -55,18 +55,7 @@ contract KeysWithValueModule is Module { (bool success, bytes memory returnData) = address(world).delegatecall( abi.encodeCall( world.registerStoreHook, - ( - sourceTableId, - hook, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: false, - onBeforeSetField: true, - onAfterSetField: true, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: false - }) - ) + (sourceTableId, hook, BEFORE_SET_RECORD | BEFORE_SET_FIELD | AFTER_SET_FIELD | BEFORE_DELETE_RECORD) ) ); if (!success) revertWithBytes(returnData); diff --git a/packages/world/src/systemHookTypes.sol b/packages/world/src/systemHookTypes.sol new file mode 100644 index 0000000000..0f578dfed5 --- /dev/null +++ b/packages/world/src/systemHookTypes.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +uint8 constant BEFORE_CALL_SYSTEM = 1 << 0; +uint8 constant AFTER_CALL_SYSTEM = 1 << 1; diff --git a/packages/world/test/SystemHook.t.sol b/packages/world/test/SystemHook.t.sol index b1d423be0f..bcc9f66784 100644 --- a/packages/world/test/SystemHook.t.sol +++ b/packages/world/test/SystemHook.t.sol @@ -4,60 +4,31 @@ pragma solidity >=0.8.0; import "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; -import { Hook } from "@latticexyz/store/src/Hook.sol"; -import { SystemHookType } from "../src/SystemHook.sol"; -import { SystemHookLib } from "../src/SystemHook.sol"; +import { Hook, HookLib } from "@latticexyz/store/src/Hook.sol"; +import { BEFORE_CALL_SYSTEM, AFTER_CALL_SYSTEM } from "../src/systemHookTypes.sol"; import { ISystemHook } from "../src/interfaces/ISystemHook.sol"; contract SystemHookTest is Test, GasReporter { - function testEncodeBitmap() public { - assertEq( - SystemHookLib.encodeBitmap({ onBeforeCallSystem: false, onAfterCallSystem: false }), - uint8(0x00), - "0b00000000" - ); - - assertEq( - SystemHookLib.encodeBitmap({ onBeforeCallSystem: true, onAfterCallSystem: false }), - uint8(0x01), - "0b00000001" - ); - - assertEq( - SystemHookLib.encodeBitmap({ onBeforeCallSystem: false, onAfterCallSystem: true }), - uint8(0x02), - "0b00000010" - ); - - assertEq( - SystemHookLib.encodeBitmap({ onBeforeCallSystem: true, onAfterCallSystem: true }), - uint8(0x03), - "0b00000011" - ); - } - function testFuzzEncode(address hookAddress, bool enableBeforeCallSystem, bool enableAfterCallSystem) public { - uint8 enabledHooksBitmap = SystemHookLib.encodeBitmap({ - onBeforeCallSystem: enableBeforeCallSystem, - onAfterCallSystem: enableAfterCallSystem - }); + uint8 enabledHooksBitmap = 0; + if (enableBeforeCallSystem) enabledHooksBitmap |= BEFORE_CALL_SYSTEM; + if (enableAfterCallSystem) enabledHooksBitmap |= AFTER_CALL_SYSTEM; assertEq( - Hook.unwrap(SystemHookLib.encode(ISystemHook(hookAddress), enabledHooksBitmap)), + Hook.unwrap(HookLib.encode(hookAddress, enabledHooksBitmap)), bytes21(abi.encodePacked(hookAddress, enabledHooksBitmap)) ); } function testFuzzIsEnabled(address hookAddress, bool enableBeforeCallSystem, bool enableAfterCallSystem) public { - uint8 enabledHooksBitmap = SystemHookLib.encodeBitmap({ - onBeforeCallSystem: enableBeforeCallSystem, - onAfterCallSystem: enableAfterCallSystem - }); + uint8 enabledHooksBitmap = 0; + if (enableBeforeCallSystem) enabledHooksBitmap |= BEFORE_CALL_SYSTEM; + if (enableAfterCallSystem) enabledHooksBitmap |= AFTER_CALL_SYSTEM; - Hook systemHook = SystemHookLib.encode(ISystemHook(hookAddress), enabledHooksBitmap); + Hook systemHook = HookLib.encode(hookAddress, enabledHooksBitmap); - assertEq(systemHook.isEnabled(uint8(SystemHookType.BEFORE_CALL_SYSTEM)), enableBeforeCallSystem); - assertEq(systemHook.isEnabled(uint8(SystemHookType.AFTER_CALL_SYSTEM)), enableAfterCallSystem); + assertEq(systemHook.isEnabled(BEFORE_CALL_SYSTEM), enableBeforeCallSystem); + assertEq(systemHook.isEnabled(AFTER_CALL_SYSTEM), enableAfterCallSystem); } function testFuzzGetAddressAndBitmap( @@ -65,12 +36,11 @@ contract SystemHookTest is Test, GasReporter { bool enableBeforeCallSystem, bool enableAfterCallSystem ) public { - uint8 enabledHooksBitmap = SystemHookLib.encodeBitmap({ - onBeforeCallSystem: enableBeforeCallSystem, - onAfterCallSystem: enableAfterCallSystem - }); + uint8 enabledHooksBitmap = 0; + if (enableBeforeCallSystem) enabledHooksBitmap |= BEFORE_CALL_SYSTEM; + if (enableAfterCallSystem) enabledHooksBitmap |= AFTER_CALL_SYSTEM; - Hook systemHook = SystemHookLib.encode(ISystemHook(hookAddress), enabledHooksBitmap); + Hook systemHook = HookLib.encode(hookAddress, enabledHooksBitmap); assertEq(systemHook.getAddress(), hookAddress); assertEq(systemHook.getBitmap(), enabledHooksBitmap); diff --git a/packages/world/test/World.t.sol b/packages/world/test/World.t.sol index 6a3406fe63..e1129733e0 100644 --- a/packages/world/test/World.t.sol +++ b/packages/world/test/World.t.sol @@ -16,7 +16,7 @@ import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { SchemaEncodeHelper } from "@latticexyz/store/test/SchemaEncodeHelper.sol"; import { Tables, TablesTableId } from "@latticexyz/store/src/codegen/Tables.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; -import { StoreHookLib } from "@latticexyz/store/src/StoreHook.sol"; +import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SET_FIELD, AFTER_SET_FIELD, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "@latticexyz/store/src/storeHookTypes.sol"; import { RevertSubscriber } from "@latticexyz/store/test/RevertSubscriber.sol"; import { EchoSubscriber } from "@latticexyz/store/test/EchoSubscriber.sol"; @@ -27,7 +27,8 @@ import { ResourceSelector } from "../src/ResourceSelector.sol"; import { ROOT_NAMESPACE, ROOT_NAME, UNLIMITED_DELEGATION } from "../src/constants.sol"; import { Resource } from "../src/Types.sol"; import { WorldContextProvider, WORLD_CONTEXT_CONSUMER_INTERFACE_ID } from "../src/WorldContext.sol"; -import { SystemHookLib, SystemHook } from "../src/SystemHook.sol"; +import { SystemHook } from "../src/SystemHook.sol"; +import { BEFORE_CALL_SYSTEM, AFTER_CALL_SYSTEM } from "../src/systemHookTypes.sol"; import { Module, MODULE_INTERFACE_ID } from "../src/Module.sol"; import { NamespaceOwner, NamespaceOwnerTableId } from "../src/tables/NamespaceOwner.sol"; @@ -842,14 +843,12 @@ contract WorldTest is Test, GasReporter { world.registerStoreHook( tableId, tableHook, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: true, - onBeforeSetField: true, - onAfterSetField: true, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: true - }) + BEFORE_SET_RECORD | + AFTER_SET_RECORD | + BEFORE_SET_FIELD | + AFTER_SET_FIELD | + BEFORE_DELETE_RECORD | + AFTER_DELETE_RECORD ); // Prepare data to write to the table @@ -893,14 +892,12 @@ contract WorldTest is Test, GasReporter { world.registerStoreHook( tableId, IStoreHook(address(world)), // the World contract does not implement the store hook interface - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: true, - onBeforeSetField: true, - onAfterSetField: true, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: true - }) + BEFORE_SET_RECORD | + AFTER_SET_RECORD | + BEFORE_SET_FIELD | + AFTER_SET_FIELD | + BEFORE_DELETE_RECORD | + AFTER_DELETE_RECORD ); } @@ -917,28 +914,24 @@ contract WorldTest is Test, GasReporter { world.registerStoreHook( tableId, revertSubscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: true, - onBeforeSetField: true, - onAfterSetField: true, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: true - }) + BEFORE_SET_RECORD | + AFTER_SET_RECORD | + BEFORE_SET_FIELD | + AFTER_SET_FIELD | + BEFORE_DELETE_RECORD | + AFTER_DELETE_RECORD ); // Register a new EchoSubscriber IStoreHook echoSubscriber = new EchoSubscriber(); world.registerStoreHook( tableId, echoSubscriber, - StoreHookLib.encodeBitmap({ - onBeforeSetRecord: true, - onAfterSetRecord: true, - onBeforeSetField: true, - onAfterSetField: true, - onBeforeDeleteRecord: true, - onAfterDeleteRecord: true - }) + BEFORE_SET_RECORD | + AFTER_SET_RECORD | + BEFORE_SET_FIELD | + AFTER_SET_FIELD | + BEFORE_DELETE_RECORD | + AFTER_DELETE_RECORD ); // Prepare data to write to the table @@ -1005,16 +998,12 @@ contract WorldTest is Test, GasReporter { world.registerSystemHook( systemId, ISystemHook(address(world)), // the World contract does not implement the system hook interface - SystemHookLib.encodeBitmap({ onBeforeCallSystem: true, onAfterCallSystem: true }) + BEFORE_CALL_SYSTEM | AFTER_CALL_SYSTEM ); // Register a new hook ISystemHook systemHook = new EchoSystemHook(); - world.registerSystemHook( - systemId, - systemHook, - SystemHookLib.encodeBitmap({ onBeforeCallSystem: true, onAfterCallSystem: true }) - ); + world.registerSystemHook(systemId, systemHook, BEFORE_CALL_SYSTEM | AFTER_CALL_SYSTEM); bytes memory funcSelectorAndArgs = abi.encodeWithSelector(bytes4(keccak256("fallbackselector"))); @@ -1041,19 +1030,11 @@ contract WorldTest is Test, GasReporter { // Register a new RevertSystemHook ISystemHook revertSystemHook = new RevertSystemHook(); - world.registerSystemHook( - systemId, - revertSystemHook, - SystemHookLib.encodeBitmap({ onBeforeCallSystem: true, onAfterCallSystem: true }) - ); + world.registerSystemHook(systemId, revertSystemHook, BEFORE_CALL_SYSTEM | AFTER_CALL_SYSTEM); // Register a new EchoSystemHook ISystemHook echoSystemHook = new EchoSystemHook(); - world.registerSystemHook( - systemId, - echoSystemHook, - SystemHookLib.encodeBitmap({ onBeforeCallSystem: true, onAfterCallSystem: true }) - ); + world.registerSystemHook(systemId, echoSystemHook, BEFORE_CALL_SYSTEM | AFTER_CALL_SYSTEM); bytes memory funcSelectorAndArgs = abi.encodeWithSelector(bytes4(keccak256("fallbackselector"))); From 498d05e3604cd422064e5548dc53bec327e936ee Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Sun, 17 Sep 2023 15:00:10 +0100 Subject: [PATCH 14/17] feat(store-indexer): run indexers with npx (#1526) --- .changeset/proud-insects-perform.md | 25 +++++++ .../store-indexer/bin/postgres-indexer.ts | 70 ++++++++----------- packages/store-indexer/bin/sqlite-indexer.ts | 66 ++++++++--------- packages/store-indexer/package.json | 5 ++ packages/store-indexer/tsup.config.ts | 2 +- pnpm-lock.yaml | 3 + 6 files changed, 92 insertions(+), 79 deletions(-) create mode 100644 .changeset/proud-insects-perform.md diff --git a/.changeset/proud-insects-perform.md b/.changeset/proud-insects-perform.md new file mode 100644 index 0000000000..69d515d7ed --- /dev/null +++ b/.changeset/proud-insects-perform.md @@ -0,0 +1,25 @@ +--- +"@latticexyz/store-indexer": minor +--- + +You can now install and run `@latticexyz/store-indexer` from the npm package itself, without having to clone/build the MUD repo: + +```sh +npm install @latticexyz/store-indexer + +npm sqlite-indexer +# or +npm postgres-indexer +``` + +or + +```sh +npx -p @latticexyz/store-indexer sqlite-indexer +# or +npx -p @latticexyz/store-indexer postgres-indexer +``` + +The binary will also load the nearby `.env` file for easier local configuration. + +We've removed the `CHAIN_ID` requirement and instead require just a `RPC_HTTP_URL` or `RPC_WS_URL` or both. You can now also adjust the polling interval with `POLLING_INTERVAL` (defaults to 1000ms, which corresponds to MUD's default block time). diff --git a/packages/store-indexer/bin/postgres-indexer.ts b/packages/store-indexer/bin/postgres-indexer.ts index 64cc564f24..b2b7068276 100644 --- a/packages/store-indexer/bin/postgres-indexer.ts +++ b/packages/store-indexer/bin/postgres-indexer.ts @@ -1,3 +1,5 @@ +#!/usr/bin/env node +import "dotenv/config"; import { z } from "zod"; import { DefaultLogger, eq } from "drizzle-orm"; import { createPublicClient, fallback, webSocket, http, Transport } from "viem"; @@ -5,70 +7,58 @@ import fastify from "fastify"; import { fastifyTRPCPlugin } from "@trpc/server/adapters/fastify"; import { AppRouter, createAppRouter } from "@latticexyz/store-sync/trpc-indexer"; import { createQueryAdapter } from "../src/postgres/createQueryAdapter"; -import type { Chain } from "viem/chains"; -import * as mudChains from "@latticexyz/common/chains"; -import * as chains from "viem/chains"; -import { isNotNull } from "@latticexyz/common/utils"; +import { isDefined } from "@latticexyz/common/utils"; import { combineLatest, filter, first } from "rxjs"; import { drizzle } from "drizzle-orm/postgres-js"; import postgres from "postgres"; import { cleanDatabase, postgresStorage, schemaVersion } from "@latticexyz/store-sync/postgres"; import { createStoreSync } from "@latticexyz/store-sync"; -const possibleChains = Object.values({ ...mudChains, ...chains }) as Chain[]; - -// TODO: refine zod type to be either CHAIN_ID or RPC_HTTP_URL/RPC_WS_URL const env = z - .object({ - CHAIN_ID: z.coerce.number().positive().optional(), - RPC_HTTP_URL: z.string().optional(), - RPC_WS_URL: z.string().optional(), - START_BLOCK: z.coerce.bigint().nonnegative().default(0n), - MAX_BLOCK_RANGE: z.coerce.bigint().positive().default(1000n), - HOST: z.string().default("0.0.0.0"), - PORT: z.coerce.number().positive().default(3001), - DATABASE_URL: z.string(), - }) + .intersection( + z.object({ + HOST: z.string().default("0.0.0.0"), + PORT: z.coerce.number().positive().default(3001), + DATABASE_URL: z.string(), + START_BLOCK: z.coerce.bigint().nonnegative().default(0n), + MAX_BLOCK_RANGE: z.coerce.bigint().positive().default(1000n), + POLLING_INTERVAL: z.coerce.number().positive().default(1000), + }), + z + .object({ + RPC_HTTP_URL: z.string(), + RPC_WS_URL: z.string(), + }) + .partial() + .refine((values) => Object.values(values).some(isDefined)) + ) .parse(process.env, { errorMap: (issue) => ({ message: `Missing or invalid environment variable: ${issue.path.join(".")}`, }), }); -const chain = env.CHAIN_ID != null ? possibleChains.find((c) => c.id === env.CHAIN_ID) : undefined; -if (env.CHAIN_ID != null && !chain) { - console.warn(`No chain found for chain ID ${env.CHAIN_ID}`); -} - const transports: Transport[] = [ - env.RPC_WS_URL ? webSocket(env.RPC_WS_URL) : null, - env.RPC_HTTP_URL ? http(env.RPC_HTTP_URL) : null, -].filter(isNotNull); + // prefer WS when specified + env.RPC_WS_URL ? webSocket(env.RPC_WS_URL) : undefined, + // otherwise use or fallback to HTTP + env.RPC_HTTP_URL ? http(env.RPC_HTTP_URL) : undefined, +].filter(isDefined); const publicClient = createPublicClient({ - chain, - transport: fallback( - // If one or more RPC URLs are provided, we'll configure the transport with only those RPC URLs - transports.length > 0 - ? transports - : // Otherwise use the chain defaults - [webSocket(), http()] - ), - pollingInterval: 1000, + transport: fallback(transports), + pollingInterval: env.POLLING_INTERVAL, }); -// Fetch the chain ID from the RPC if no chain object was found for the provided chain ID. -// We do this to match the downstream logic, which also attempts to find the chain ID. -const chainId = chain?.id ?? (await publicClient.getChainId()); - +const chainId = await publicClient.getChainId(); const database = drizzle(postgres(env.DATABASE_URL), { logger: new DefaultLogger(), }); -let startBlock = env.START_BLOCK; - const { storageAdapter, internalTables } = await postgresStorage({ database, publicClient }); +let startBlock = env.START_BLOCK; + // Resume from latest block stored in DB. This will throw if the DB doesn't exist yet, so we wrap in a try/catch and ignore the error. try { const currentChainStates = await database diff --git a/packages/store-indexer/bin/sqlite-indexer.ts b/packages/store-indexer/bin/sqlite-indexer.ts index 7cdaa50c87..483dc9a823 100644 --- a/packages/store-indexer/bin/sqlite-indexer.ts +++ b/packages/store-indexer/bin/sqlite-indexer.ts @@ -1,3 +1,5 @@ +#!/usr/bin/env node +import "dotenv/config"; import fs from "node:fs"; import { z } from "zod"; import { eq } from "drizzle-orm"; @@ -9,58 +11,46 @@ import { fastifyTRPCPlugin } from "@trpc/server/adapters/fastify"; import { AppRouter, createAppRouter } from "@latticexyz/store-sync/trpc-indexer"; import { chainState, schemaVersion, syncToSqlite } from "@latticexyz/store-sync/sqlite"; import { createQueryAdapter } from "../src/sqlite/createQueryAdapter"; -import type { Chain } from "viem/chains"; -import * as mudChains from "@latticexyz/common/chains"; -import * as chains from "viem/chains"; -import { isNotNull } from "@latticexyz/common/utils"; +import { isDefined } from "@latticexyz/common/utils"; import { combineLatest, filter, first } from "rxjs"; -const possibleChains = Object.values({ ...mudChains, ...chains }) as Chain[]; - -// TODO: refine zod type to be either CHAIN_ID or RPC_HTTP_URL/RPC_WS_URL const env = z - .object({ - CHAIN_ID: z.coerce.number().positive().optional(), - RPC_HTTP_URL: z.string().optional(), - RPC_WS_URL: z.string().optional(), - START_BLOCK: z.coerce.bigint().nonnegative().default(0n), - MAX_BLOCK_RANGE: z.coerce.bigint().positive().default(1000n), - HOST: z.string().default("0.0.0.0"), - PORT: z.coerce.number().positive().default(3001), - SQLITE_FILENAME: z.string().default("indexer.db"), - }) + .intersection( + z.object({ + HOST: z.string().default("0.0.0.0"), + PORT: z.coerce.number().positive().default(3001), + SQLITE_FILENAME: z.string().default("indexer.db"), + START_BLOCK: z.coerce.bigint().nonnegative().default(0n), + MAX_BLOCK_RANGE: z.coerce.bigint().positive().default(1000n), + POLLING_INTERVAL: z.coerce.number().positive().default(1000), + }), + z + .object({ + RPC_HTTP_URL: z.string(), + RPC_WS_URL: z.string(), + }) + .partial() + .refine((values) => Object.values(values).some(isDefined)) + ) .parse(process.env, { errorMap: (issue) => ({ message: `Missing or invalid environment variable: ${issue.path.join(".")}`, }), }); -const chain = env.CHAIN_ID != null ? possibleChains.find((c) => c.id === env.CHAIN_ID) : undefined; -if (env.CHAIN_ID != null && !chain) { - console.warn(`No chain found for chain ID ${env.CHAIN_ID}`); -} - const transports: Transport[] = [ - env.RPC_WS_URL ? webSocket(env.RPC_WS_URL) : null, - env.RPC_HTTP_URL ? http(env.RPC_HTTP_URL) : null, -].filter(isNotNull); + // prefer WS when specified + env.RPC_WS_URL ? webSocket(env.RPC_WS_URL) : undefined, + // otherwise use or fallback to HTTP + env.RPC_HTTP_URL ? http(env.RPC_HTTP_URL) : undefined, +].filter(isDefined); const publicClient = createPublicClient({ - chain, - transport: fallback( - // If one or more RPC URLs are provided, we'll configure the transport with only those RPC URLs - transports.length > 0 - ? transports - : // Otherwise use the chain defaults - [webSocket(), http()] - ), - pollingInterval: 1000, + transport: fallback(transports), + pollingInterval: env.POLLING_INTERVAL, }); -// Fetch the chain ID from the RPC if no chain object was found for the provided chain ID. -// We do this to match the downstream logic, which also attempts to find the chain ID. -const chainId = chain?.id ?? (await publicClient.getChainId()); - +const chainId = await publicClient.getChainId(); const database = drizzle(new Database(env.SQLITE_FILENAME)); let startBlock = env.START_BLOCK; diff --git a/packages/store-indexer/package.json b/packages/store-indexer/package.json index 175b8b7090..3a17b7b65b 100644 --- a/packages/store-indexer/package.json +++ b/packages/store-indexer/package.json @@ -13,6 +13,10 @@ ".": "./dist/index.js" }, "types": "src/index.ts", + "bin": { + "postgres-indexer": "./dist/bin/postgres-indexer.js", + "sqlite-indexer": "./dist/bin/sqlite-indexer.js" + }, "scripts": { "build": "pnpm run build:js", "build:js": "tsup", @@ -42,6 +46,7 @@ "@wagmi/chains": "^0.2.22", "better-sqlite3": "^8.6.0", "debug": "^4.3.4", + "dotenv": "^16.0.3", "drizzle-orm": "^0.28.5", "fastify": "^4.21.0", "postgres": "^3.3.5", diff --git a/packages/store-indexer/tsup.config.ts b/packages/store-indexer/tsup.config.ts index b755469f90..ab77d021ff 100644 --- a/packages/store-indexer/tsup.config.ts +++ b/packages/store-indexer/tsup.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from "tsup"; export default defineConfig({ - entry: ["src/index.ts"], + entry: ["src/index.ts", "bin/postgres-indexer.ts", "bin/sqlite-indexer.ts"], target: "esnext", format: ["esm"], dts: false, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b1dec75481..077747e8e9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -827,6 +827,9 @@ importers: debug: specifier: ^4.3.4 version: 4.3.4(supports-color@8.1.1) + dotenv: + specifier: ^16.0.3 + version: 16.0.3 drizzle-orm: specifier: ^0.28.5 version: 0.28.5(@types/better-sqlite3@7.6.4)(better-sqlite3@8.6.0)(postgres@3.3.5) From a0341daf9fd87e8072ffa292a33f508dd37b8ca6 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Sun, 17 Sep 2023 15:20:25 +0100 Subject: [PATCH 15/17] feat(world): rename `funcSelectorAndArgs` to `callData` (#1524) Co-authored-by: alvarius --- .changeset/lovely-fireants-behave.md | 5 ++ packages/world/mud.config.ts | 2 +- packages/world/src/Delegation.sol | 9 +--- packages/world/src/SystemCall.sol | 23 ++++----- packages/world/src/World.sol | 21 ++++----- packages/world/src/WorldContext.sol | 20 ++++---- .../src/interfaces/IDelegationControl.sol | 2 +- packages/world/src/interfaces/ISystemHook.sol | 4 +- .../world/src/interfaces/IWorldKernel.sol | 4 +- .../interfaces/IWorldRegistrationSystem.sol | 6 +-- .../world/src/modules/core/CoreModule.sol | 4 +- .../ModuleInstallationSystem.sol | 2 +- .../StoreRegistrationSystem.sol | 2 +- .../WorldRegistrationSystem.sol | 10 ++-- .../CallboundDelegationControl.sol | 21 ++++----- .../TimeboundDelegationControl.sol | 2 +- .../tables/CallboundDelegations.sol | 47 +++++++++---------- packages/world/test/World.t.sol | 28 +++++------ packages/world/test/WorldContext.t.sol | 10 ++-- 19 files changed, 98 insertions(+), 124 deletions(-) create mode 100644 .changeset/lovely-fireants-behave.md diff --git a/.changeset/lovely-fireants-behave.md b/.changeset/lovely-fireants-behave.md new file mode 100644 index 0000000000..6e6968e1ca --- /dev/null +++ b/.changeset/lovely-fireants-behave.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/world": patch +--- + +Renamed all `funcSelectorAndArgs` arguments to `callData` for clarity. diff --git a/packages/world/mud.config.ts b/packages/world/mud.config.ts index 97563a1cdf..1ad535703d 100644 --- a/packages/world/mud.config.ts +++ b/packages/world/mud.config.ts @@ -150,7 +150,7 @@ export default mudConfig({ delegator: "address", delegatee: "address", resourceSelector: "bytes32", - funcSelectorAndArgsHash: "bytes32", + callDataHash: "bytes32", }, valueSchema: { availableCalls: "uint256", diff --git a/packages/world/src/Delegation.sol b/packages/world/src/Delegation.sol index c4140ea0d7..8a4a0b9b8e 100644 --- a/packages/world/src/Delegation.sol +++ b/packages/world/src/Delegation.sol @@ -32,7 +32,7 @@ library DelegationInstance { address delegator, address delegatee, bytes32 systemId, - bytes memory funcSelectorAndArgs + bytes memory callData ) internal returns (bool) { // Early return if there is an unlimited delegation if (isUnlimited(self)) return true; @@ -44,12 +44,7 @@ library DelegationInstance { (bool success, bytes memory data) = SystemCall.call({ caller: delegatee, resourceSelector: Delegation.unwrap(self), - funcSelectorAndArgs: abi.encodeWithSelector( - IDelegationControl.verify.selector, - delegator, - systemId, - funcSelectorAndArgs - ), + callData: abi.encodeWithSelector(IDelegationControl.verify.selector, delegator, systemId, callData), value: 0 }); diff --git a/packages/world/src/SystemCall.sol b/packages/world/src/SystemCall.sol index e6ec08e28f..27241b9a6b 100644 --- a/packages/world/src/SystemCall.sol +++ b/packages/world/src/SystemCall.sol @@ -31,7 +31,7 @@ library SystemCall { address caller, uint256 value, bytes32 resourceSelector, - bytes memory funcSelectorAndArgs + bytes memory callData ) internal returns (bool success, bytes memory data) { // Load the system data (address systemAddress, bool publicAccess) = Systems._get(resourceSelector); @@ -55,13 +55,13 @@ library SystemCall { msgSender: caller, msgValue: value, target: systemAddress, - funcSelectorAndArgs: funcSelectorAndArgs + callData: callData }) : WorldContextProvider.callWithContext({ msgSender: caller, msgValue: value, target: systemAddress, - funcSelectorAndArgs: funcSelectorAndArgs + callData: callData }); } @@ -72,7 +72,7 @@ library SystemCall { function callWithHooks( address caller, bytes32 resourceSelector, - bytes memory funcSelectorAndArgs, + bytes memory callData, uint256 value ) internal returns (bool success, bytes memory data) { // Get system hooks @@ -82,23 +82,18 @@ library SystemCall { for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(BEFORE_CALL_SYSTEM)) { - ISystemHook(hook.getAddress()).onBeforeCallSystem(caller, resourceSelector, funcSelectorAndArgs); + ISystemHook(hook.getAddress()).onBeforeCallSystem(caller, resourceSelector, callData); } } // Call the system and forward any return data - (success, data) = call({ - caller: caller, - value: value, - resourceSelector: resourceSelector, - funcSelectorAndArgs: funcSelectorAndArgs - }); + (success, data) = call({ caller: caller, value: value, resourceSelector: resourceSelector, callData: callData }); // Call onAfterCallSystem hooks (after calling the system) for (uint256 i; i < hooks.length; i++) { Hook hook = Hook.wrap(hooks[i]); if (hook.isEnabled(AFTER_CALL_SYSTEM)) { - ISystemHook(hook.getAddress()).onAfterCallSystem(caller, resourceSelector, funcSelectorAndArgs); + ISystemHook(hook.getAddress()).onAfterCallSystem(caller, resourceSelector, callData); } } } @@ -110,14 +105,14 @@ library SystemCall { function callWithHooksOrRevert( address caller, bytes32 resourceSelector, - bytes memory funcSelectorAndArgs, + bytes memory callData, uint256 value ) internal returns (bytes memory data) { (bool success, bytes memory returnData) = callWithHooks({ caller: caller, value: value, resourceSelector: resourceSelector, - funcSelectorAndArgs: funcSelectorAndArgs + callData: callData }); if (!success) revertWithBytes(returnData); return returnData; diff --git a/packages/world/src/World.sol b/packages/world/src/World.sol index 88265fa063..7b61f52e0e 100644 --- a/packages/world/src/World.sol +++ b/packages/world/src/World.sol @@ -85,7 +85,7 @@ contract World is StoreRead, IStoreData, IWorldKernel { msgSender: msg.sender, msgValue: 0, target: address(module), - funcSelectorAndArgs: abi.encodeWithSelector(IModule.installRoot.selector, args) + callData: abi.encodeWithSelector(IModule.installRoot.selector, args) }); // Register the module in the InstalledModules table @@ -212,11 +212,8 @@ contract World is StoreRead, IStoreData, IWorldKernel { * Call the system at the given resourceSelector. * If the system is not public, the caller must have access to the namespace or name (encoded in the resourceSelector). */ - function call( - bytes32 resourceSelector, - bytes memory funcSelectorAndArgs - ) external payable virtual returns (bytes memory) { - return SystemCall.callWithHooksOrRevert(msg.sender, resourceSelector, funcSelectorAndArgs, msg.value); + function call(bytes32 resourceSelector, bytes memory callData) external payable virtual returns (bytes memory) { + return SystemCall.callWithHooksOrRevert(msg.sender, resourceSelector, callData, msg.value); } /** @@ -226,26 +223,26 @@ contract World is StoreRead, IStoreData, IWorldKernel { function callFrom( address delegator, bytes32 resourceSelector, - bytes memory funcSelectorAndArgs + bytes memory callData ) external payable virtual returns (bytes memory) { // If the delegator is the caller, call the system directly if (delegator == msg.sender) { - return SystemCall.callWithHooksOrRevert(msg.sender, resourceSelector, funcSelectorAndArgs, msg.value); + return SystemCall.callWithHooksOrRevert(msg.sender, resourceSelector, callData, msg.value); } // Check if there is an explicit authorization for this caller to perform actions on behalf of the delegator Delegation explicitDelegation = Delegation.wrap(Delegations._get({ delegator: delegator, delegatee: msg.sender })); - if (explicitDelegation.verify(delegator, msg.sender, resourceSelector, funcSelectorAndArgs)) { + if (explicitDelegation.verify(delegator, msg.sender, resourceSelector, callData)) { // forward the call as `delegator` - return SystemCall.callWithHooksOrRevert(delegator, resourceSelector, funcSelectorAndArgs, msg.value); + return SystemCall.callWithHooksOrRevert(delegator, resourceSelector, callData, msg.value); } // Check if the delegator has a fallback delegation control set Delegation fallbackDelegation = Delegation.wrap(Delegations._get({ delegator: delegator, delegatee: address(0) })); - if (fallbackDelegation.verify(delegator, msg.sender, resourceSelector, funcSelectorAndArgs)) { + if (fallbackDelegation.verify(delegator, msg.sender, resourceSelector, callData)) { // forward the call with `from` as `msgSender` - return SystemCall.callWithHooksOrRevert(delegator, resourceSelector, funcSelectorAndArgs, msg.value); + return SystemCall.callWithHooksOrRevert(delegator, resourceSelector, callData, msg.value); } revert DelegationNotFound(delegator, msg.sender); diff --git a/packages/world/src/WorldContext.sol b/packages/world/src/WorldContext.sol index 167bb88ee8..7c29e09f25 100644 --- a/packages/world/src/WorldContext.sol +++ b/packages/world/src/WorldContext.sol @@ -46,21 +46,21 @@ abstract contract WorldContextConsumer is IWorldContextConsumer { */ library WorldContextProvider { function appendContext( - bytes memory funcSelectorAndArgs, + bytes memory callData, address msgSender, uint256 msgValue ) internal pure returns (bytes memory) { - return abi.encodePacked(funcSelectorAndArgs, msgSender, msgValue); + return abi.encodePacked(callData, msgSender, msgValue); } function callWithContext( address msgSender, uint256 msgValue, address target, - bytes memory funcSelectorAndArgs + bytes memory callData ) internal returns (bool success, bytes memory data) { (success, data) = target.call{ value: 0 }( - appendContext({ funcSelectorAndArgs: funcSelectorAndArgs, msgSender: msgSender, msgValue: msgValue }) + appendContext({ callData: callData, msgSender: msgSender, msgValue: msgValue }) ); } @@ -68,10 +68,10 @@ library WorldContextProvider { address msgSender, uint256 msgValue, address target, - bytes memory funcSelectorAndArgs + bytes memory callData ) internal returns (bool success, bytes memory data) { (success, data) = target.delegatecall( - appendContext({ funcSelectorAndArgs: funcSelectorAndArgs, msgSender: msgSender, msgValue: msgValue }) + appendContext({ callData: callData, msgSender: msgSender, msgValue: msgValue }) ); } @@ -79,13 +79,13 @@ library WorldContextProvider { address msgSender, uint256 msgValue, address target, - bytes memory funcSelectorAndArgs + bytes memory callData ) internal returns (bytes memory data) { (bool success, bytes memory _data) = callWithContext({ msgSender: msgSender, msgValue: msgValue, target: target, - funcSelectorAndArgs: funcSelectorAndArgs + callData: callData }); if (!success) revertWithBytes(_data); return _data; @@ -95,13 +95,13 @@ library WorldContextProvider { address msgSender, uint256 msgValue, address target, - bytes memory funcSelectorAndArgs + bytes memory callData ) internal returns (bytes memory data) { (bool success, bytes memory _data) = delegatecallWithContext({ msgSender: msgSender, msgValue: msgValue, target: target, - funcSelectorAndArgs: funcSelectorAndArgs + callData: callData }); if (!success) revertWithBytes(_data); return _data; diff --git a/packages/world/src/interfaces/IDelegationControl.sol b/packages/world/src/interfaces/IDelegationControl.sol index 2da8324ec1..3f77f24632 100644 --- a/packages/world/src/interfaces/IDelegationControl.sol +++ b/packages/world/src/interfaces/IDelegationControl.sol @@ -8,5 +8,5 @@ bytes4 constant DELEGATION_CONTROL_INTERFACE_ID = IDelegationControl.verify.sele WORLD_CONTEXT_CONSUMER_INTERFACE_ID; interface IDelegationControl is IWorldContextConsumer { - function verify(address delegator, bytes32 systemId, bytes calldata funcSelectorAndArgs) external returns (bool); + function verify(address delegator, bytes32 systemId, bytes calldata callData) external returns (bool); } diff --git a/packages/world/src/interfaces/ISystemHook.sol b/packages/world/src/interfaces/ISystemHook.sol index cb1526bcf2..a09c15f796 100644 --- a/packages/world/src/interfaces/ISystemHook.sol +++ b/packages/world/src/interfaces/ISystemHook.sol @@ -9,7 +9,7 @@ bytes4 constant SYSTEM_HOOK_INTERFACE_ID = ISystemHook.onBeforeCallSystem.select ERC165_INTERFACE_ID; interface ISystemHook is IERC165 { - function onBeforeCallSystem(address msgSender, bytes32 resourceSelector, bytes memory funcSelectorAndArgs) external; + function onBeforeCallSystem(address msgSender, bytes32 resourceSelector, bytes memory callData) external; - function onAfterCallSystem(address msgSender, bytes32 resourceSelector, bytes memory funcSelectorAndArgs) external; + function onAfterCallSystem(address msgSender, bytes32 resourceSelector, bytes memory callData) external; } diff --git a/packages/world/src/interfaces/IWorldKernel.sol b/packages/world/src/interfaces/IWorldKernel.sol index d5b1c5cec4..72395d553d 100644 --- a/packages/world/src/interfaces/IWorldKernel.sol +++ b/packages/world/src/interfaces/IWorldKernel.sol @@ -18,7 +18,7 @@ interface IWorldCall { * Call the system at the given resourceSelector. * If the system is not public, the caller must have access to the namespace or name (encoded in the resourceSelector). */ - function call(bytes32 resourceSelector, bytes memory funcSelectorAndArgs) external payable returns (bytes memory); + function call(bytes32 resourceSelector, bytes memory callData) external payable returns (bytes memory); /** * Call the system at the given resourceSelector on behalf of the given delegator. @@ -27,7 +27,7 @@ interface IWorldCall { function callFrom( address delegator, bytes32 resourceSelector, - bytes memory funcSelectorAndArgs + bytes memory callData ) external payable returns (bytes memory); } diff --git a/packages/world/src/interfaces/IWorldRegistrationSystem.sol b/packages/world/src/interfaces/IWorldRegistrationSystem.sol index 8b319aef9a..eda464a074 100644 --- a/packages/world/src/interfaces/IWorldRegistrationSystem.sol +++ b/packages/world/src/interfaces/IWorldRegistrationSystem.sol @@ -27,9 +27,5 @@ interface IWorldRegistrationSystem { bytes4 systemFunctionSelector ) external returns (bytes4); - function registerDelegation( - address delegatee, - bytes32 delegationControlId, - bytes memory initFuncSelectorAndArgs - ) external; + function registerDelegation(address delegatee, bytes32 delegationControlId, bytes memory initCallData) external; } diff --git a/packages/world/src/modules/core/CoreModule.sol b/packages/world/src/modules/core/CoreModule.sol index a9712b4576..341e1aebeb 100644 --- a/packages/world/src/modules/core/CoreModule.sol +++ b/packages/world/src/modules/core/CoreModule.sol @@ -90,7 +90,7 @@ contract CoreModule is Module { msgSender: _msgSender(), msgValue: 0, target: coreSystem, - funcSelectorAndArgs: abi.encodeCall( + callData: abi.encodeCall( WorldRegistrationSystem.registerSystem, (ResourceSelector.from(ROOT_NAMESPACE, CORE_SYSTEM_NAME), CoreSystem(coreSystem), true) ) @@ -134,7 +134,7 @@ contract CoreModule is Module { msgSender: _msgSender(), msgValue: 0, target: coreSystem, - funcSelectorAndArgs: abi.encodeCall( + callData: abi.encodeCall( WorldRegistrationSystem.registerRootFunctionSelector, (ResourceSelector.from(ROOT_NAMESPACE, CORE_SYSTEM_NAME), functionSelectors[i], functionSelectors[i]) ) diff --git a/packages/world/src/modules/core/implementations/ModuleInstallationSystem.sol b/packages/world/src/modules/core/implementations/ModuleInstallationSystem.sol index 80a004975a..527cf62eba 100644 --- a/packages/world/src/modules/core/implementations/ModuleInstallationSystem.sol +++ b/packages/world/src/modules/core/implementations/ModuleInstallationSystem.sol @@ -24,7 +24,7 @@ contract ModuleInstallationSystem is System { msgSender: _msgSender(), msgValue: 0, target: address(module), - funcSelectorAndArgs: abi.encodeWithSelector(IModule.install.selector, args) + callData: abi.encodeWithSelector(IModule.install.selector, args) }); // Register the module in the InstalledModules table diff --git a/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol b/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol index eacfff6087..eee36e25fd 100644 --- a/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol @@ -57,7 +57,7 @@ contract StoreRegistrationSystem is System, IWorldErrors { msgSender: _msgSender(), msgValue: 0, target: systemAddress, - funcSelectorAndArgs: abi.encodeWithSelector(WorldRegistrationSystem.registerNamespace.selector, namespace) + callData: abi.encodeWithSelector(WorldRegistrationSystem.registerNamespace.selector, namespace) }); } else { // otherwise require caller to own the namespace diff --git a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol index 03cd41a7ec..a4d8ceea7b 100644 --- a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol @@ -202,16 +202,12 @@ contract WorldRegistrationSystem is System, IWorldErrors { /** * Register a delegation from the caller to the given delegatee. */ - function registerDelegation( - address delegatee, - bytes32 delegationControlId, - bytes memory initFuncSelectorAndArgs - ) public { + function registerDelegation(address delegatee, bytes32 delegationControlId, bytes memory initCallData) public { // Store the delegation control contract address Delegations.set({ delegator: _msgSender(), delegatee: delegatee, delegationControlId: delegationControlId }); // If the delegation is not unlimited... - if (delegationControlId != UNLIMITED_DELEGATION && initFuncSelectorAndArgs.length > 0) { + if (delegationControlId != UNLIMITED_DELEGATION && initCallData.length > 0) { // Require the delegationControl contract to implement the IDelegationControl interface (address delegationControl, ) = Systems._get(delegationControlId); requireInterface(delegationControl, DELEGATION_CONTROL_INTERFACE_ID); @@ -220,7 +216,7 @@ contract WorldRegistrationSystem is System, IWorldErrors { SystemCall.call({ caller: _msgSender(), resourceSelector: delegationControlId, - funcSelectorAndArgs: initFuncSelectorAndArgs, + callData: initCallData, value: 0 }); } diff --git a/packages/world/src/modules/std-delegations/CallboundDelegationControl.sol b/packages/world/src/modules/std-delegations/CallboundDelegationControl.sol index 66785b0bfa..fbb62081ee 100644 --- a/packages/world/src/modules/std-delegations/CallboundDelegationControl.sol +++ b/packages/world/src/modules/std-delegations/CallboundDelegationControl.sol @@ -8,15 +8,15 @@ contract CallboundDelegationControl is DelegationControl { /** * Verify a delegation by checking if the delegator has any available calls left in the CallboundDelegations table and decrementing the available calls if so. */ - function verify(address delegator, bytes32 resourceSelector, bytes memory funcSelectorAndArgs) public returns (bool) { - bytes32 funcSelectorAndArgsHash = keccak256(funcSelectorAndArgs); + function verify(address delegator, bytes32 resourceSelector, bytes memory callData) public returns (bool) { + bytes32 callDataHash = keccak256(callData); - // Get the number of available calls for the given delegator, resourceSelector and funcSelectorAndArgs + // Get the number of available calls for the given delegator, resourceSelector and callData uint256 availableCalls = CallboundDelegations.get({ delegator: delegator, delegatee: _msgSender(), resourceSelector: resourceSelector, - funcSelectorAndArgsHash: funcSelectorAndArgsHash + callDataHash: callDataHash }); if (availableCalls == 1) { @@ -25,7 +25,7 @@ contract CallboundDelegationControl is DelegationControl { delegator: delegator, delegatee: _msgSender(), resourceSelector: resourceSelector, - funcSelectorAndArgsHash: funcSelectorAndArgsHash + callDataHash: callDataHash }); return true; } @@ -39,7 +39,7 @@ contract CallboundDelegationControl is DelegationControl { delegator: delegator, delegatee: _msgSender(), resourceSelector: resourceSelector, - funcSelectorAndArgsHash: funcSelectorAndArgsHash, + callDataHash: callDataHash, availableCalls: availableCalls }); return true; @@ -51,17 +51,12 @@ contract CallboundDelegationControl is DelegationControl { /** * Initialize a delegation by setting the number of available calls in the CallboundDelegations table */ - function initDelegation( - address delegatee, - bytes32 resourceSelector, - bytes memory funcSelectorAndArgs, - uint256 numCalls - ) public { + function initDelegation(address delegatee, bytes32 resourceSelector, bytes memory callData, uint256 numCalls) public { CallboundDelegations.set({ delegator: _msgSender(), delegatee: delegatee, resourceSelector: resourceSelector, - funcSelectorAndArgsHash: keccak256(funcSelectorAndArgs), + callDataHash: keccak256(callData), availableCalls: numCalls }); } diff --git a/packages/world/src/modules/std-delegations/TimeboundDelegationControl.sol b/packages/world/src/modules/std-delegations/TimeboundDelegationControl.sol index ca792336bf..efeb00663e 100644 --- a/packages/world/src/modules/std-delegations/TimeboundDelegationControl.sol +++ b/packages/world/src/modules/std-delegations/TimeboundDelegationControl.sol @@ -7,7 +7,7 @@ import { TimeboundDelegations } from "./tables/TimeboundDelegations.sol"; contract TimeboundDelegationControl is DelegationControl { /** * Verify a delegation by checking if the current block timestamp is not larger than the max valid timestamp for the delegation. - * Note: the delegation control check ignores the resourceSelector and funcSelectorAndArgs parameters. + * Note: the delegation control check ignores the resourceSelector and callData parameters. */ function verify(address delegator, bytes32, bytes memory) public view returns (bool) { // Get the max valid timestamp for the given delegator diff --git a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol index f36c9e45b5..69367d5c30 100644 --- a/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol +++ b/packages/world/src/modules/std-delegations/tables/CallboundDelegations.sol @@ -56,7 +56,7 @@ library CallboundDelegations { keyNames[0] = "delegator"; keyNames[1] = "delegatee"; keyNames[2] = "resourceSelector"; - keyNames[3] = "funcSelectorAndArgsHash"; + keyNames[3] = "callDataHash"; } /** Get the table's field names */ @@ -85,13 +85,13 @@ library CallboundDelegations { address delegator, address delegatee, bytes32 resourceSelector, - bytes32 funcSelectorAndArgsHash + bytes32 callDataHash ) internal view returns (uint256 availableCalls) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); _keyTuple[2] = resourceSelector; - _keyTuple[3] = funcSelectorAndArgsHash; + _keyTuple[3] = callDataHash; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); @@ -102,13 +102,13 @@ library CallboundDelegations { address delegator, address delegatee, bytes32 resourceSelector, - bytes32 funcSelectorAndArgsHash + bytes32 callDataHash ) internal view returns (uint256 availableCalls) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); _keyTuple[2] = resourceSelector; - _keyTuple[3] = funcSelectorAndArgsHash; + _keyTuple[3] = callDataHash; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); @@ -120,13 +120,13 @@ library CallboundDelegations { address delegator, address delegatee, bytes32 resourceSelector, - bytes32 funcSelectorAndArgsHash + bytes32 callDataHash ) internal view returns (uint256 availableCalls) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); _keyTuple[2] = resourceSelector; - _keyTuple[3] = funcSelectorAndArgsHash; + _keyTuple[3] = callDataHash; bytes32 _blob = _store.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); @@ -137,14 +137,14 @@ library CallboundDelegations { address delegator, address delegatee, bytes32 resourceSelector, - bytes32 funcSelectorAndArgsHash, + bytes32 callDataHash, uint256 availableCalls ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); _keyTuple[2] = resourceSelector; - _keyTuple[3] = funcSelectorAndArgsHash; + _keyTuple[3] = callDataHash; StoreSwitch.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); } @@ -154,14 +154,14 @@ library CallboundDelegations { address delegator, address delegatee, bytes32 resourceSelector, - bytes32 funcSelectorAndArgsHash, + bytes32 callDataHash, uint256 availableCalls ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); _keyTuple[2] = resourceSelector; - _keyTuple[3] = funcSelectorAndArgsHash; + _keyTuple[3] = callDataHash; StoreCore.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); } @@ -172,14 +172,14 @@ library CallboundDelegations { address delegator, address delegatee, bytes32 resourceSelector, - bytes32 funcSelectorAndArgsHash, + bytes32 callDataHash, uint256 availableCalls ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); _keyTuple[2] = resourceSelector; - _keyTuple[3] = funcSelectorAndArgsHash; + _keyTuple[3] = callDataHash; _store.setField(_tableId, _keyTuple, 0, abi.encodePacked((availableCalls)), _fieldLayout); } @@ -204,29 +204,24 @@ library CallboundDelegations { address delegator, address delegatee, bytes32 resourceSelector, - bytes32 funcSelectorAndArgsHash + bytes32 callDataHash ) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); _keyTuple[2] = resourceSelector; - _keyTuple[3] = funcSelectorAndArgsHash; + _keyTuple[3] = callDataHash; return _keyTuple; } /* Delete all data for given keys */ - function deleteRecord( - address delegator, - address delegatee, - bytes32 resourceSelector, - bytes32 funcSelectorAndArgsHash - ) internal { + function deleteRecord(address delegator, address delegatee, bytes32 resourceSelector, bytes32 callDataHash) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); _keyTuple[2] = resourceSelector; - _keyTuple[3] = funcSelectorAndArgsHash; + _keyTuple[3] = callDataHash; StoreSwitch.deleteRecord(_tableId, _keyTuple, _fieldLayout); } @@ -236,13 +231,13 @@ library CallboundDelegations { address delegator, address delegatee, bytes32 resourceSelector, - bytes32 funcSelectorAndArgsHash + bytes32 callDataHash ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); _keyTuple[2] = resourceSelector; - _keyTuple[3] = funcSelectorAndArgsHash; + _keyTuple[3] = callDataHash; StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } @@ -253,13 +248,13 @@ library CallboundDelegations { address delegator, address delegatee, bytes32 resourceSelector, - bytes32 funcSelectorAndArgsHash + bytes32 callDataHash ) internal { bytes32[] memory _keyTuple = new bytes32[](4); _keyTuple[0] = bytes32(uint256(uint160(delegator))); _keyTuple[1] = bytes32(uint256(uint160(delegatee))); _keyTuple[2] = resourceSelector; - _keyTuple[3] = funcSelectorAndArgsHash; + _keyTuple[3] = callDataHash; _store.deleteRecord(_tableId, _keyTuple, _fieldLayout); } diff --git a/packages/world/test/World.t.sol b/packages/world/test/World.t.sol index e1129733e0..7cf3111d2c 100644 --- a/packages/world/test/World.t.sol +++ b/packages/world/test/World.t.sol @@ -136,12 +136,12 @@ contract PayableFallbackSystem is System { contract EchoSystemHook is SystemHook { event SystemHookCalled(bytes data); - function onBeforeCallSystem(address msgSender, bytes32 resourceSelector, bytes memory funcSelectorAndArgs) public { - emit SystemHookCalled(abi.encode("before", msgSender, resourceSelector, funcSelectorAndArgs)); + function onBeforeCallSystem(address msgSender, bytes32 resourceSelector, bytes memory callData) public { + emit SystemHookCalled(abi.encode("before", msgSender, resourceSelector, callData)); } - function onAfterCallSystem(address msgSender, bytes32 resourceSelector, bytes memory funcSelectorAndArgs) public { - emit SystemHookCalled(abi.encode("after", msgSender, resourceSelector, funcSelectorAndArgs)); + function onAfterCallSystem(address msgSender, bytes32 resourceSelector, bytes memory callData) public { + emit SystemHookCalled(abi.encode("after", msgSender, resourceSelector, callData)); } } @@ -738,7 +738,7 @@ contract WorldTest is Test, GasReporter { WorldTestSystem.delegateCallSubSystem.selector, // Function in system address(subSystem), // Address of subsystem WorldContextProvider.appendContext({ - funcSelectorAndArgs: abi.encodeWithSelector(WorldTestSystem.msgSender.selector), + callData: abi.encodeWithSelector(WorldTestSystem.msgSender.selector), msgSender: address(this), msgValue: uint256(0) }) @@ -1005,20 +1005,20 @@ contract WorldTest is Test, GasReporter { ISystemHook systemHook = new EchoSystemHook(); world.registerSystemHook(systemId, systemHook, BEFORE_CALL_SYSTEM | AFTER_CALL_SYSTEM); - bytes memory funcSelectorAndArgs = abi.encodeWithSelector(bytes4(keccak256("fallbackselector"))); + bytes memory callData = abi.encodeWithSelector(bytes4(keccak256("fallbackselector"))); // Expect the hooks to be called in correct order vm.expectEmit(true, true, true, true); - emit SystemHookCalled(abi.encode("before", address(this), systemId, funcSelectorAndArgs)); + emit SystemHookCalled(abi.encode("before", address(this), systemId, callData)); vm.expectEmit(true, true, true, true); emit WorldTestSystemLog("fallback"); vm.expectEmit(true, true, true, true); - emit SystemHookCalled(abi.encode("after", address(this), systemId, funcSelectorAndArgs)); + emit SystemHookCalled(abi.encode("after", address(this), systemId, callData)); // Call a system fallback function without arguments via the World - world.call(systemId, funcSelectorAndArgs); + world.call(systemId, callData); } function testUnregisterSystemHook() public { @@ -1036,27 +1036,27 @@ contract WorldTest is Test, GasReporter { ISystemHook echoSystemHook = new EchoSystemHook(); world.registerSystemHook(systemId, echoSystemHook, BEFORE_CALL_SYSTEM | AFTER_CALL_SYSTEM); - bytes memory funcSelectorAndArgs = abi.encodeWithSelector(bytes4(keccak256("fallbackselector"))); + bytes memory callData = abi.encodeWithSelector(bytes4(keccak256("fallbackselector"))); // Expect calls to fail while the RevertSystemHook is registered vm.expectRevert(bytes("onBeforeCallSystem")); - world.call(systemId, funcSelectorAndArgs); + world.call(systemId, callData); // Unregister the RevertSystemHook world.unregisterSystemHook(systemId, revertSystemHook); // Expect the echo hooks to be called in correct order vm.expectEmit(true, true, true, true); - emit SystemHookCalled(abi.encode("before", address(this), systemId, funcSelectorAndArgs)); + emit SystemHookCalled(abi.encode("before", address(this), systemId, callData)); vm.expectEmit(true, true, true, true); emit WorldTestSystemLog("fallback"); vm.expectEmit(true, true, true, true); - emit SystemHookCalled(abi.encode("after", address(this), systemId, funcSelectorAndArgs)); + emit SystemHookCalled(abi.encode("after", address(this), systemId, callData)); // Call a system fallback function without arguments via the World - world.call(systemId, funcSelectorAndArgs); + world.call(systemId, callData); } function testWriteRootSystem() public { diff --git a/packages/world/test/WorldContext.t.sol b/packages/world/test/WorldContext.t.sol index 4ba6fb2454..174c90bfd3 100644 --- a/packages/world/test/WorldContext.t.sol +++ b/packages/world/test/WorldContext.t.sol @@ -18,10 +18,10 @@ contract WorldContextTest is Test, GasReporter { TestContextConsumer public consumer = new TestContextConsumer(); - function testFuzzAppendContext(bytes memory funcSelectorAndArgs, address msgSender, uint256 msgValue) public { + function testFuzzAppendContext(bytes memory callData, address msgSender, uint256 msgValue) public { assertEq( - keccak256(abi.encodePacked(funcSelectorAndArgs, msgSender, msgValue)), - keccak256(WorldContextProvider.appendContext(funcSelectorAndArgs, msgSender, msgValue)) + keccak256(abi.encodePacked(callData, msgSender, msgValue)), + keccak256(WorldContextProvider.appendContext(callData, msgSender, msgValue)) ); } @@ -34,7 +34,7 @@ contract WorldContextTest is Test, GasReporter { msgSender: msgSender, msgValue: msgValue, target: address(consumer), - funcSelectorAndArgs: abi.encodeWithSelector(TestContextConsumer.emitContext.selector, args) + callData: abi.encodeWithSelector(TestContextConsumer.emitContext.selector, args) }); } @@ -47,7 +47,7 @@ contract WorldContextTest is Test, GasReporter { msgSender: msgSender, msgValue: msgValue, target: address(consumer), - funcSelectorAndArgs: abi.encodeWithSelector(TestContextConsumer.emitContext.selector, args) + callData: abi.encodeWithSelector(TestContextConsumer.emitContext.selector, args) }); } } From ac508bf189b098e66b59a725f58a2008537be130 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Sun, 17 Sep 2023 19:41:27 +0100 Subject: [PATCH 16/17] feat(store): codegen index and common files (#1318) Co-authored-by: alvarius --- .changeset/shy-monkeys-wonder.md | 29 +++++++++++++++++++ .../src/codegen/{Tables.sol => index.sol} | 0 .../src/systems/NumberListSystem.sol | 2 +- .../minimal/packages/contracts/package.json | 2 +- .../contracts/script/PostDeploy.s.sol | 2 +- .../src/codegen/{Tables.sol => index.sol} | 0 .../src/systems/ChatNamespacedSystem.sol | 2 +- .../contracts/src/systems/ChatSystem.sol | 2 +- .../contracts/src/systems/IncrementSystem.sol | 2 +- .../contracts/src/systems/InventorySystem.sol | 2 +- .../contracts/src/systems/StructSystem.sol | 2 +- .../contracts/test/ChatNamespaced.t.sol | 2 +- .../packages/contracts/test/CounterTest.t.sol | 2 +- .../packages/contracts/test/StructTest.t.sol | 2 +- packages/cli/contracts/src/codegen/common.sol | 13 +++++++++ packages/cli/contracts/src/codegen/index.sol | 10 +++++++ .../contracts/src/codegen/tables/Statics.sol | 2 +- packages/cli/contracts/test/Tablegen.t.sol | 4 +-- packages/store/src/StoreCore.sol | 2 +- .../src/codegen/{Types.sol => common.sol} | 0 .../src/codegen/{Tables.sol => index.sol} | 0 .../store/src/codegen/tables/KeyEncoding.sol | 2 +- packages/store/test/Gas.t.sol | 2 +- packages/store/test/KeyEncoding.t.sol | 4 +-- packages/store/test/Mixed.t.sol | 2 +- packages/store/test/StoreCore.t.sol | 2 +- packages/store/test/Vector2.t.sol | 2 +- packages/store/test/tables/Callbacks.t.sol | 2 +- packages/store/test/tables/StoreHooks.t.sol | 2 +- .../test/tables/StoreHooksColdLoad.t.sol | 2 +- packages/store/ts/codegen/tablegen.ts | 4 +-- packages/store/ts/codegen/userType.ts | 2 +- packages/store/ts/config/defaults.ts | 3 +- packages/store/ts/config/storeConfig.ts | 9 ++++-- .../store/ts/register/mudConfig.test-d.ts | 3 +- packages/store/ts/register/typeExtensions.ts | 3 +- packages/world/src/common.sol | 10 +++++++ packages/world/src/index.sol | 23 +++++++++++++++ .../world/src/modules/core/CoreModule.sol | 2 +- .../StoreRegistrationSystem.sol | 2 +- .../WorldRegistrationSystem.sol | 2 +- .../src/modules/core/tables/ResourceType.sol | 2 +- .../modules/keysintable/KeysInTableModule.sol | 2 +- packages/world/test/World.t.sol | 4 +-- .../phaser/packages/contracts/package.json | 2 +- .../src/codegen/{Tables.sol => index.sol} | 0 .../contracts/src/systems/IncrementSystem.sol | 2 +- .../packages/contracts/test/CounterTest.t.sol | 2 +- .../react/packages/contracts/package.json | 2 +- .../src/codegen/{Tables.sol => index.sol} | 0 .../contracts/src/systems/IncrementSystem.sol | 2 +- .../packages/contracts/test/CounterTest.t.sol | 2 +- .../threejs/packages/contracts/package.json | 2 +- .../src/codegen/{Tables.sol => index.sol} | 0 .../contracts/src/systems/MoveSystem.sol | 2 +- .../vanilla/packages/contracts/package.json | 2 +- .../src/codegen/{Tables.sol => index.sol} | 0 .../contracts/src/systems/IncrementSystem.sol | 2 +- .../packages/contracts/test/CounterTest.t.sol | 2 +- 59 files changed, 143 insertions(+), 52 deletions(-) create mode 100644 .changeset/shy-monkeys-wonder.md rename e2e/packages/contracts/src/codegen/{Tables.sol => index.sol} (100%) rename examples/minimal/packages/contracts/src/codegen/{Tables.sol => index.sol} (100%) create mode 100644 packages/cli/contracts/src/codegen/common.sol create mode 100644 packages/cli/contracts/src/codegen/index.sol rename packages/store/src/codegen/{Types.sol => common.sol} (100%) rename packages/store/src/codegen/{Tables.sol => index.sol} (100%) create mode 100644 packages/world/src/common.sol create mode 100644 packages/world/src/index.sol rename templates/phaser/packages/contracts/src/codegen/{Tables.sol => index.sol} (100%) rename templates/react/packages/contracts/src/codegen/{Tables.sol => index.sol} (100%) rename templates/threejs/packages/contracts/src/codegen/{Tables.sol => index.sol} (100%) rename templates/vanilla/packages/contracts/src/codegen/{Tables.sol => index.sol} (100%) diff --git a/.changeset/shy-monkeys-wonder.md b/.changeset/shy-monkeys-wonder.md new file mode 100644 index 0000000000..9105087ee5 --- /dev/null +++ b/.changeset/shy-monkeys-wonder.md @@ -0,0 +1,29 @@ +--- +"@latticexyz/cli": major +"@latticexyz/store": major +"create-mud": patch +--- + +Renamed the default filename of generated user types from `Types.sol` to `common.sol` and the default filename of the generated table index file from `Tables.sol` to `index.sol`. + +Both can be overridden via the MUD config: + +```ts +export default mudConfig({ + /** Filename where common user types will be generated and imported from. */ + userTypesFilename: "common.sol", + /** Filename where codegen index will be generated. */ + codegenIndexFilename: "index.sol", +}); +``` + +Note: `userTypesFilename` was renamed from `userTypesPath` and `.sol` is not appended automatically anymore but needs to be part of the provided filename. + +To update your existing project, update all imports from `Tables.sol` to `index.sol` and all imports from `Types.sol` to `common.sol`, or override the defaults in your MUD config to the previous values. + +```diff +- import { Counter } from "../src/codegen/Tables.sol"; ++ import { Counter } from "../src/codegen/index.sol"; +- import { ExampleEnum } from "../src/codegen/Types.sol"; ++ import { ExampleEnum } from "../src/codegen/common.sol"; +``` diff --git a/e2e/packages/contracts/src/codegen/Tables.sol b/e2e/packages/contracts/src/codegen/index.sol similarity index 100% rename from e2e/packages/contracts/src/codegen/Tables.sol rename to e2e/packages/contracts/src/codegen/index.sol diff --git a/e2e/packages/contracts/src/systems/NumberListSystem.sol b/e2e/packages/contracts/src/systems/NumberListSystem.sol index cd6d80a58c..6d48adc115 100644 --- a/e2e/packages/contracts/src/systems/NumberListSystem.sol +++ b/e2e/packages/contracts/src/systems/NumberListSystem.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { System } from "@latticexyz/world/src/System.sol"; -import { NumberList, NumberListTableId } from "../codegen/Tables.sol"; +import { NumberList, NumberListTableId } from "../codegen/index.sol"; contract NumberListSystem is System { function set(uint32[] memory list) public { diff --git a/examples/minimal/packages/contracts/package.json b/examples/minimal/packages/contracts/package.json index 5acf110bed..21abadfe78 100644 --- a/examples/minimal/packages/contracts/package.json +++ b/examples/minimal/packages/contracts/package.json @@ -7,7 +7,7 @@ "build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts", "build:abi": "forge clean && forge build --skip test script", "build:abi-ts": "mud abi-ts && prettier --write '**/*.abi.json.d.ts'", - "build:mud": "mud tablegen && mud worldgen", + "build:mud": "rimraf src/codegen && mud tablegen && mud worldgen", "deploy:local": "pnpm run build && mud deploy", "deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet", "dev": "pnpm mud dev-contracts", diff --git a/examples/minimal/packages/contracts/script/PostDeploy.s.sol b/examples/minimal/packages/contracts/script/PostDeploy.s.sol index d540e882e2..059758821e 100644 --- a/examples/minimal/packages/contracts/script/PostDeploy.s.sol +++ b/examples/minimal/packages/contracts/script/PostDeploy.s.sol @@ -6,7 +6,7 @@ import { console } from "forge-std/console.sol"; import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol"; import { IWorld } from "../src/codegen/world/IWorld.sol"; -import { MessageTable, MessageTableTableId } from "../src/codegen/Tables.sol"; +import { MessageTable, MessageTableTableId } from "../src/codegen/index.sol"; import { ChatNamespacedSystem } from "../src/systems/ChatNamespacedSystem.sol"; contract PostDeploy is Script { diff --git a/examples/minimal/packages/contracts/src/codegen/Tables.sol b/examples/minimal/packages/contracts/src/codegen/index.sol similarity index 100% rename from examples/minimal/packages/contracts/src/codegen/Tables.sol rename to examples/minimal/packages/contracts/src/codegen/index.sol diff --git a/examples/minimal/packages/contracts/src/systems/ChatNamespacedSystem.sol b/examples/minimal/packages/contracts/src/systems/ChatNamespacedSystem.sol index 3a7949e086..88a5958cbe 100644 --- a/examples/minimal/packages/contracts/src/systems/ChatNamespacedSystem.sol +++ b/examples/minimal/packages/contracts/src/systems/ChatNamespacedSystem.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { System } from "@latticexyz/world/src/System.sol"; -import { MessageTable } from "../codegen/Tables.sol"; +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 { diff --git a/examples/minimal/packages/contracts/src/systems/ChatSystem.sol b/examples/minimal/packages/contracts/src/systems/ChatSystem.sol index 8eb4229f47..6091eb92a9 100644 --- a/examples/minimal/packages/contracts/src/systems/ChatSystem.sol +++ b/examples/minimal/packages/contracts/src/systems/ChatSystem.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { System } from "@latticexyz/world/src/System.sol"; -import { MessageTable } from "../codegen/Tables.sol"; +import { MessageTable } from "../codegen/index.sol"; contract ChatSystem is System { function sendMessage(string memory message) public { diff --git a/examples/minimal/packages/contracts/src/systems/IncrementSystem.sol b/examples/minimal/packages/contracts/src/systems/IncrementSystem.sol index e5f0d89c3d..7d805b655d 100644 --- a/examples/minimal/packages/contracts/src/systems/IncrementSystem.sol +++ b/examples/minimal/packages/contracts/src/systems/IncrementSystem.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0; import { console } from "forge-std/console.sol"; import { System } from "@latticexyz/world/src/System.sol"; -import { CounterTable } from "../codegen/Tables.sol"; +import { CounterTable } from "../codegen/index.sol"; contract IncrementSystem is System { error MyCustomError(); diff --git a/examples/minimal/packages/contracts/src/systems/InventorySystem.sol b/examples/minimal/packages/contracts/src/systems/InventorySystem.sol index 914cad3a80..6360871dde 100644 --- a/examples/minimal/packages/contracts/src/systems/InventorySystem.sol +++ b/examples/minimal/packages/contracts/src/systems/InventorySystem.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { System } from "@latticexyz/world/src/System.sol"; -import { Inventory } from "../codegen/Tables.sol"; +import { Inventory } from "../codegen/index.sol"; contract InventorySystem is System { function pickUp(uint32 item, uint32 itemVariant) public { diff --git a/examples/minimal/packages/contracts/src/systems/StructSystem.sol b/examples/minimal/packages/contracts/src/systems/StructSystem.sol index dec8e95a24..5fe1ad91cb 100644 --- a/examples/minimal/packages/contracts/src/systems/StructSystem.sol +++ b/examples/minimal/packages/contracts/src/systems/StructSystem.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { System } from "@latticexyz/world/src/System.sol"; -import { CounterTable } from "../codegen/Tables.sol"; +import { CounterTable } from "../codegen/index.sol"; import { BytesStruct, StringStruct } from "./structs.sol"; contract StructSystem is System { diff --git a/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol b/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol index 0bd179745f..10a4675e22 100644 --- a/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol +++ b/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol @@ -7,7 +7,7 @@ import { getKeysWithValue } from "@latticexyz/world/src/modules/keyswithvalue/ge import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { IWorld } from "../src/codegen/world/IWorld.sol"; -import { MessageTable, MessageTableTableId } from "../src/codegen/Tables.sol"; +import { MessageTable, MessageTableTableId } from "../src/codegen/index.sol"; import { IChatNamespacedSystem } from "../src/interfaces/IChatNamespacedSystem.sol"; contract ChatNamespacedTest is MudTest { diff --git a/examples/minimal/packages/contracts/test/CounterTest.t.sol b/examples/minimal/packages/contracts/test/CounterTest.t.sol index 70b201406a..f731279df5 100644 --- a/examples/minimal/packages/contracts/test/CounterTest.t.sol +++ b/examples/minimal/packages/contracts/test/CounterTest.t.sol @@ -6,7 +6,7 @@ import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; import { getKeysWithValue } from "@latticexyz/world/src/modules/keyswithvalue/getKeysWithValue.sol"; import { IWorld } from "../src/codegen/world/IWorld.sol"; -import { CounterTable, CounterTableTableId } from "../src/codegen/Tables.sol"; +import { CounterTable, CounterTableTableId } from "../src/codegen/index.sol"; contract CounterTest is MudTest { IWorld world; diff --git a/examples/minimal/packages/contracts/test/StructTest.t.sol b/examples/minimal/packages/contracts/test/StructTest.t.sol index 637acd2405..87b67846da 100644 --- a/examples/minimal/packages/contracts/test/StructTest.t.sol +++ b/examples/minimal/packages/contracts/test/StructTest.t.sol @@ -6,7 +6,7 @@ import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; import { getKeysWithValue } from "@latticexyz/world/src/modules/keyswithvalue/getKeysWithValue.sol"; import { IWorld } from "../src/codegen/world/IWorld.sol"; -import { CounterTable, CounterTableTableId } from "../src/codegen/Tables.sol"; +import { CounterTable, CounterTableTableId } from "../src/codegen/index.sol"; import { BytesStruct, StringStruct } from "../src/systems/structs.sol"; contract StructTest is MudTest { diff --git a/packages/cli/contracts/src/codegen/common.sol b/packages/cli/contracts/src/codegen/common.sol new file mode 100644 index 0000000000..85fa534462 --- /dev/null +++ b/packages/cli/contracts/src/codegen/common.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +/* Autogenerated file. Do not edit manually. */ +enum Enum1 { + E1, + E2, + E3 +} + +enum Enum2 { + E1 +} diff --git a/packages/cli/contracts/src/codegen/index.sol b/packages/cli/contracts/src/codegen/index.sol new file mode 100644 index 0000000000..de034e0789 --- /dev/null +++ b/packages/cli/contracts/src/codegen/index.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +/* Autogenerated file. Do not edit manually. */ + +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"; diff --git a/packages/cli/contracts/src/codegen/tables/Statics.sol b/packages/cli/contracts/src/codegen/tables/Statics.sol index 0c74e1b419..b65c03db2f 100644 --- a/packages/cli/contracts/src/codegen/tables/Statics.sol +++ b/packages/cli/contracts/src/codegen/tables/Statics.sol @@ -19,7 +19,7 @@ import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; // Import user types -import { Enum2, Enum1 } from "./../Types.sol"; +import { Enum2, Enum1 } from "./../common.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Statics"))); bytes32 constant StaticsTableId = _tableId; diff --git a/packages/cli/contracts/test/Tablegen.t.sol b/packages/cli/contracts/test/Tablegen.t.sol index af41a9f635..d5a5cbc77b 100644 --- a/packages/cli/contracts/test/Tablegen.t.sol +++ b/packages/cli/contracts/test/Tablegen.t.sol @@ -4,9 +4,9 @@ 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/Tables.sol"; +import { Statics, StaticsData, Dynamics1, Dynamics1Data, Dynamics2, Dynamics2Data, Singleton, Ephemeral } from "../src/codegen/index.sol"; -import { Enum1, Enum2 } from "../src/codegen/Types.sol"; +import { Enum1, Enum2 } from "../src/codegen/common.sol"; contract TablegenTest is Test, StoreMock { function testStaticsSetAndGet() public { diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 0d7e48548a..67361e3d84 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -9,7 +9,7 @@ import { FieldLayout, FieldLayoutLib } from "./FieldLayout.sol"; import { Schema, SchemaLib } from "./Schema.sol"; import { PackedCounter } from "./PackedCounter.sol"; import { Slice, SliceLib } from "./Slice.sol"; -import { StoreHooks, Tables, StoreHooksTableId } from "./codegen/Tables.sol"; +import { StoreHooks, Tables, StoreHooksTableId } from "./codegen/index.sol"; import { IStoreErrors } from "./IStoreErrors.sol"; import { IStoreHook } from "./IStoreHook.sol"; import { StoreSwitch } from "./StoreSwitch.sol"; diff --git a/packages/store/src/codegen/Types.sol b/packages/store/src/codegen/common.sol similarity index 100% rename from packages/store/src/codegen/Types.sol rename to packages/store/src/codegen/common.sol diff --git a/packages/store/src/codegen/Tables.sol b/packages/store/src/codegen/index.sol similarity index 100% rename from packages/store/src/codegen/Tables.sol rename to packages/store/src/codegen/index.sol diff --git a/packages/store/src/codegen/tables/KeyEncoding.sol b/packages/store/src/codegen/tables/KeyEncoding.sol index 47cc468cb7..013f19d845 100644 --- a/packages/store/src/codegen/tables/KeyEncoding.sol +++ b/packages/store/src/codegen/tables/KeyEncoding.sol @@ -19,7 +19,7 @@ import { Schema, SchemaLib } from "../../Schema.sol"; import { PackedCounter, PackedCounterLib } from "../../PackedCounter.sol"; // Import user types -import { ExampleEnum } from "./../Types.sol"; +import { ExampleEnum } from "./../common.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16("mudstore"), bytes16("KeyEncoding"))); bytes32 constant KeyEncodingTableId = _tableId; diff --git a/packages/store/test/Gas.t.sol b/packages/store/test/Gas.t.sol index ea0a6299e9..bd776cd145 100644 --- a/packages/store/test/Gas.t.sol +++ b/packages/store/test/Gas.t.sol @@ -7,7 +7,7 @@ import { Bytes } from "../src/Bytes.sol"; import { SliceLib } from "../src/Slice.sol"; import { Storage } from "../src/Storage.sol"; import { PackedCounter } from "../src/PackedCounter.sol"; -import { Mixed, MixedData } from "../src/codegen/Tables.sol"; +import { Mixed, MixedData } from "../src/codegen/index.sol"; contract SomeContract { function doSomethingWithBytes(bytes memory data) public {} diff --git a/packages/store/test/KeyEncoding.t.sol b/packages/store/test/KeyEncoding.t.sol index 1c959ba75b..f1b91ae49b 100644 --- a/packages/store/test/KeyEncoding.t.sol +++ b/packages/store/test/KeyEncoding.t.sol @@ -3,8 +3,8 @@ pragma solidity >=0.8.0; import { Test } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; -import { KeyEncoding, KeyEncodingTableId } from "../src/codegen/Tables.sol"; -import { ExampleEnum } from "../src/codegen/Types.sol"; +import { KeyEncoding, KeyEncodingTableId } from "../src/codegen/index.sol"; +import { ExampleEnum } from "../src/codegen/common.sol"; import { StoreCore } from "../src/StoreCore.sol"; import { StoreMock } from "../test/StoreMock.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; diff --git a/packages/store/test/Mixed.t.sol b/packages/store/test/Mixed.t.sol index b38f714d53..453c405d4c 100644 --- a/packages/store/test/Mixed.t.sol +++ b/packages/store/test/Mixed.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.0; import { Test } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; -import { Mixed, MixedData, MixedTableId } from "../src/codegen/Tables.sol"; +import { Mixed, MixedData, MixedTableId } from "../src/codegen/index.sol"; import { StoreCore } from "../src/StoreCore.sol"; import { StoreMock } from "../test/StoreMock.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; diff --git a/packages/store/test/StoreCore.t.sol b/packages/store/test/StoreCore.t.sol index 5228db737d..d9fa42b94d 100644 --- a/packages/store/test/StoreCore.t.sol +++ b/packages/store/test/StoreCore.t.sol @@ -14,7 +14,7 @@ import { StoreMock } from "../test/StoreMock.sol"; import { IStoreErrors } from "../src/IStoreErrors.sol"; import { IStore } from "../src/IStore.sol"; import { StoreSwitch } from "../src/StoreSwitch.sol"; -import { Tables, TablesTableId } from "../src/codegen/Tables.sol"; +import { Tables, TablesTableId } from "../src/codegen/index.sol"; import { FieldLayoutEncodeHelper } from "./FieldLayoutEncodeHelper.sol"; import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SET_FIELD, AFTER_SET_FIELD, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "../src/storeHookTypes.sol"; import { SchemaEncodeHelper } from "./SchemaEncodeHelper.sol"; diff --git a/packages/store/test/Vector2.t.sol b/packages/store/test/Vector2.t.sol index 769054a76a..3c6fe3541a 100644 --- a/packages/store/test/Vector2.t.sol +++ b/packages/store/test/Vector2.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.0; import { Test } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; -import { Vector2, Vector2Data, Vector2TableId } from "../src/codegen/Tables.sol"; +import { Vector2, Vector2Data, Vector2TableId } from "../src/codegen/index.sol"; import { StoreCore } from "../src/StoreCore.sol"; import { StoreMock } from "../test/StoreMock.sol"; import { FieldLayout } from "../src/FieldLayout.sol"; diff --git a/packages/store/test/tables/Callbacks.t.sol b/packages/store/test/tables/Callbacks.t.sol index dacf396c31..e7f40e3a78 100644 --- a/packages/store/test/tables/Callbacks.t.sol +++ b/packages/store/test/tables/Callbacks.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0; import { Test } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { StoreMock } from "../../test/StoreMock.sol"; -import { Callbacks } from "../../src/codegen/Tables.sol"; +import { Callbacks } from "../../src/codegen/index.sol"; contract CallbacksTest is Test, GasReporter, StoreMock { function testSetAndGet() public { diff --git a/packages/store/test/tables/StoreHooks.t.sol b/packages/store/test/tables/StoreHooks.t.sol index 5960dde364..e6fa64dd85 100644 --- a/packages/store/test/tables/StoreHooks.t.sol +++ b/packages/store/test/tables/StoreHooks.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0; import { Test } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { StoreMock } from "../../test/StoreMock.sol"; -import { StoreHooks } from "../../src/codegen/Tables.sol"; +import { StoreHooks } from "../../src/codegen/index.sol"; contract StoreHooksTest is Test, GasReporter, StoreMock { function testTable() public { diff --git a/packages/store/test/tables/StoreHooksColdLoad.t.sol b/packages/store/test/tables/StoreHooksColdLoad.t.sol index 07513c2c54..2943927e51 100644 --- a/packages/store/test/tables/StoreHooksColdLoad.t.sol +++ b/packages/store/test/tables/StoreHooksColdLoad.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0; import { Test } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { StoreMock } from "../../test/StoreMock.sol"; -import { StoreHooks } from "../../src/codegen/Tables.sol"; +import { StoreHooks } from "../../src/codegen/index.sol"; contract StoreHooksColdLoadTest is Test, GasReporter, StoreMock { bytes21[] hooks; diff --git a/packages/store/ts/codegen/tablegen.ts b/packages/store/ts/codegen/tablegen.ts index f154e42d9b..9852081a41 100644 --- a/packages/store/ts/codegen/tablegen.ts +++ b/packages/store/ts/codegen/tablegen.ts @@ -24,12 +24,12 @@ export async function tablegen(config: StoreConfig, outputBaseDirectory: string) // write types to file if (Object.keys(config.enums).length > 0) { - const fullOutputPath = path.join(outputBaseDirectory, `${config.userTypesPath}.sol`); + const fullOutputPath = path.join(outputBaseDirectory, config.userTypesFilename); const output = renderTypesFromConfig(config); await formatAndWriteSolidity(output, fullOutputPath, "Generated types file"); } - const fullOutputPath = path.join(outputBaseDirectory, `Tables.sol`); + const fullOutputPath = path.join(outputBaseDirectory, config.codegenIndexFilename); const output = renderTableIndex(allTableOptions); await formatAndWriteSolidity(output, fullOutputPath, "Generated table index"); } diff --git a/packages/store/ts/codegen/userType.ts b/packages/store/ts/codegen/userType.ts index e23d988d28..f22f2664de 100644 --- a/packages/store/ts/codegen/userType.ts +++ b/packages/store/ts/codegen/userType.ts @@ -61,7 +61,7 @@ export function importForAbiOrUserType( // user types return { symbol: abiOrUserType, - fromPath: config.userTypesPath + ".sol", + fromPath: config.userTypesFilename, usedInPath: usedInDirectory, }; } diff --git a/packages/store/ts/config/defaults.ts b/packages/store/ts/config/defaults.ts index 0aecf902da..0393830547 100644 --- a/packages/store/ts/config/defaults.ts +++ b/packages/store/ts/config/defaults.ts @@ -1,7 +1,8 @@ export const PATH_DEFAULTS = { storeImportPath: "@latticexyz/store/src/", - userTypesPath: "Types", + userTypesFilename: "common.sol", codegenDirectory: "codegen", + codegenIndexFilename: "index.sol", } as const; export const DEFAULTS = { diff --git a/packages/store/ts/config/storeConfig.ts b/packages/store/ts/config/storeConfig.ts index 8a3905d359..2795a266ff 100644 --- a/packages/store/ts/config/storeConfig.ts +++ b/packages/store/ts/config/storeConfig.ts @@ -261,10 +261,12 @@ export type MUDUserConfig< namespace?: string; /** Path for store package imports. Default is "@latticexyz/store/src/" */ storeImportPath?: string; - /** Path to the file where common user types will be generated and imported from. Default is "Types" */ - userTypesPath?: string; + /** Filename where common user types will be generated and imported from. Default is "common.sol" */ + userTypesFilename?: string; /** Path to the directory where generated files will be placed. (Default is "codegen") */ codegenDirectory?: string; + /** Filename where codegen index will be generated. Default is "index.sol" */ + codegenIndexFilename?: string; }; const StoreConfigUnrefined = z @@ -272,8 +274,9 @@ const StoreConfigUnrefined = z namespace: zSelector.default(DEFAULTS.namespace), storeImportPath: z.string().default(PATH_DEFAULTS.storeImportPath), tables: zTablesConfig, - userTypesPath: z.string().default(PATH_DEFAULTS.userTypesPath), + userTypesFilename: z.string().default(PATH_DEFAULTS.userTypesFilename), codegenDirectory: z.string().default(PATH_DEFAULTS.codegenDirectory), + codegenIndexFilename: z.string().default(PATH_DEFAULTS.codegenIndexFilename), }) .merge(zEnumsConfig); diff --git a/packages/store/ts/register/mudConfig.test-d.ts b/packages/store/ts/register/mudConfig.test-d.ts index de08e2695b..e310c93804 100644 --- a/packages/store/ts/register/mudConfig.test-d.ts +++ b/packages/store/ts/register/mudConfig.test-d.ts @@ -50,7 +50,8 @@ describe("mudConfig", () => { }; namespace: ""; storeImportPath: "@latticexyz/store/src/"; - userTypesPath: "Types"; + userTypesFilename: "common.sol"; codegenDirectory: "codegen"; + codegenIndexFilename: "index.sol"; }>(); }); diff --git a/packages/store/ts/register/typeExtensions.ts b/packages/store/ts/register/typeExtensions.ts index 88dd09dee4..e0bb8d20cb 100644 --- a/packages/store/ts/register/typeExtensions.ts +++ b/packages/store/ts/register/typeExtensions.ts @@ -27,8 +27,9 @@ export interface ExpandMUDUserConfig enums: typeof DEFAULTS.enums; namespace: typeof DEFAULTS.namespace; storeImportPath: typeof PATH_DEFAULTS.storeImportPath; - userTypesPath: typeof PATH_DEFAULTS.userTypesPath; + userTypesFilename: typeof PATH_DEFAULTS.userTypesFilename; codegenDirectory: typeof PATH_DEFAULTS.codegenDirectory; + codegenIndexFilename: typeof PATH_DEFAULTS.codegenIndexFilename; } > { tables: ExpandTablesConfig; diff --git a/packages/world/src/common.sol b/packages/world/src/common.sol new file mode 100644 index 0000000000..6c4b0ff193 --- /dev/null +++ b/packages/world/src/common.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +/* Autogenerated file. Do not edit manually. */ +enum Resource { + NONE, + NAMESPACE, + TABLE, + SYSTEM +} diff --git a/packages/world/src/index.sol b/packages/world/src/index.sol new file mode 100644 index 0000000000..021a7371bf --- /dev/null +++ b/packages/world/src/index.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +/* Autogenerated file. Do not edit manually. */ + +import { NamespaceOwner, NamespaceOwnerTableId } from "./tables/NamespaceOwner.sol"; +import { ResourceAccess, ResourceAccessTableId } from "./tables/ResourceAccess.sol"; +import { InstalledModules, InstalledModulesTableId } from "./tables/InstalledModules.sol"; +import { Delegations, DelegationsTableId } from "./tables/Delegations.sol"; +import { Balances, BalancesTableId } from "./modules/core/tables/Balances.sol"; +import { Systems, SystemsTableId } from "./modules/core/tables/Systems.sol"; +import { SystemRegistry, SystemRegistryTableId } from "./modules/core/tables/SystemRegistry.sol"; +import { SystemHooks, SystemHooksTableId } from "./modules/core/tables/SystemHooks.sol"; +import { ResourceType, ResourceTypeTableId } from "./modules/core/tables/ResourceType.sol"; +import { FunctionSelectors, FunctionSelectorsTableId } from "./modules/core/tables/FunctionSelectors.sol"; +import { KeysWithValue } from "./modules/keyswithvalue/tables/KeysWithValue.sol"; +import { KeysInTable, KeysInTableData, KeysInTableTableId } from "./modules/keysintable/tables/KeysInTable.sol"; +import { UsedKeysIndex, UsedKeysIndexTableId } from "./modules/keysintable/tables/UsedKeysIndex.sol"; +import { UniqueEntity } from "./modules/uniqueentity/tables/UniqueEntity.sol"; +import { CallboundDelegations, CallboundDelegationsTableId } from "./modules/std-delegations/tables/CallboundDelegations.sol"; +import { TimeboundDelegations, TimeboundDelegationsTableId } from "./modules/std-delegations/tables/TimeboundDelegations.sol"; +import { Bool } from "./../test/tables/Bool.sol"; +import { AddressArray } from "./../test/tables/AddressArray.sol"; diff --git a/packages/world/src/modules/core/CoreModule.sol b/packages/world/src/modules/core/CoreModule.sol index 341e1aebeb..9e8698d72a 100644 --- a/packages/world/src/modules/core/CoreModule.sol +++ b/packages/world/src/modules/core/CoreModule.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.0; import { WorldContextProvider } from "../../WorldContext.sol"; import { ROOT_NAMESPACE } from "../../constants.sol"; -import { Resource } from "../../Types.sol"; +import { Resource } from "../../common.sol"; import { Module } from "../../Module.sol"; import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; diff --git a/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol b/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol index eee36e25fd..f51e198b4a 100644 --- a/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/StoreRegistrationSystem.sol @@ -8,7 +8,7 @@ import { Schema } from "@latticexyz/store/src/Schema.sol"; import { System } from "../../../System.sol"; import { ResourceSelector } from "../../../ResourceSelector.sol"; -import { Resource } from "../../../Types.sol"; +import { Resource } from "../../../common.sol"; import { ROOT_NAMESPACE, ROOT_NAME } from "../../../constants.sol"; import { AccessControl } from "../../../AccessControl.sol"; import { requireInterface } from "../../../requireInterface.sol"; diff --git a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol index a4d8ceea7b..58ecdea46f 100644 --- a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol @@ -6,7 +6,7 @@ import { Hook, HookLib } from "@latticexyz/store/src/Hook.sol"; import { System } from "../../../System.sol"; import { WorldContextConsumer, WORLD_CONTEXT_CONSUMER_INTERFACE_ID } from "../../../WorldContext.sol"; import { ResourceSelector } from "../../../ResourceSelector.sol"; -import { Resource } from "../../../Types.sol"; +import { Resource } from "../../../common.sol"; import { SystemCall } from "../../../SystemCall.sol"; import { ROOT_NAMESPACE, ROOT_NAME, UNLIMITED_DELEGATION } from "../../../constants.sol"; import { AccessControl } from "../../../AccessControl.sol"; diff --git a/packages/world/src/modules/core/tables/ResourceType.sol b/packages/world/src/modules/core/tables/ResourceType.sol index 0fb6a1c293..141d9b1bb5 100644 --- a/packages/world/src/modules/core/tables/ResourceType.sol +++ b/packages/world/src/modules/core/tables/ResourceType.sol @@ -19,7 +19,7 @@ import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; // Import user types -import { Resource } from "./../../../Types.sol"; +import { Resource } from "./../../../common.sol"; bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("ResourceType"))); bytes32 constant ResourceTypeTableId = _tableId; diff --git a/packages/world/src/modules/keysintable/KeysInTableModule.sol b/packages/world/src/modules/keysintable/KeysInTableModule.sol index b5c64cb8af..b775ea020a 100644 --- a/packages/world/src/modules/keysintable/KeysInTableModule.sol +++ b/packages/world/src/modules/keysintable/KeysInTableModule.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0; import { BEFORE_SET_RECORD, AFTER_SET_FIELD, BEFORE_DELETE_RECORD } from "@latticexyz/store/src/storeHookTypes.sol"; import { ResourceType } from "../core/tables/ResourceType.sol"; -import { Resource } from "../../Types.sol"; +import { Resource } from "../../common.sol"; import { Module } from "../../Module.sol"; import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; diff --git a/packages/world/test/World.t.sol b/packages/world/test/World.t.sol index 7cf3111d2c..4e1038c93c 100644 --- a/packages/world/test/World.t.sol +++ b/packages/world/test/World.t.sol @@ -14,7 +14,7 @@ import { FieldLayoutEncodeHelper } from "@latticexyz/store/test/FieldLayoutEncod import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol"; import { SchemaEncodeHelper } from "@latticexyz/store/test/SchemaEncodeHelper.sol"; -import { Tables, TablesTableId } from "@latticexyz/store/src/codegen/Tables.sol"; +import { Tables, TablesTableId } from "@latticexyz/store/src/codegen/index.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SET_FIELD, AFTER_SET_FIELD, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "@latticexyz/store/src/storeHookTypes.sol"; import { RevertSubscriber } from "@latticexyz/store/test/RevertSubscriber.sol"; @@ -25,7 +25,7 @@ import { World } from "../src/World.sol"; import { System } from "../src/System.sol"; import { ResourceSelector } from "../src/ResourceSelector.sol"; import { ROOT_NAMESPACE, ROOT_NAME, UNLIMITED_DELEGATION } from "../src/constants.sol"; -import { Resource } from "../src/Types.sol"; +import { Resource } from "../src/common.sol"; import { WorldContextProvider, WORLD_CONTEXT_CONSUMER_INTERFACE_ID } from "../src/WorldContext.sol"; import { SystemHook } from "../src/SystemHook.sol"; import { BEFORE_CALL_SYSTEM, AFTER_CALL_SYSTEM } from "../src/systemHookTypes.sol"; diff --git a/templates/phaser/packages/contracts/package.json b/templates/phaser/packages/contracts/package.json index d7c3b00abf..c3d56ce47e 100644 --- a/templates/phaser/packages/contracts/package.json +++ b/templates/phaser/packages/contracts/package.json @@ -7,7 +7,7 @@ "build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts", "build:abi": "forge clean && forge build --skip test script", "build:abi-ts": "mud abi-ts && prettier --write '**/*.abi.json.d.ts'", - "build:mud": "mud tablegen && mud worldgen", + "build:mud": "rimraf src/codegen && mud tablegen && mud worldgen", "deploy:local": "pnpm run build && mud deploy", "deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet", "dev": "pnpm mud dev-contracts", diff --git a/templates/phaser/packages/contracts/src/codegen/Tables.sol b/templates/phaser/packages/contracts/src/codegen/index.sol similarity index 100% rename from templates/phaser/packages/contracts/src/codegen/Tables.sol rename to templates/phaser/packages/contracts/src/codegen/index.sol diff --git a/templates/phaser/packages/contracts/src/systems/IncrementSystem.sol b/templates/phaser/packages/contracts/src/systems/IncrementSystem.sol index 1075d5999e..db5a2673a2 100644 --- a/templates/phaser/packages/contracts/src/systems/IncrementSystem.sol +++ b/templates/phaser/packages/contracts/src/systems/IncrementSystem.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0; import { System } from "@latticexyz/world/src/System.sol"; -import { Counter } from "../codegen/Tables.sol"; +import { Counter } from "../codegen/index.sol"; contract IncrementSystem is System { function increment() public returns (uint32) { diff --git a/templates/phaser/packages/contracts/test/CounterTest.t.sol b/templates/phaser/packages/contracts/test/CounterTest.t.sol index 5c16ef92af..efe11c5126 100644 --- a/templates/phaser/packages/contracts/test/CounterTest.t.sol +++ b/templates/phaser/packages/contracts/test/CounterTest.t.sol @@ -6,7 +6,7 @@ import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; import { getKeysWithValue } from "@latticexyz/world/src/modules/keyswithvalue/getKeysWithValue.sol"; import { IWorld } from "../src/codegen/world/IWorld.sol"; -import { Counter, CounterTableId } from "../src/codegen/Tables.sol"; +import { Counter, CounterTableId } from "../src/codegen/index.sol"; contract CounterTest is MudTest { IWorld public world; diff --git a/templates/react/packages/contracts/package.json b/templates/react/packages/contracts/package.json index d7c3b00abf..c3d56ce47e 100644 --- a/templates/react/packages/contracts/package.json +++ b/templates/react/packages/contracts/package.json @@ -7,7 +7,7 @@ "build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts", "build:abi": "forge clean && forge build --skip test script", "build:abi-ts": "mud abi-ts && prettier --write '**/*.abi.json.d.ts'", - "build:mud": "mud tablegen && mud worldgen", + "build:mud": "rimraf src/codegen && mud tablegen && mud worldgen", "deploy:local": "pnpm run build && mud deploy", "deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet", "dev": "pnpm mud dev-contracts", diff --git a/templates/react/packages/contracts/src/codegen/Tables.sol b/templates/react/packages/contracts/src/codegen/index.sol similarity index 100% rename from templates/react/packages/contracts/src/codegen/Tables.sol rename to templates/react/packages/contracts/src/codegen/index.sol diff --git a/templates/react/packages/contracts/src/systems/IncrementSystem.sol b/templates/react/packages/contracts/src/systems/IncrementSystem.sol index 1075d5999e..db5a2673a2 100644 --- a/templates/react/packages/contracts/src/systems/IncrementSystem.sol +++ b/templates/react/packages/contracts/src/systems/IncrementSystem.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0; import { System } from "@latticexyz/world/src/System.sol"; -import { Counter } from "../codegen/Tables.sol"; +import { Counter } from "../codegen/index.sol"; contract IncrementSystem is System { function increment() public returns (uint32) { diff --git a/templates/react/packages/contracts/test/CounterTest.t.sol b/templates/react/packages/contracts/test/CounterTest.t.sol index 5c16ef92af..efe11c5126 100644 --- a/templates/react/packages/contracts/test/CounterTest.t.sol +++ b/templates/react/packages/contracts/test/CounterTest.t.sol @@ -6,7 +6,7 @@ import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; import { getKeysWithValue } from "@latticexyz/world/src/modules/keyswithvalue/getKeysWithValue.sol"; import { IWorld } from "../src/codegen/world/IWorld.sol"; -import { Counter, CounterTableId } from "../src/codegen/Tables.sol"; +import { Counter, CounterTableId } from "../src/codegen/index.sol"; contract CounterTest is MudTest { IWorld public world; diff --git a/templates/threejs/packages/contracts/package.json b/templates/threejs/packages/contracts/package.json index d7c3b00abf..c3d56ce47e 100644 --- a/templates/threejs/packages/contracts/package.json +++ b/templates/threejs/packages/contracts/package.json @@ -7,7 +7,7 @@ "build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts", "build:abi": "forge clean && forge build --skip test script", "build:abi-ts": "mud abi-ts && prettier --write '**/*.abi.json.d.ts'", - "build:mud": "mud tablegen && mud worldgen", + "build:mud": "rimraf src/codegen && mud tablegen && mud worldgen", "deploy:local": "pnpm run build && mud deploy", "deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet", "dev": "pnpm mud dev-contracts", diff --git a/templates/threejs/packages/contracts/src/codegen/Tables.sol b/templates/threejs/packages/contracts/src/codegen/index.sol similarity index 100% rename from templates/threejs/packages/contracts/src/codegen/Tables.sol rename to templates/threejs/packages/contracts/src/codegen/index.sol diff --git a/templates/threejs/packages/contracts/src/systems/MoveSystem.sol b/templates/threejs/packages/contracts/src/systems/MoveSystem.sol index fe2de0c34b..c90fa1c107 100644 --- a/templates/threejs/packages/contracts/src/systems/MoveSystem.sol +++ b/templates/threejs/packages/contracts/src/systems/MoveSystem.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { System } from "@latticexyz/world/src/System.sol"; -import { Position, PositionData } from "../codegen/Tables.sol"; +import { Position, PositionData } from "../codegen/index.sol"; function distance(PositionData memory a, PositionData memory b) pure returns (int32) { int32 deltaX = a.x > b.x ? a.x - b.x : b.x - a.x; diff --git a/templates/vanilla/packages/contracts/package.json b/templates/vanilla/packages/contracts/package.json index d7c3b00abf..c3d56ce47e 100644 --- a/templates/vanilla/packages/contracts/package.json +++ b/templates/vanilla/packages/contracts/package.json @@ -7,7 +7,7 @@ "build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts", "build:abi": "forge clean && forge build --skip test script", "build:abi-ts": "mud abi-ts && prettier --write '**/*.abi.json.d.ts'", - "build:mud": "mud tablegen && mud worldgen", + "build:mud": "rimraf src/codegen && mud tablegen && mud worldgen", "deploy:local": "pnpm run build && mud deploy", "deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet", "dev": "pnpm mud dev-contracts", diff --git a/templates/vanilla/packages/contracts/src/codegen/Tables.sol b/templates/vanilla/packages/contracts/src/codegen/index.sol similarity index 100% rename from templates/vanilla/packages/contracts/src/codegen/Tables.sol rename to templates/vanilla/packages/contracts/src/codegen/index.sol diff --git a/templates/vanilla/packages/contracts/src/systems/IncrementSystem.sol b/templates/vanilla/packages/contracts/src/systems/IncrementSystem.sol index 1075d5999e..db5a2673a2 100644 --- a/templates/vanilla/packages/contracts/src/systems/IncrementSystem.sol +++ b/templates/vanilla/packages/contracts/src/systems/IncrementSystem.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0; import { System } from "@latticexyz/world/src/System.sol"; -import { Counter } from "../codegen/Tables.sol"; +import { Counter } from "../codegen/index.sol"; contract IncrementSystem is System { function increment() public returns (uint32) { diff --git a/templates/vanilla/packages/contracts/test/CounterTest.t.sol b/templates/vanilla/packages/contracts/test/CounterTest.t.sol index 5c16ef92af..efe11c5126 100644 --- a/templates/vanilla/packages/contracts/test/CounterTest.t.sol +++ b/templates/vanilla/packages/contracts/test/CounterTest.t.sol @@ -6,7 +6,7 @@ import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; import { getKeysWithValue } from "@latticexyz/world/src/modules/keyswithvalue/getKeysWithValue.sol"; import { IWorld } from "../src/codegen/world/IWorld.sol"; -import { Counter, CounterTableId } from "../src/codegen/Tables.sol"; +import { Counter, CounterTableId } from "../src/codegen/index.sol"; contract CounterTest is MudTest { IWorld public world; From 3b88c3aad43f14e002a05a6bd234dfc2c4747121 Mon Sep 17 00:00:00 2001 From: y77cao Date: Mon, 18 Sep 2023 09:27:46 -0400 Subject: [PATCH 17/17] clean up --- .../client-vanilla/src/mud/setupNetwork.ts | 17 ++++++++--------- e2e/packages/contracts/worlds.json | 2 +- e2e/packages/test-data/generate-test-data.ts | 1 + .../client-phaser/src/mud/setupNetwork.ts | 15 +++++++-------- .../client-react/src/mud/setupNetwork.ts | 15 +++++++-------- .../client-vanilla/src/mud/setupNetwork.ts | 15 +++++++-------- packages/common/src/createContract.ts | 7 ------- packages/common/src/hexToTableId.ts | 1 - .../packages/client/src/mud/setupNetwork.ts | 15 +++++++-------- .../packages/client/src/mud/setupNetwork.ts | 15 +++++++-------- .../packages/client/src/mud/setupNetwork.ts | 15 +++++++-------- .../packages/client/src/mud/setupNetwork.ts | 15 +++++++-------- 12 files changed, 59 insertions(+), 74 deletions(-) diff --git a/e2e/packages/client-vanilla/src/mud/setupNetwork.ts b/e2e/packages/client-vanilla/src/mud/setupNetwork.ts index ded161af44..a61b7cade7 100644 --- a/e2e/packages/client-vanilla/src/mud/setupNetwork.ts +++ b/e2e/packages/client-vanilla/src/mud/setupNetwork.ts @@ -26,15 +26,14 @@ export async function setupNetwork() { account: burnerAccount, }); - const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = - await syncToRecs({ - world, - config: mudConfig, - address: networkConfig.worldAddress as Hex, - publicClient, - startBlock: BigInt(networkConfig.initialBlockNumber), - indexerUrl: networkConfig.indexerUrl ?? undefined, - }); + const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = await syncToRecs({ + world, + config: mudConfig, + address: networkConfig.worldAddress as Hex, + publicClient, + startBlock: BigInt(networkConfig.initialBlockNumber), + indexerUrl: networkConfig.indexerUrl ?? undefined, + }); const worldContract = createContract({ address: networkConfig.worldAddress as Hex, diff --git a/e2e/packages/contracts/worlds.json b/e2e/packages/contracts/worlds.json index ca10c7ae59..a9623cfa62 100644 --- a/e2e/packages/contracts/worlds.json +++ b/e2e/packages/contracts/worlds.json @@ -2,4 +2,4 @@ "31337": { "address": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c" } -} +} \ No newline at end of file diff --git a/e2e/packages/test-data/generate-test-data.ts b/e2e/packages/test-data/generate-test-data.ts index 4b146a12c3..9f88a14894 100644 --- a/e2e/packages/test-data/generate-test-data.ts +++ b/e2e/packages/test-data/generate-test-data.ts @@ -68,6 +68,7 @@ const worldContract = createContract({ abi: IWorldAbi, publicClient, walletClient, + getResourceSelector: async (selector) => selector, }); console.log("calling set"); diff --git a/examples/minimal/packages/client-phaser/src/mud/setupNetwork.ts b/examples/minimal/packages/client-phaser/src/mud/setupNetwork.ts index 9f86e5ee94..3e5d0a90f5 100644 --- a/examples/minimal/packages/client-phaser/src/mud/setupNetwork.ts +++ b/examples/minimal/packages/client-phaser/src/mud/setupNetwork.ts @@ -29,14 +29,13 @@ export async function setupNetwork() { const write$ = new Subject(); - const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = - await syncToRecs({ - world, - config: mudConfig, - address: networkConfig.worldAddress as Hex, - publicClient, - startBlock: BigInt(networkConfig.initialBlockNumber), - }); + const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = await syncToRecs({ + world, + config: mudConfig, + address: networkConfig.worldAddress as Hex, + publicClient, + startBlock: BigInt(networkConfig.initialBlockNumber), + }); const worldContract = createContract({ address: networkConfig.worldAddress as Hex, diff --git a/examples/minimal/packages/client-react/src/mud/setupNetwork.ts b/examples/minimal/packages/client-react/src/mud/setupNetwork.ts index f38e499278..4143016fc6 100644 --- a/examples/minimal/packages/client-react/src/mud/setupNetwork.ts +++ b/examples/minimal/packages/client-react/src/mud/setupNetwork.ts @@ -30,14 +30,13 @@ export async function setupNetwork() { const write$ = new Subject(); - const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = - await syncToRecs({ - world, - config: mudConfig, - address: networkConfig.worldAddress as Hex, - publicClient, - startBlock: BigInt(networkConfig.initialBlockNumber), - }); + const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = await syncToRecs({ + world, + config: mudConfig, + address: networkConfig.worldAddress as Hex, + publicClient, + startBlock: BigInt(networkConfig.initialBlockNumber), + }); const worldContract = createContract({ address: networkConfig.worldAddress as Hex, diff --git a/examples/minimal/packages/client-vanilla/src/mud/setupNetwork.ts b/examples/minimal/packages/client-vanilla/src/mud/setupNetwork.ts index 9f86e5ee94..3e5d0a90f5 100644 --- a/examples/minimal/packages/client-vanilla/src/mud/setupNetwork.ts +++ b/examples/minimal/packages/client-vanilla/src/mud/setupNetwork.ts @@ -29,14 +29,13 @@ export async function setupNetwork() { const write$ = new Subject(); - const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = - await syncToRecs({ - world, - config: mudConfig, - address: networkConfig.worldAddress as Hex, - publicClient, - startBlock: BigInt(networkConfig.initialBlockNumber), - }); + const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = await syncToRecs({ + world, + config: mudConfig, + address: networkConfig.worldAddress as Hex, + publicClient, + startBlock: BigInt(networkConfig.initialBlockNumber), + }); const worldContract = createContract({ address: networkConfig.worldAddress as Hex, diff --git a/packages/common/src/createContract.ts b/packages/common/src/createContract.ts index 3b30d1e559..3a49aabfde 100644 --- a/packages/common/src/createContract.ts +++ b/packages/common/src/createContract.ts @@ -173,13 +173,6 @@ export function createContract< ...options, }; const resourceSelector = await getResourceSelector(functionSelector); - - console.log({ - functionName, - functionSignature: JSON.stringify(functionSignature), - functionSelector, - resourceSelector, - }); const shouldUseCallFrom = resourceSelector && resourceSelector !== staticAbiTypeToDefaultValue.bytes32; // if the function is not part of the world contract and needs to be routed diff --git a/packages/common/src/hexToTableId.ts b/packages/common/src/hexToTableId.ts index 12c695f070..8782630888 100644 --- a/packages/common/src/hexToTableId.ts +++ b/packages/common/src/hexToTableId.ts @@ -3,6 +3,5 @@ import { Hex, hexToString, sliceHex } from "viem"; export function hexToTableId(hex: Hex): { namespace: string; name: string } { const namespace = hexToString(sliceHex(hex, 0, 16)).replace(/\0+$/, ""); const name = hexToString(sliceHex(hex, 16, 32)).replace(/\0+$/, ""); - return { namespace, name }; } diff --git a/templates/phaser/packages/client/src/mud/setupNetwork.ts b/templates/phaser/packages/client/src/mud/setupNetwork.ts index 12fc4e4590..ebabf85d13 100644 --- a/templates/phaser/packages/client/src/mud/setupNetwork.ts +++ b/templates/phaser/packages/client/src/mud/setupNetwork.ts @@ -61,14 +61,13 @@ export async function setupNetwork() { * to the viem publicClient to make RPC calls to fetch MUD * events from the chain. */ - const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = - await syncToRecs({ - world, - config: mudConfig, - address: networkConfig.worldAddress as Hex, - publicClient, - startBlock: BigInt(networkConfig.initialBlockNumber), - }); + const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = await syncToRecs({ + world, + config: mudConfig, + address: networkConfig.worldAddress as Hex, + publicClient, + startBlock: BigInt(networkConfig.initialBlockNumber), + }); /* * Create an object for communicating with the deployed World. diff --git a/templates/react/packages/client/src/mud/setupNetwork.ts b/templates/react/packages/client/src/mud/setupNetwork.ts index e5be1b4fe3..59f5663277 100644 --- a/templates/react/packages/client/src/mud/setupNetwork.ts +++ b/templates/react/packages/client/src/mud/setupNetwork.ts @@ -63,14 +63,13 @@ export async function setupNetwork() { * to the viem publicClient to make RPC calls to fetch MUD * events from the chain. */ - const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = - await syncToRecs({ - world, - config: mudConfig, - address: networkConfig.worldAddress as Hex, - publicClient, - startBlock: BigInt(networkConfig.initialBlockNumber), - }); + const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = await syncToRecs({ + world, + config: mudConfig, + address: networkConfig.worldAddress as Hex, + publicClient, + startBlock: BigInt(networkConfig.initialBlockNumber), + }); /* * Create an object for communicating with the deployed World. diff --git a/templates/threejs/packages/client/src/mud/setupNetwork.ts b/templates/threejs/packages/client/src/mud/setupNetwork.ts index e6839dc797..188beffcd2 100644 --- a/templates/threejs/packages/client/src/mud/setupNetwork.ts +++ b/templates/threejs/packages/client/src/mud/setupNetwork.ts @@ -61,14 +61,13 @@ export async function setupNetwork() { * to the viem publicClient to make RPC calls to fetch MUD * events from the chain. */ - const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = - await syncToRecs({ - world, - config: mudConfig, - address: networkConfig.worldAddress as Hex, - publicClient, - startBlock: BigInt(networkConfig.initialBlockNumber), - }); + const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = await syncToRecs({ + world, + config: mudConfig, + address: networkConfig.worldAddress as Hex, + publicClient, + startBlock: BigInt(networkConfig.initialBlockNumber), + }); /* * Create an object for communicating with the deployed World. diff --git a/templates/vanilla/packages/client/src/mud/setupNetwork.ts b/templates/vanilla/packages/client/src/mud/setupNetwork.ts index e5be1b4fe3..59f5663277 100644 --- a/templates/vanilla/packages/client/src/mud/setupNetwork.ts +++ b/templates/vanilla/packages/client/src/mud/setupNetwork.ts @@ -63,14 +63,13 @@ export async function setupNetwork() { * to the viem publicClient to make RPC calls to fetch MUD * events from the chain. */ - const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = - await syncToRecs({ - world, - config: mudConfig, - address: networkConfig.worldAddress as Hex, - publicClient, - startBlock: BigInt(networkConfig.initialBlockNumber), - }); + const { components, latestBlock$, storedBlockLogs$, waitForTransaction, getResourceSelector } = await syncToRecs({ + world, + config: mudConfig, + address: networkConfig.worldAddress as Hex, + publicClient, + startBlock: BigInt(networkConfig.initialBlockNumber), + }); /* * Create an object for communicating with the deployed World.