From 05e2b8ac2f76ee7e25e6919de87d2740f6601df1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 25 Sep 2023 01:35:06 +0000 Subject: [PATCH] Version Packages (next) --- .changeset/pre.json | 73 +- CHANGELOG.md | 1119 ++++++++++++++++++++++ docs/pages/changelog.mdx | 1119 ++++++++++++++++++++++ packages/abi-ts/CHANGELOG.md | 2 + packages/abi-ts/package.json | 2 +- packages/block-logs-stream/CHANGELOG.md | 239 +++++ packages/block-logs-stream/package.json | 2 +- packages/cli/CHANGELOG.md | 411 ++++++++ packages/cli/package.json | 2 +- packages/common/CHANGELOG.md | 246 +++++ packages/common/package.json | 2 +- packages/config/CHANGELOG.md | 74 ++ packages/config/package.json | 2 +- packages/create-mud/CHANGELOG.md | 199 ++++ packages/create-mud/package.json | 2 +- packages/dev-tools/CHANGELOG.md | 193 ++++ packages/dev-tools/package.json | 14 +- packages/ecs-browser/CHANGELOG.md | 2 + packages/ecs-browser/package.json | 2 +- packages/faucet/CHANGELOG.md | 31 + packages/faucet/package.json | 2 +- packages/gas-report/CHANGELOG.md | 6 + packages/gas-report/package.json | 2 +- packages/network/CHANGELOG.md | 2 + packages/network/package.json | 2 +- packages/noise/CHANGELOG.md | 6 + packages/noise/package.json | 2 +- packages/phaserx/CHANGELOG.md | 7 + packages/phaserx/package.json | 2 +- packages/protocol-parser/CHANGELOG.md | 58 ++ packages/protocol-parser/package.json | 2 +- packages/react/CHANGELOG.md | 8 + packages/react/package.json | 2 +- packages/recs/CHANGELOG.md | 8 + packages/recs/package.json | 2 +- packages/schema-type/CHANGELOG.md | 6 + packages/schema-type/package.json | 2 +- packages/services/CHANGELOG.md | 2 + packages/services/package.json | 2 +- packages/solecs/CHANGELOG.md | 2 + packages/solecs/package.json | 2 +- packages/solhint-config-mud/CHANGELOG.md | 2 + packages/solhint-config-mud/package.json | 2 +- packages/solhint-plugin-mud/CHANGELOG.md | 2 + packages/solhint-plugin-mud/package.json | 2 +- packages/std-client/CHANGELOG.md | 2 + packages/std-client/package.json | 2 +- packages/std-contracts/CHANGELOG.md | 2 + packages/std-contracts/package.json | 2 +- packages/store-cache/CHANGELOG.md | 2 + packages/store-cache/package.json | 2 +- packages/store-indexer/CHANGELOG.md | 40 + packages/store-indexer/package.json | 2 +- packages/store-sync/CHANGELOG.md | 273 ++++++ packages/store-sync/package.json | 2 +- packages/store/CHANGELOG.md | 715 ++++++++++++++ packages/store/package.json | 2 +- packages/utils/CHANGELOG.md | 2 + packages/utils/package.json | 2 +- packages/world-modules/CHANGELOG.md | 26 + packages/world-modules/package.json | 2 +- packages/world/CHANGELOG.md | 626 ++++++++++++ packages/world/package.json | 2 +- 63 files changed, 5540 insertions(+), 37 deletions(-) create mode 100644 packages/faucet/CHANGELOG.md diff --git a/.changeset/pre.json b/.changeset/pre.json index 0f93d8380b..27b4cca4d0 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -29,38 +29,61 @@ "@latticexyz/store-sync": "1.42.0", "@latticexyz/utils": "1.42.0", "@latticexyz/world": "1.42.0", - "@latticexyz/abi-ts": "2.0.0-next.5" + "@latticexyz/abi-ts": "2.0.0-next.5", + "@latticexyz/faucet": "2.0.0-next.8", + "@latticexyz/world-modules": "2.0.0-next.8" }, "changesets": [ "afraid-hotels-bathe", "beige-radios-drop", "big-goats-prove", + "blue-seals-relate", "brave-needles-love", "brave-rings-tickle", + "brown-garlics-lie", "brown-icons-burn", "chilled-chicken-repair", + "chilled-cougars-smash", + "chilled-kangaroos-dream", + "clever-items-appear", "clever-rats-sip", + "cold-years-itch", "cool-snakes-reply", + "curly-countries-obey", + "curvy-tables-melt", + "cyan-hats-try", "dirty-items-retire", "dry-chicken-love", + "eighty-pots-report", "eighty-tigers-argue", "empty-planes-kiss", "fast-ears-hug", "fast-zebras-drum", + "fast-zebras-promise", + "few-jars-turn", "few-mirrors-reflect", + "few-papayas-leave", "fifty-squids-eat", "fifty-suits-shout", "flat-trainers-marry", "fluffy-moles-march", "four-coats-pull", + "fresh-scissors-unite", "funny-paws-admire", "fuzzy-cars-stare", "giant-masks-carry", "great-cooks-dream", + "grumpy-files-heal", "grumpy-geckos-raise", + "hip-tables-check", + "honest-months-boil", + "hot-mice-play", + "hungry-rings-doubt", "itchy-kids-relax", "itchy-shoes-appear", "khaki-doors-refuse", + "khaki-houses-whisper", + "large-drinks-sell", "large-hats-walk", "large-sloths-camp", "late-geese-guess", @@ -68,58 +91,106 @@ "lazy-ladybugs-return", "little-ravens-yawn", "long-lizards-admire", + "lovely-buses-boil", + "lovely-fireants-behave", "many-phones-study", + "many-pumpkins-cry", + "mean-islands-brake", "mean-pans-study", + "mean-seals-nail", "metal-cats-double", + "metal-hounds-drum", "metal-wombats-judge", "mighty-eels-type", "modern-bikes-build", "modern-hornets-jam", + "modern-trains-remain", + "nasty-trains-drop", "nasty-waves-divide", "nervous-walls-knock", + "nice-fishes-perform", + "nice-glasses-begin", "nice-moose-love", "nice-pandas-knock", "olive-parrots-move", + "olive-pigs-fold", "perfect-mangos-cry", + "pink-buses-look", "pink-fans-nail", "pink-horses-deny", "pink-tips-give", + "popular-coins-invent", "pretty-hotels-drop", + "proud-insects-perform", "quick-numbers-flash", + "quiet-dancers-prove", "quiet-squids-share", + "rare-lizards-sleep", "rare-planes-draw", "rare-trainers-fry", + "real-ducks-hope", + "real-students-exercise", + "red-falcons-do", "red-turkeys-develop", + "rotten-cats-lay", "selfish-cycles-retire", + "serious-ads-trade", + "serious-plants-itch", "seven-flies-chew", + "seven-mangos-roll", "sharp-worms-kneel", "short-ads-jog", + "short-dragons-shout", + "shy-monkeys-wonder", + "shy-sheep-wait", + "silent-rice-argue", + "silly-snakes-fold", "silver-mangos-thank", "six-cats-agree", + "small-boxes-rush", + "small-chicken-repair", "smooth-elephants-wave", "smooth-pots-nail", "soft-boxes-smile", "soft-dryers-invite", + "soft-fans-wink", + "sour-cycles-warn", "spicy-bees-teach", "spotty-cups-destroy", "spotty-sheep-warn", "stale-cooks-reflect", + "stale-schools-wait", + "stale-seahorses-pay", + "stale-worms-hunt", "strange-candles-shout", "strange-ducks-float", "strong-geckos-shake", + "strong-months-push", + "sweet-kiwis-unite", + "tall-buses-kick", "tame-lemons-play", "thin-buses-reply", + "thin-chairs-compare", + "thin-rice-trade", + "thin-terms-lay", + "tough-flowers-breathe", + "tricky-beds-kiss", "tricky-carrots-talk", "tricky-comics-remain", "tricky-frogs-beam", "tricky-kangaroos-love", "tricky-olives-stare", "tricky-oranges-pump", + "twelve-monkeys-juggle", "twenty-birds-scream", + "unlucky-cups-fetch", "unlucky-guests-cover", + "violet-insects-press", "weak-mails-cross", + "wicked-squids-do", "wicked-tigers-return", "wild-gorillas-care", + "wild-nails-wonder", "witty-jokes-serve", "witty-tigers-rest" ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 59dcc2257f..0448fc0b20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,1122 @@ +## Version 2.0.0-next.9 + +### Major changes + +**[feat(world): prevent the `World` from calling itself (#1563)](https://github.com/latticexyz/mud/commit/748f4588a218928bca041760448c26991c0d8033)** (@latticexyz/world) + +All `World` methods now revert if the `World` calls itself. +The `World` should never need to externally call itself, since all internal table operations happen via library calls, and all root system operations happen via delegate call. + +It should not be possible to make the `World` call itself as an external actor. +If it were possible to make the `World` call itself, it would be possible to write to internal tables that only the `World` should have access to. +As this is a very important invariance, we made it explicit in a requirement check in every `World` method, rather than just relying on making it impossible to trigger the `World` to call itself. + +This is a breaking change for modules that previously used external calls to the `World` in the `installRoot` method. +In the `installRoot` method, the `World` can only be called via `delegatecall`, and table operations should be performed via the internal table methods (e.g. `_set` instead of `set`). + +Example for how to replace external calls to `world` in root systems / root modules (`installRoot`) with `delegatecall`: + +```diff ++ import { revertWithBytes } from "@latticexyz/world/src/revertWithBytes.sol"; + +- world.grantAccess(tableId, address(hook)); ++ (bool success, bytes memory returnData) = address(world).delegatecall( ++ abi.encodeCall(world.grantAccess, (tableId, address(hook))) ++ ); + ++ if (!success) revertWithBytes(returnData); +``` + +**[feat: rename schema to valueSchema (#1482)](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9)** (@latticexyz/cli, @latticexyz/protocol-parser, @latticexyz/store-sync, @latticexyz/store, create-mud) + +Renamed all occurrences of `schema` where it is used as "value schema" to `valueSchema` to clearly distinguish it from "key schema". +The only breaking change for users is the change from `schema` to `valueSchema` in `mud.config.ts`. + +```diff +// mud.config.ts +export default mudConfig({ + tables: { + CounterTable: { + keySchema: {}, +- schema: { ++ valueSchema: { + value: "uint32", + }, + }, + } +} +``` + +**[refactor(world): move codegen files (#1592)](https://github.com/latticexyz/mud/commit/c07fa021501ff92be35c0491dd89bbb8161e1c07)** (@latticexyz/cli, @latticexyz/world-modules, @latticexyz/world) + +Tables and interfaces in the `world` package are now generated to the `codegen` folder. +This is only a breaking change if you imported tables or codegenerated interfaces from `@latticexyz/world` directly. +If you're using the MUD CLI, the changed import paths are already integrated and no further changes are necessary. + +```diff +- import { IBaseWorld } from "@latticexyz/world/src/interfaces/IBaseWorld.sol"; ++ import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol"; + +``` + +**[refactor(store): always render field methods with suffix and conditionally without (#1550)](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e)** (@latticexyz/common) + +- Add `renderWithFieldSuffix` helper method to always render a field function with a suffix, and optionally render the same function without a suffix. +- Remove `methodNameSuffix` from `RenderField` interface, because the suffix is now computed as part of `renderWithFieldSuffix`. + +**[feat(store,): add splice events (#1354)](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853)** (@latticexyz/store, @latticexyz/world) + +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. + +**[refactor(store): change argument order on `Store_SpliceDynamicData` and hooks for consistency (#1589)](https://github.com/latticexyz/mud/commit/f9f9609ef69d7fa58cad6a9af3fe6d2eed6d8aa2)** (@latticexyz/store) + +The argument order on `Store_SpliceDynamicData`, `onBeforeSpliceDynamicData` and `onAfterSpliceDynamicData` has been changed to match the argument order on `Store_SetRecord`, +where the `PackedCounter encodedLength` field comes before the `bytes dynamicData` field. + +```diff +IStore { + event Store_SpliceDynamicData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, ++ PackedCounter encodedLengths, + bytes data, +- PackedCounter encodedLengths + ); +} + +IStoreHook { + function onBeforeSpliceDynamicData( + ResourceId tableId, + bytes32[] memory keyTuple, + uint8 dynamicFieldIndex, + uint40 startWithinField, + uint40 deleteCount, ++ PackedCounter encodedLengths, + bytes memory data, +- PackedCounter encodedLengths + ) external; + + function onAfterSpliceDynamicData( + ResourceId tableId, + bytes32[] memory keyTuple, + uint8 dynamicFieldIndex, + uint40 startWithinField, + uint40 deleteCount, ++ PackedCounter encodedLengths, + bytes memory data, +- PackedCounter encodedLengths + ) external; +} +``` + +**[feat(store,): add splice events (#1354)](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853)** (@latticexyz/common, @latticexyz/protocol-parser) + +`readHex` was moved from `@latticexyz/protocol-parser` to `@latticexyz/common` + +**[feat(store,world): move hooks to bit flags (#1527)](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8)** (@latticexyz/store, @latticexyz/world) + +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 + ); + +``` + +**[feat(store,world): add splice hooks, expose spliceStaticData, spliceDynamicData (#1531)](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4)** (@latticexyz/store, @latticexyz/world) + +- The `IStoreHook` interface was changed to replace `onBeforeSetField` and `onAfterSetField` with `onBeforeSpliceStaticData`, `onAfterSpliceStaticData`, `onBeforeSpliceDynamicData` and `onAfterSpliceDynamicData`. + + This new interface matches the new `StoreSpliceStaticData` and `StoreSpliceDynamicData` events, and avoids having to read the entire field from storage when only a subset of the field was updated + (e.g. when pushing elements to a field). + + ```diff + interface IStoreHook { + - function onBeforeSetField( + - bytes32 tableId, + - bytes32[] memory keyTuple, + - uint8 fieldIndex, + - bytes memory data, + - FieldLayout fieldLayout + - ) external; + + - function onAfterSetField( + - bytes32 tableId, + - bytes32[] memory keyTuple, + - uint8 fieldIndex, + - bytes memory data, + - FieldLayout fieldLayout + - ) external; + + + function onBeforeSpliceStaticData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint48 start, + + uint40 deleteCount, + + bytes memory data + + ) external; + + + function onAfterSpliceStaticData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint48 start, + + uint40 deleteCount, + + bytes memory data + + ) external; + + + function onBeforeSpliceDynamicData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex, + + uint40 startWithinField, + + uint40 deleteCount, + + bytes memory data, + + PackedCounter encodedLengths + + ) external; + + + function onAfterSpliceDynamicData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex, + + uint40 startWithinField, + + uint40 deleteCount, + + bytes memory data, + + PackedCounter encodedLengths + + ) external; + } + ``` + +- All `calldata` parameters on the `IStoreHook` interface were changed to `memory`, since the functions are called with `memory` from the `World`. + +- `IStore` exposes two new functions: `spliceStaticData` and `spliceDynamicData`. + + These functions provide lower level access to the operations happening under the hood in `setField`, `pushToField`, `popFromField` and `updateInField` and simplify handling + the new splice hooks. + + `StoreCore`'s internal logic was simplified to use the `spliceStaticData` and `spliceDynamicData` functions instead of duplicating similar logic in different functions. + + ```solidity + interface IStore { + // Splice data in the static part of the record + function spliceStaticData( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint48 start, + uint40 deleteCount, + bytes calldata data + ) external; + + // Splice data in the dynamic part of the record + function spliceDynamicData( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint8 dynamicFieldIndex, + uint40 startWithinField, + uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + +**[feat: replace Schema with FieldLayout for contract internals (#1336)](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e)** (@latticexyz/cli, @latticexyz/protocol-parser, @latticexyz/store, @latticexyz/world) + +- Add `FieldLayout`, which is a `bytes32` user-type similar to `Schema`. + + Both `FieldLayout` and `Schema` have the same kind of data in the first 4 bytes. + + - 2 bytes for total length of all static fields + - 1 byte for number of static size fields + - 1 byte for number of dynamic size fields + + But whereas `Schema` has `SchemaType` enum in each of the other 28 bytes, `FieldLayout` has static byte lengths in each of the other 28 bytes. + +- Replace `Schema valueSchema` with `FieldLayout fieldLayout` in Store and World contracts. + + `FieldLayout` is more gas-efficient because it already has lengths, and `Schema` has types which need to be converted to lengths. + +- Add `getFieldLayout` to `IStore` interface. + + There is no `FieldLayout` for keys, only for values, because key byte lengths aren't usually relevant on-chain. You can still use `getKeySchema` if you need key types. + +- Add `fieldLayoutToHex` utility to `protocol-parser` package. + +- Add `constants.sol` for constants shared between `FieldLayout`, `Schema` and `PackedCounter`. + +**[refactor: separate data into staticData, encodedLengths, dynamicData in getRecord (#1532)](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623)** (@latticexyz/store, @latticexyz/world) + +Store's `getRecord` has been updated to return `staticData`, `encodedLengths`, and `dynamicData` instead of a single `data` blob, to match the new behaviour of Store setter methods. + +If you use codegenerated libraries, you will only need to update `encode` calls. + +```diff +- bytes memory data = Position.encode(x, y); ++ (bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData) = Position.encode(x, y); +``` + +**[feat(world): add `FunctionSignatures` offchain table (#1575)](https://github.com/latticexyz/mud/commit/e5d208e40b2b2fae223b48716ce3f62c530ea1ca)** (@latticexyz/cli, @latticexyz/world) + +The `registerRootFunctionSelector` function's signature was changed to accept a `string functionSignature` parameter instead of a `bytes4 functionSelector` parameter. +This change enables the `World` to store the function signatures of all registered functions in a `FunctionSignatures` offchain table, which will allow for the automatic generation of interfaces for a given `World` address in the future. + +```diff +IBaseWorld { + function registerRootFunctionSelector( + ResourceId systemId, +- bytes4 worldFunctionSelector, ++ string memory worldFunctionSignature, + bytes4 systemFunctionSelector + ) external returns (bytes4 worldFunctionSelector); +} +``` + +**[feat: move forge build + abi + abi-ts to out (#1483)](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab)** (@latticexyz/store, @latticexyz/world) + +Store and World contract ABIs are now exported from the `out` directory. You'll need to update your imports like: + +```diff +- import IBaseWorldAbi from "@latticexyz/world/abi/IBaseWorld.sol/IBaseWorldAbi.json"; ++ import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorldAbi.json"; +``` + +`MudTest.sol` was also moved to the World package. You can update your import like: + +```diff +- import { MudTest } from "@latticexyz/store/src/MudTest.sol"; ++ import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; +``` + +**[feat(common,store): add support for user-defined types (#1566)](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9)** (@latticexyz/store) + +These breaking changes only affect store utilities, you aren't affected if you use `@latticexyz/cli` codegen scripts. + +- Add `remappings` argument to the `tablegen` codegen function, so that it can read user-provided files. +- In `RenderTableOptions` change the type of `imports` from `RelativeImportDatum` to `ImportDatum`, to allow passing absolute imports to the table renderer. +- Add `solidityUserTypes` argument to several functions that need to resolve user or abi types: `resolveAbiOrUserType`, `importForAbiOrUserType`, `getUserTypeInfo`. +- Add `userTypes` config option to MUD config, which takes user types mapped to file paths from which to import them. + +**[refactor(store): always render field methods with suffix and conditionally without (#1550)](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e)** (@latticexyz/store) + +- Always render field methods with a suffix in tablegen (they used to not be rendered if field methods without a suffix were rendered). +- Add `withSuffixlessFieldMethods` to `RenderTableOptions`, which indicates that field methods without a suffix should be rendered. + +**[feat(world): change registerFunctionSelector signature to accept system signature as a single string (#1574)](https://github.com/latticexyz/mud/commit/31ffc9d5d0a6d030cc61349f0f8fbcf6748ebc48)** (@latticexyz/cli, @latticexyz/world) + +The `registerFunctionSelector` function now accepts a single `functionSignature` string paramemer instead of separating function name and function arguments into separate parameters. + +```diff +IBaseWorld { + function registerFunctionSelector( + ResourceId systemId, +- string memory systemFunctionName, +- string memory systemFunctionArguments ++ string memory systemFunctionSignature + ) external returns (bytes4 worldFunctionSelector); +} +``` + +This is a breaking change if you were manually registering function selectors, e.g. in a `PostDeploy.s.sol` script or a module. +To upgrade, simply replace the separate `systemFunctionName` and `systemFunctionArguments` parameters with a single `systemFunctionSignature` parameter. + +```diff + world.registerFunctionSelector( + systemId, +- systemFunctionName, +- systemFunctionArguments, ++ string(abi.encodePacked(systemFunctionName, systemFunctionArguments)) + ); +``` + +**[feat(store,world): replace `ResourceSelector` with `ResourceId` and `WorldResourceId` (#1544)](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae)** (@latticexyz/world) + +All `World` methods acting on namespaces as resources have been updated to use `ResourceId namespaceId` as parameter instead of `bytes14 namespace`. +The reason for this change is to make it clearer when a namespace is used as resource, as opposed to being part of another resource's ID. + +```diff ++ import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + +IBaseWorld { +- function registerNamespace(bytes14 namespace) external; ++ function registerNamespace(ResourceId namespaceId) external; + +- function transferOwnership(bytes14 namespace, address newOwner) external; ++ function transferOwnership(ResourceId namespaceId, address newOwner) external; + +- function transferBalanceToNamespace(bytes14 fromNamespace, bytes14 toNamespace, uint256 amount) external; ++ function transferBalanceToNamespace(ResourceId fromNamespaceId, ResourceId toNamespaceId, uint256 amount) external; + +- function transferBalanceToAddress(bytes14 fromNamespace, address toAddress, uint256 amount) external; ++ function transferBalanceToAddress(ResourceId fromNamespaceId, address toAddress, uint256 amount) external; +} + +``` + +**[feat: bump solidity to 0.8.21 (#1473)](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a)** (@latticexyz/cli, @latticexyz/common, @latticexyz/gas-report, @latticexyz/noise, @latticexyz/schema-type, @latticexyz/store, @latticexyz/world, create-mud) + +Bump Solidity version to 0.8.21 + +**[feat(world): add `batchCallFrom` (#1594)](https://github.com/latticexyz/mud/commit/5741d53d0a39990a0d7b2842f1f012973655e060)** (@latticexyz/world) + +- `IBaseWorld` now has a `batchCallFrom` method, which allows system calls via `callFrom` to be executed in batch. + +```solidity +import { SystemCallFromData } from "@latticexyz/world/modules/core/types.sol"; + +interface IBaseWorld { + function batchCallFrom(SystemCallFromData[] calldata systemCalls) external returns (bytes[] memory returnDatas); +} +``` + +- The `callBatch` method of `IBaseWorld` has been renamed to `batchCall` to align better with the `batchCallFrom` method. + +```diff +interface IBaseWorld { +- function callBatch(SystemCallData[] calldata systemCalls) external returns (bytes[] memory returnDatas); ++ function batchCall(SystemCallData[] calldata systemCalls) external returns (bytes[] memory returnDatas); +} +``` + +**[feat(store): codegen index and common files (#1318)](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130)** (@latticexyz/cli, @latticexyz/store, create-mud) + +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"; +``` + +**[feat(store,): add splice events (#1354)](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853)** (@latticexyz/dev-tools, @latticexyz/store-sync, create-mud) + +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. + +**[feat(store,world): replace `ephemeral` tables with `offchain` tables (#1558)](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f)** (@latticexyz/block-logs-stream, @latticexyz/cli, @latticexyz/common, @latticexyz/dev-tools, @latticexyz/store-sync, @latticexyz/store, create-mud) + +What used to be known as `ephemeral` table is now called `offchain` table. +The previous `ephemeral` tables only supported an `emitEphemeral` method, which emitted a `StoreSetEphemeralRecord` event. + +Now `offchain` tables support all regular table methods, except partial operations on dynamic fields (`push`, `pop`, `update`). +Unlike regular tables they don't store data on-chain but emit the same events as regular tables (`StoreSetRecord`, `StoreSpliceStaticData`, `StoreDeleteRecord`), so their data can be indexed by offchain indexers/clients. + +```diff +- EphemeralTable.emitEphemeral(value); ++ OffchainTable.set(value); +``` + +**[feat(store): rename events for readability and consistency with errors (#1577)](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c)** (@latticexyz/block-logs-stream, @latticexyz/dev-tools, @latticexyz/store-sync, @latticexyz/store) + +`Store` events have been renamed for consistency and readability. +If you're parsing `Store` events manually, you need to update your ABI. +If you're using the MUD sync stack, the new events are already integrated and no further changes are necessary. + +```diff +- event StoreSetRecord( ++ event Store_SetRecord( + ResourceId indexed tableId, + bytes32[] keyTuple, + bytes staticData, + bytes32 encodedLengths, + bytes dynamicData + ); +- event StoreSpliceStaticData( ++ event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data + ); +- event StoreSpliceDynamicData( ++ event Store_SpliceDynamicData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data, + bytes32 encodedLengths + ); +- event StoreDeleteRecord( ++ event Store_DeleteRecord( + ResourceId indexed tableId, + bytes32[] keyTuple + ); +``` + +**[feat(store,world): replace `ResourceSelector` with `ResourceId` and `WorldResourceId` (#1544)](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae)** (@latticexyz/cli, @latticexyz/common, @latticexyz/config, @latticexyz/store) + +- `ResourceSelector` is replaced with `ResourceId`, `ResourceIdLib`, `ResourceIdInstance`, `WorldResourceIdLib` and `WorldResourceIdInstance`. + + Previously a "resource selector" was a `bytes32` value with the first 16 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + Now a "resource ID" is a `bytes32` value with the first 2 bytes reserved for the resource type, the next 14 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + + Previously `ResouceSelector` was a library and the resource selector type was a plain `bytes32`. + Now `ResourceId` is a user type, and the functionality is implemented in the `ResourceIdInstance` (for type) and `WorldResourceIdInstance` (for namespace and name) libraries. + We split the logic into two libraries, because `Store` now also uses `ResourceId` and needs to be aware of resource types, but not of namespaces/names. + + ```diff + - import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol"; + + import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; + + import { WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol"; + + import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol"; + + - bytes32 systemId = ResourceSelector.from("namespace", "name"); + + ResourceId systemId = WorldResourceIdLib.encode(RESOURCE_SYSTEM, "namespace", "name"); + + - using ResourceSelector for bytes32; + + using WorldResourceIdInstance for ResourceId; + + using ResourceIdInstance for ResourceId; + + systemId.getName(); + systemId.getNamespace(); + + systemId.getType(); + + ``` + +- All `Store` and `World` methods now use the `ResourceId` type for `tableId`, `systemId`, `moduleId` and `namespaceId`. + All mentions of `resourceSelector` were renamed to `resourceId` or the more specific type (e.g. `tableId`, `systemId`) + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IStore { + function setRecord( + - bytes32 tableId, + + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + FieldLayout fieldLayout + ) external; + + // Same for all other methods + } + ``` + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IBaseWorld { + function callFrom( + address delegator, + - bytes32 resourceSelector, + + ResourceId systemId, + bytes memory callData + ) external payable returns (bytes memory); + + // Same for all other methods + } + ``` + +**[feat(store): indexed `tableId` in store events (#1520)](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380)** (@latticexyz/store) + +Store events now use an `indexed` `tableId`. This adds ~100 gas per write, but means we our sync stack can filter events by table. + +**[feat(world,store): add initialize method, initialize core tables in core module (#1472)](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf)** (@latticexyz/store) + +- `StoreCore`'s `initialize` function is split into `initialize` (to set the `StoreSwitch`'s `storeAddress`) and `registerCoreTables` (to register the `Tables` and `StoreHooks` tables). + The purpose of this is to give consumers more granular control over the setup flow. + +- The `StoreRead` contract no longer calls `StoreCore.initialize` in its constructor. + `StoreCore` consumers are expected to call `StoreCore.initialize` and `StoreCore.registerCoreTable` in their own setup logic. + +**[feat(store): add `internalType` property to user types config for type inference (#1587)](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d)** (@latticexyz/cli, @latticexyz/common, @latticexyz/store) + +Changed the `userTypes` property to accept `{ filePath: string, internalType: SchemaAbiType }` to enable strong type inference from the config. + +**[refactor(world,world-modules): move optional modules from `world` to `world-modules` package (#1591)](https://github.com/latticexyz/mud/commit/251170e1ef0b07466c597ea84df0cb49de7d6a23)** (@latticexyz/cli, @latticexyz/world, @latticexyz/world-modules) + +All optional modules have been moved from `@latticexyz/world` to `@latticexyz/world-modules`. +If you're using the MUD CLI, the import is already updated and no changes are necessary. + +**[feat(store,world): polish store methods (#1581)](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b)** (@latticexyz/block-logs-stream, @latticexyz/cli, @latticexyz/common, @latticexyz/dev-tools, @latticexyz/store-sync, @latticexyz/store, @latticexyz/world, create-mud) + +- The external `setRecord` and `deleteRecord` methods of `IStore` no longer accept a `FieldLayout` as input, but load it from storage instead. + This is to prevent invalid `FieldLayout` values being passed, which could cause the onchain state to diverge from the indexer state. + However, the internal `StoreCore` library still exposes a `setRecord` and `deleteRecord` method that allows a `FieldLayout` to be passed. + This is because `StoreCore` can only be used internally, so the `FieldLayout` value can be trusted and we can save the gas for accessing storage. + + ```diff + interface IStore { + function setRecord( + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + - FieldLayout fieldLayout + ) external; + + function deleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + - FieldLayout fieldLayout + ) external; + } + ``` + +- The `spliceStaticData` method and `Store_SpliceStaticData` event of `IStore` and `StoreCore` no longer include `deleteCount` in their signature. + This is because when splicing static data, the data after `start` is always overwritten with `data` instead of being shifted, so `deleteCount` is always the length of the data to be written. + + ```diff + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + - uint40 deleteCount, + bytes data + ); + + interface IStore { + function spliceStaticData( + ResourceId tableId, + bytes32[] calldata keyTuple, + uint48 start, + - uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + +- The `updateInField` method has been removed from `IStore`, as it's almost identical to the more general `spliceDynamicData`. + If you're manually calling `updateInField`, here is how to upgrade to `spliceDynamicData`: + + ```diff + - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); + + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields(); + + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet); + ``` + +- All other methods that are only valid for dynamic fields (`pushToField`, `popFromField`, `getFieldSlice`) + have been renamed to make this more explicit (`pushToDynamicField`, `popFromDynamicField`, `getDynamicFieldSlice`). + + Their `fieldIndex` parameter has been replaced by a `dynamicFieldIndex` parameter, which is the index relative to the first dynamic field (i.e. `dynamicFieldIndex` = `fieldIndex` - `numStaticFields`). + The `FieldLayout` parameter has been removed, as it was only used to calculate the `dynamicFieldIndex` in the method. + + ```diff + interface IStore { + - function pushToField( + + function pushToDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + bytes calldata dataToPush, + - FieldLayout fieldLayout + ) external; + + - function popFromField( + + function popFromDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + uint256 byteLengthToPop, + - FieldLayout fieldLayout + ) external; + + - function getFieldSlice( + + function getDynamicFieldSlice( + ResourceId tableId, + bytes32[] memory keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + - FieldLayout fieldLayout, + uint256 start, + uint256 end + ) external view returns (bytes memory data); + } + ``` + +- `IStore` has a new `getDynamicFieldLength` length method, which returns the byte length of the given dynamic field and doesn't require the `FieldLayout`. + + ```diff + IStore { + + function getDynamicFieldLength( + + ResourceId tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex + + ) external view returns (uint256); + } + + ``` + +- `IStore` now has additional overloads for `getRecord`, `getField`, `getFieldLength` and `setField` that don't require a `FieldLength` to be passed, but instead load it from storage. + +- `IStore` now exposes `setStaticField` and `setDynamicField` to save gas by avoiding the dynamic inference of whether the field is static or dynamic. + +- The `getDynamicFieldSlice` method no longer accepts reading outside the bounds of the dynamic field. + This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero. + +### Minor changes + +**[feat(dev-tools): update actions to display function name instead of callFrom (#1497)](https://github.com/latticexyz/mud/commit/24a0dd4440d6fe661640c581ff5348d62eae9302)** (@latticexyz/dev-tools) + +Improved rendering of transactions that make calls via World's `call` and `callFrom` methods + +**[feat(faucet): add faucet service (#1517)](https://github.com/latticexyz/mud/commit/9940fdb3e036e03aa8ede1ca80cd44d86d3b85b7)** (@latticexyz/faucet) + +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 }); +``` + +**[feat(world): add `registerNamespaceDelegation` for namespace-bound fallback delegation controls (#1590)](https://github.com/latticexyz/mud/commit/1f80a0b52a5c2d051e3697d6e60aad7364b0a925)** (@latticexyz/world) + +It is now possible for namespace owners to register a fallback delegation control system for the namespace. +This fallback delegation control system is used to verify a delegation in `IBaseWorld.callFrom`, after the user's individual and fallback delegations have been checked. + +```solidity +IBaseWorld { + function registerNamespaceDelegation( + ResourceId namespaceId, + ResourceId delegationControlId, + bytes memory initCallData + ) external; +} +``` + +**[feat: move forge build + abi + abi-ts to out (#1483)](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab)** (create-mud) + +Templates now use `out` for their `forge build` artifacts, including ABIs. If you have a project created from a previous template, you can update your `packages/contracts/package.json` with: + +```diff +- "build:abi": "rimraf abi && forge build --extra-output-files abi --out abi --skip test script MudTest.sol", +- "build:abi-ts": "mud abi-ts --input 'abi/IWorld.sol/IWorld.abi.json' && prettier --write '**/*.abi.json.d.ts'", ++ "build:abi": "forge clean && forge build --skip test script", ++ "build:abi-ts": "mud abi-ts && prettier --write '**/*.abi.json.d.ts'", +``` + +And your `packages/client/src/mud/setupNetwork` with: + +```diff +- import IWorldAbi from "contracts/abi/IWorld.sol/IWorld.abi.json"; ++ import IWorldAbi from "contracts/out/IWorld.sol/IWorld.abi.json"; +``` + +**[feat(common,store): add support for user-defined types (#1566)](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9)** (@latticexyz/common) + +- Add `getRemappings` to get foundry remappings as an array of `[to, from]` tuples. +- Add `extractUserTypes` solidity parser utility to extract user-defined types. +- Add `loadAndExtractUserTypes` helper to load and parse a solidity file, extracting user-defined types. + +**[feat(store-indexer): run indexers with npx (#1526)](https://github.com/latticexyz/mud/commit/498d05e3604cd422064e5548dc53bec327e936ee)** (@latticexyz/store-indexer) + +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). + +**[feat(store,): add splice events (#1354)](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853)** (@latticexyz/common) + +`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" +``` + +**[feat(protoocl-parser): add valueSchemaToFieldLayoutHex (#1476)](https://github.com/latticexyz/mud/commit/9ff4dd955fd6dca36eb15cfe7e46bb522d2e943b)** (@latticexyz/protocol-parser) + +Adds `valueSchemaToFieldLayoutHex` helper + +**[feat(store,world): emit Store/World versions (#1511)](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7)** (@latticexyz/store, @latticexyz/world) + +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); +``` + +**[feat(store): expose `getStaticField` and `getDynamicField` on `IStore` and use it in codegen tables (#1521)](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314)** (@latticexyz/cli, @latticexyz/store, @latticexyz/world) + +`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); +} +``` + +**[refactor(store): inline logic in codegenned set method which uses struct (#1542)](https://github.com/latticexyz/mud/commit/80dd6992e98c90a91d417fc785d0d53260df6ce2)** (@latticexyz/store) + +Add an optional `namePrefix` argument to `renderRecordData`, to support inlined logic in codegenned `set` method which uses a struct. + +**[feat(store): indexed `tableId` in store events (#1520)](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380)** (@latticexyz/cli, @latticexyz/common, @latticexyz/store, @latticexyz/world) + +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 +} +``` + +**[feat(world,store): add initialize method, initialize core tables in core module (#1472)](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf)** (@latticexyz/cli, @latticexyz/world) + +- The `World` contract now has an `initialize` function, which can be called once by the creator of the World to install the core module. + This change allows the registration of all core tables to happen in the `CoreModule`, so no table metadata has to be included in the `World`'s bytecode. + + ```solidity + interface IBaseWorld { + function initialize(IModule coreModule) public; + } + ``` + +- The `World` contract now stores the original creator of the `World` in an immutable state variable. + It is used internally to only allow the original creator to initialize the `World` in a separate transaction. + + ```solidity + interface IBaseWorld { + function creator() external view returns (address); + } + ``` + +- The deploy script is updated to use the `World`'s `initialize` function to install the `CoreModule` instead of `registerRootModule` as before. + +**[feat(world): add CallBatchSystem to core module (#1500)](https://github.com/latticexyz/mud/commit/95c59b203259c20a6f944c5f9af008b44e2902b6)** (@latticexyz/world) + +The `World` now has a `callBatch` method which allows multiple system calls to be batched into a single transaction. + +```solidity +import { SystemCallData } from "@latticexyz/world/modules/core/types.sol"; + +interface IBaseWorld { + function callBatch(SystemCallData[] calldata systemCalls) external returns (bytes[] memory returnDatas); +} +``` + +### Patch changes + +**[fix(store-indexer): subscribe postgres indexer to stream (#1514)](https://github.com/latticexyz/mud/commit/ed07018b86046fec20786f4752ac98a4175eb5eb)** (@latticexyz/store-indexer) + +Fixes postgres indexer stopping sync after it catches up to the latest block. + +**[fix: release bytecode on npm and import abi in cli deploy (#1490)](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84)** (@latticexyz/cli, @latticexyz/store, @latticexyz/world) + +Include bytecode for `World` and `Store` in npm packages. + +**[fix(common): always import relative sol files from ./ (#1585)](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96)** (@latticexyz/common) + +Minor fix to resolving user types: `solc` doesn't like relative imports without `./`, but is fine with relative imports from `./../`, so we always append `./` to the relative path. + +**[feat(store): compute FieldLayout at compile time (#1508)](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9)** (@latticexyz/cli, @latticexyz/store, @latticexyz/world) + +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. + +**[feat(store): add Storage.loadField for optimized loading of 32 bytes or less from storage (#1512)](https://github.com/latticexyz/mud/commit/0f3e2e02b5114e08fe700c18326db76816ffad3c)** (@latticexyz/store) + +Added `Storage.loadField` to optimize loading 32 bytes or less from storage (which is always the case when loading data for static fields). + +**[refactor(store,world): prefix errors with library/contract name (#1568)](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c)** (@latticexyz/store, @latticexyz/world) + +Prefixed all errors with their respective library/contract for improved debugging. + +**[refactor(world): remove workaround in mud config (#1501)](https://github.com/latticexyz/mud/commit/4c7fd3eb29e3d3954f2f1f36ace474a436082651)** (@latticexyz/world) + +Remove a workaround for the internal `InstalledModules` table that is not needed anymore. + +**[feat(world): rename `funcSelectorAndArgs` to `callData` (#1524)](https://github.com/latticexyz/mud/commit/a0341daf9fd87e8072ffa292a33f508dd37b8ca6)** (@latticexyz/world) + +Renamed all `funcSelectorAndArgs` arguments to `callData` for clarity. + +**[fix(faucet,store-indexer): fix invalid env message (#1546)](https://github.com/latticexyz/mud/commit/301bcb75dd8c15b8ea1a9d0ca8c75c15d7cd92bd)** (@latticexyz/faucet, @latticexyz/store-indexer) + +Improves error message when parsing env variables + +**[feat(store,world): replace `ResourceSelector` with `ResourceId` and `WorldResourceId` (#1544)](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae)** (@latticexyz/world, @latticexyz/store) + +The `ResourceType` table is removed. +It was previously used to store the resource type for each resource ID in a `World`. This is no longer necessary as the [resource type is now encoded in the resource ID](https://github.com/latticexyz/mud/pull/1544). + +To still be able to determine whether a given resource ID exists, a `ResourceIds` table has been added. +The previous `ResourceType` table was part of `World` and missed tables that were registered directly via `StoreCore.registerTable` instead of via `World.registerTable` (e.g. when a table was registered as part of a root module). +This problem is solved by the new table `ResourceIds` being part of `Store`. + +`StoreCore`'s `hasTable` function was removed in favor of using `ResourceIds.getExists(tableId)` directly. + +```diff +- import { ResourceType } from "@latticexyz/world/src/tables/ResourceType.sol"; +- import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; ++ import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol"; + +- bool tableExists = StoreCore.hasTable(tableId); ++ bool tableExists = ResourceIds.getExists(tableId); + +- bool systemExists = ResourceType.get(systemId) != Resource.NONE; ++ bool systemExists = ResourceIds.getExists(systemId); +``` + +**[feat: rename table to tableId (#1484)](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847)** (@latticexyz/block-logs-stream, @latticexyz/store-sync, @latticexyz/store) + +Renamed all occurrences of `table` where it is used as "table ID" to `tableId`. +This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + +```diff +event StoreSetRecord( +- bytes32 table, ++ bytes32 tableId, + bytes32[] key, + bytes data +); + +event StoreSetField( +- bytes32 table, ++ bytes32 tableId, + bytes32[] key, + uint8 fieldIndex, + bytes data +); + +event StoreDeleteRecord( +- bytes32 table, ++ bytes32 tableId, + bytes32[] key +); + +event StoreEphemeralRecord( +- bytes32 table, ++ bytes32 tableId, + bytes32[] key, + bytes data +); +``` + +**[docs: cli changeset after deploy changes (#1503)](https://github.com/latticexyz/mud/commit/bd9cc8ec2608efcb05ef95df64448b2ec28bcb49)** (@latticexyz/cli) + +Refactor `deploy` command to break up logic into modules + +**[feat: rename key to keyTuple (#1492)](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96)** (@latticexyz/block-logs-stream, @latticexyz/store-sync, @latticexyz/store, @latticexyz/world) + +Renamed all occurrences of `key` where it is used as "key tuple" to `keyTuple`. +This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + +```diff +event StoreSetRecord( + bytes32 tableId, +- bytes32[] key, ++ bytes32[] keyTuple, + bytes data +); + +event StoreSetField( + bytes32 tableId, +- bytes32[] key, ++ bytes32[] keyTuple, + uint8 fieldIndex, + bytes data +); + +event StoreDeleteRecord( + bytes32 tableId, +- bytes32[] key, ++ bytes32[] keyTuple, +); + +event StoreEphemeralRecord( + bytes32 tableId, +- bytes32[] key, ++ bytes32[] keyTuple, + bytes data +); +``` + +**[fix(protocol-parser): export valueSchemaToFieldLayoutHex (#1481)](https://github.com/latticexyz/mud/commit/f8a01a047d73a15326ebf6577ea033674d8e61a9)** (@latticexyz/protocol-parser) + +Export `valueSchemaToFieldLayoutHex` helper + +**[fix(world): register Delegations table in CoreModule (#1452)](https://github.com/latticexyz/mud/commit/f1cd43bf9264d5a23a3edf2a1ea4212361a72203)** (@latticexyz/world) + +Register `Delegations` table in the `CoreModule` + +**[fix(store-indexer): catch errors when parsing logs to tables and storage operations (#1488)](https://github.com/latticexyz/mud/commit/7e6e5157bb124f19bd8ed9f02b93afadc97cdf50)** (@latticexyz/store-sync) + +Catch errors when parsing logs to tables and storage operations, log and skip + +**[refactor(store): rename `Utils.sol` to `leftMask.sol` and minor cleanup (#1599)](https://github.com/latticexyz/mud/commit/63831a264b6b09501f380a4601f82ba7bf07a619)** (@latticexyz/store) + +Minor `Store` cleanups: renamed `Utils.sol` to `leftMask.sol` since it only contains a single free function, and removed a leftover sanity check. + +**[feat(store,world): use user-types for `ResourceId`, `FieldLayout` and `Schema` in table libraries (#1586)](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612)** (@latticexyz/store-sync, @latticexyz/store, @latticexyz/world) + +All `Store` and `World` tables now use the appropriate user-types for `ResourceId`, `FieldLayout` and `Schema` to avoid manual `wrap`/`unwrap`. + +**[feat(store): optimize storage location hash (#1509)](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87)** (@latticexyz/store, @latticexyz/world) + +Optimized the `StoreCore` hash function determining the data location to use less gas. + +**[fix(dev-tools): key -> keyTuple (#1505)](https://github.com/latticexyz/mud/commit/e0193e5737fa2148d5d2b888d71df01d1e46b6d5)** (@latticexyz/dev-tools) + +Updates store event `key` reference to `keyTuple` + +**[fix(dev-tools): table -> tableId (#1502)](https://github.com/latticexyz/mud/commit/e0377761c3a3f83a23de78f6bcb0733c500a0825)** (@latticexyz/dev-tools) + +Updates `table` reference to `tableId` + +**[feat: move forge build + abi + abi-ts to out (#1483)](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab)** (@latticexyz/cli) + +`deploy` and `dev-contracts` CLI commands now use `forge build --skip test script` before deploying and run `mud abi-ts` to generate strong types for ABIs. + +**[refactor(store-indexer): add readme, refactor common env (#1533)](https://github.com/latticexyz/mud/commit/b3c22a183c0b288b9eb1487e4fef125bf7dae915)** (@latticexyz/store-indexer) + +Added README and refactored handling of common environment variables + +**[refactor(store,world): simplify constants (#1569)](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7)** (@latticexyz/store, @latticexyz/world) + +Simplified a couple internal constants used for bitshifting. + +**[docs(faucet): add readme (#1534)](https://github.com/latticexyz/mud/commit/fa409e83db6b76422d525f7d2e9c947dc3c51262)** (@latticexyz/faucet) + +Added README + +**[fix(common): fix memory corruption for dynamic to static array conversion (#1598)](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04)** (@latticexyz/cli, @latticexyz/common) + +Table libraries now correctly handle uninitialized fixed length arrays. + +--- + ## Version 2.0.0-next.8 ### Major changes diff --git a/docs/pages/changelog.mdx b/docs/pages/changelog.mdx index 59dcc2257f..0448fc0b20 100644 --- a/docs/pages/changelog.mdx +++ b/docs/pages/changelog.mdx @@ -1,3 +1,1122 @@ +## Version 2.0.0-next.9 + +### Major changes + +**[feat(world): prevent the `World` from calling itself (#1563)](https://github.com/latticexyz/mud/commit/748f4588a218928bca041760448c26991c0d8033)** (@latticexyz/world) + +All `World` methods now revert if the `World` calls itself. +The `World` should never need to externally call itself, since all internal table operations happen via library calls, and all root system operations happen via delegate call. + +It should not be possible to make the `World` call itself as an external actor. +If it were possible to make the `World` call itself, it would be possible to write to internal tables that only the `World` should have access to. +As this is a very important invariance, we made it explicit in a requirement check in every `World` method, rather than just relying on making it impossible to trigger the `World` to call itself. + +This is a breaking change for modules that previously used external calls to the `World` in the `installRoot` method. +In the `installRoot` method, the `World` can only be called via `delegatecall`, and table operations should be performed via the internal table methods (e.g. `_set` instead of `set`). + +Example for how to replace external calls to `world` in root systems / root modules (`installRoot`) with `delegatecall`: + +```diff ++ import { revertWithBytes } from "@latticexyz/world/src/revertWithBytes.sol"; + +- world.grantAccess(tableId, address(hook)); ++ (bool success, bytes memory returnData) = address(world).delegatecall( ++ abi.encodeCall(world.grantAccess, (tableId, address(hook))) ++ ); + ++ if (!success) revertWithBytes(returnData); +``` + +**[feat: rename schema to valueSchema (#1482)](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9)** (@latticexyz/cli, @latticexyz/protocol-parser, @latticexyz/store-sync, @latticexyz/store, create-mud) + +Renamed all occurrences of `schema` where it is used as "value schema" to `valueSchema` to clearly distinguish it from "key schema". +The only breaking change for users is the change from `schema` to `valueSchema` in `mud.config.ts`. + +```diff +// mud.config.ts +export default mudConfig({ + tables: { + CounterTable: { + keySchema: {}, +- schema: { ++ valueSchema: { + value: "uint32", + }, + }, + } +} +``` + +**[refactor(world): move codegen files (#1592)](https://github.com/latticexyz/mud/commit/c07fa021501ff92be35c0491dd89bbb8161e1c07)** (@latticexyz/cli, @latticexyz/world-modules, @latticexyz/world) + +Tables and interfaces in the `world` package are now generated to the `codegen` folder. +This is only a breaking change if you imported tables or codegenerated interfaces from `@latticexyz/world` directly. +If you're using the MUD CLI, the changed import paths are already integrated and no further changes are necessary. + +```diff +- import { IBaseWorld } from "@latticexyz/world/src/interfaces/IBaseWorld.sol"; ++ import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol"; + +``` + +**[refactor(store): always render field methods with suffix and conditionally without (#1550)](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e)** (@latticexyz/common) + +- Add `renderWithFieldSuffix` helper method to always render a field function with a suffix, and optionally render the same function without a suffix. +- Remove `methodNameSuffix` from `RenderField` interface, because the suffix is now computed as part of `renderWithFieldSuffix`. + +**[feat(store,): add splice events (#1354)](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853)** (@latticexyz/store, @latticexyz/world) + +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. + +**[refactor(store): change argument order on `Store_SpliceDynamicData` and hooks for consistency (#1589)](https://github.com/latticexyz/mud/commit/f9f9609ef69d7fa58cad6a9af3fe6d2eed6d8aa2)** (@latticexyz/store) + +The argument order on `Store_SpliceDynamicData`, `onBeforeSpliceDynamicData` and `onAfterSpliceDynamicData` has been changed to match the argument order on `Store_SetRecord`, +where the `PackedCounter encodedLength` field comes before the `bytes dynamicData` field. + +```diff +IStore { + event Store_SpliceDynamicData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, ++ PackedCounter encodedLengths, + bytes data, +- PackedCounter encodedLengths + ); +} + +IStoreHook { + function onBeforeSpliceDynamicData( + ResourceId tableId, + bytes32[] memory keyTuple, + uint8 dynamicFieldIndex, + uint40 startWithinField, + uint40 deleteCount, ++ PackedCounter encodedLengths, + bytes memory data, +- PackedCounter encodedLengths + ) external; + + function onAfterSpliceDynamicData( + ResourceId tableId, + bytes32[] memory keyTuple, + uint8 dynamicFieldIndex, + uint40 startWithinField, + uint40 deleteCount, ++ PackedCounter encodedLengths, + bytes memory data, +- PackedCounter encodedLengths + ) external; +} +``` + +**[feat(store,): add splice events (#1354)](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853)** (@latticexyz/common, @latticexyz/protocol-parser) + +`readHex` was moved from `@latticexyz/protocol-parser` to `@latticexyz/common` + +**[feat(store,world): move hooks to bit flags (#1527)](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8)** (@latticexyz/store, @latticexyz/world) + +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 + ); + +``` + +**[feat(store,world): add splice hooks, expose spliceStaticData, spliceDynamicData (#1531)](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4)** (@latticexyz/store, @latticexyz/world) + +- The `IStoreHook` interface was changed to replace `onBeforeSetField` and `onAfterSetField` with `onBeforeSpliceStaticData`, `onAfterSpliceStaticData`, `onBeforeSpliceDynamicData` and `onAfterSpliceDynamicData`. + + This new interface matches the new `StoreSpliceStaticData` and `StoreSpliceDynamicData` events, and avoids having to read the entire field from storage when only a subset of the field was updated + (e.g. when pushing elements to a field). + + ```diff + interface IStoreHook { + - function onBeforeSetField( + - bytes32 tableId, + - bytes32[] memory keyTuple, + - uint8 fieldIndex, + - bytes memory data, + - FieldLayout fieldLayout + - ) external; + + - function onAfterSetField( + - bytes32 tableId, + - bytes32[] memory keyTuple, + - uint8 fieldIndex, + - bytes memory data, + - FieldLayout fieldLayout + - ) external; + + + function onBeforeSpliceStaticData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint48 start, + + uint40 deleteCount, + + bytes memory data + + ) external; + + + function onAfterSpliceStaticData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint48 start, + + uint40 deleteCount, + + bytes memory data + + ) external; + + + function onBeforeSpliceDynamicData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex, + + uint40 startWithinField, + + uint40 deleteCount, + + bytes memory data, + + PackedCounter encodedLengths + + ) external; + + + function onAfterSpliceDynamicData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex, + + uint40 startWithinField, + + uint40 deleteCount, + + bytes memory data, + + PackedCounter encodedLengths + + ) external; + } + ``` + +- All `calldata` parameters on the `IStoreHook` interface were changed to `memory`, since the functions are called with `memory` from the `World`. + +- `IStore` exposes two new functions: `spliceStaticData` and `spliceDynamicData`. + + These functions provide lower level access to the operations happening under the hood in `setField`, `pushToField`, `popFromField` and `updateInField` and simplify handling + the new splice hooks. + + `StoreCore`'s internal logic was simplified to use the `spliceStaticData` and `spliceDynamicData` functions instead of duplicating similar logic in different functions. + + ```solidity + interface IStore { + // Splice data in the static part of the record + function spliceStaticData( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint48 start, + uint40 deleteCount, + bytes calldata data + ) external; + + // Splice data in the dynamic part of the record + function spliceDynamicData( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint8 dynamicFieldIndex, + uint40 startWithinField, + uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + +**[feat: replace Schema with FieldLayout for contract internals (#1336)](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e)** (@latticexyz/cli, @latticexyz/protocol-parser, @latticexyz/store, @latticexyz/world) + +- Add `FieldLayout`, which is a `bytes32` user-type similar to `Schema`. + + Both `FieldLayout` and `Schema` have the same kind of data in the first 4 bytes. + + - 2 bytes for total length of all static fields + - 1 byte for number of static size fields + - 1 byte for number of dynamic size fields + + But whereas `Schema` has `SchemaType` enum in each of the other 28 bytes, `FieldLayout` has static byte lengths in each of the other 28 bytes. + +- Replace `Schema valueSchema` with `FieldLayout fieldLayout` in Store and World contracts. + + `FieldLayout` is more gas-efficient because it already has lengths, and `Schema` has types which need to be converted to lengths. + +- Add `getFieldLayout` to `IStore` interface. + + There is no `FieldLayout` for keys, only for values, because key byte lengths aren't usually relevant on-chain. You can still use `getKeySchema` if you need key types. + +- Add `fieldLayoutToHex` utility to `protocol-parser` package. + +- Add `constants.sol` for constants shared between `FieldLayout`, `Schema` and `PackedCounter`. + +**[refactor: separate data into staticData, encodedLengths, dynamicData in getRecord (#1532)](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623)** (@latticexyz/store, @latticexyz/world) + +Store's `getRecord` has been updated to return `staticData`, `encodedLengths`, and `dynamicData` instead of a single `data` blob, to match the new behaviour of Store setter methods. + +If you use codegenerated libraries, you will only need to update `encode` calls. + +```diff +- bytes memory data = Position.encode(x, y); ++ (bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData) = Position.encode(x, y); +``` + +**[feat(world): add `FunctionSignatures` offchain table (#1575)](https://github.com/latticexyz/mud/commit/e5d208e40b2b2fae223b48716ce3f62c530ea1ca)** (@latticexyz/cli, @latticexyz/world) + +The `registerRootFunctionSelector` function's signature was changed to accept a `string functionSignature` parameter instead of a `bytes4 functionSelector` parameter. +This change enables the `World` to store the function signatures of all registered functions in a `FunctionSignatures` offchain table, which will allow for the automatic generation of interfaces for a given `World` address in the future. + +```diff +IBaseWorld { + function registerRootFunctionSelector( + ResourceId systemId, +- bytes4 worldFunctionSelector, ++ string memory worldFunctionSignature, + bytes4 systemFunctionSelector + ) external returns (bytes4 worldFunctionSelector); +} +``` + +**[feat: move forge build + abi + abi-ts to out (#1483)](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab)** (@latticexyz/store, @latticexyz/world) + +Store and World contract ABIs are now exported from the `out` directory. You'll need to update your imports like: + +```diff +- import IBaseWorldAbi from "@latticexyz/world/abi/IBaseWorld.sol/IBaseWorldAbi.json"; ++ import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorldAbi.json"; +``` + +`MudTest.sol` was also moved to the World package. You can update your import like: + +```diff +- import { MudTest } from "@latticexyz/store/src/MudTest.sol"; ++ import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; +``` + +**[feat(common,store): add support for user-defined types (#1566)](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9)** (@latticexyz/store) + +These breaking changes only affect store utilities, you aren't affected if you use `@latticexyz/cli` codegen scripts. + +- Add `remappings` argument to the `tablegen` codegen function, so that it can read user-provided files. +- In `RenderTableOptions` change the type of `imports` from `RelativeImportDatum` to `ImportDatum`, to allow passing absolute imports to the table renderer. +- Add `solidityUserTypes` argument to several functions that need to resolve user or abi types: `resolveAbiOrUserType`, `importForAbiOrUserType`, `getUserTypeInfo`. +- Add `userTypes` config option to MUD config, which takes user types mapped to file paths from which to import them. + +**[refactor(store): always render field methods with suffix and conditionally without (#1550)](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e)** (@latticexyz/store) + +- Always render field methods with a suffix in tablegen (they used to not be rendered if field methods without a suffix were rendered). +- Add `withSuffixlessFieldMethods` to `RenderTableOptions`, which indicates that field methods without a suffix should be rendered. + +**[feat(world): change registerFunctionSelector signature to accept system signature as a single string (#1574)](https://github.com/latticexyz/mud/commit/31ffc9d5d0a6d030cc61349f0f8fbcf6748ebc48)** (@latticexyz/cli, @latticexyz/world) + +The `registerFunctionSelector` function now accepts a single `functionSignature` string paramemer instead of separating function name and function arguments into separate parameters. + +```diff +IBaseWorld { + function registerFunctionSelector( + ResourceId systemId, +- string memory systemFunctionName, +- string memory systemFunctionArguments ++ string memory systemFunctionSignature + ) external returns (bytes4 worldFunctionSelector); +} +``` + +This is a breaking change if you were manually registering function selectors, e.g. in a `PostDeploy.s.sol` script or a module. +To upgrade, simply replace the separate `systemFunctionName` and `systemFunctionArguments` parameters with a single `systemFunctionSignature` parameter. + +```diff + world.registerFunctionSelector( + systemId, +- systemFunctionName, +- systemFunctionArguments, ++ string(abi.encodePacked(systemFunctionName, systemFunctionArguments)) + ); +``` + +**[feat(store,world): replace `ResourceSelector` with `ResourceId` and `WorldResourceId` (#1544)](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae)** (@latticexyz/world) + +All `World` methods acting on namespaces as resources have been updated to use `ResourceId namespaceId` as parameter instead of `bytes14 namespace`. +The reason for this change is to make it clearer when a namespace is used as resource, as opposed to being part of another resource's ID. + +```diff ++ import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + +IBaseWorld { +- function registerNamespace(bytes14 namespace) external; ++ function registerNamespace(ResourceId namespaceId) external; + +- function transferOwnership(bytes14 namespace, address newOwner) external; ++ function transferOwnership(ResourceId namespaceId, address newOwner) external; + +- function transferBalanceToNamespace(bytes14 fromNamespace, bytes14 toNamespace, uint256 amount) external; ++ function transferBalanceToNamespace(ResourceId fromNamespaceId, ResourceId toNamespaceId, uint256 amount) external; + +- function transferBalanceToAddress(bytes14 fromNamespace, address toAddress, uint256 amount) external; ++ function transferBalanceToAddress(ResourceId fromNamespaceId, address toAddress, uint256 amount) external; +} + +``` + +**[feat: bump solidity to 0.8.21 (#1473)](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a)** (@latticexyz/cli, @latticexyz/common, @latticexyz/gas-report, @latticexyz/noise, @latticexyz/schema-type, @latticexyz/store, @latticexyz/world, create-mud) + +Bump Solidity version to 0.8.21 + +**[feat(world): add `batchCallFrom` (#1594)](https://github.com/latticexyz/mud/commit/5741d53d0a39990a0d7b2842f1f012973655e060)** (@latticexyz/world) + +- `IBaseWorld` now has a `batchCallFrom` method, which allows system calls via `callFrom` to be executed in batch. + +```solidity +import { SystemCallFromData } from "@latticexyz/world/modules/core/types.sol"; + +interface IBaseWorld { + function batchCallFrom(SystemCallFromData[] calldata systemCalls) external returns (bytes[] memory returnDatas); +} +``` + +- The `callBatch` method of `IBaseWorld` has been renamed to `batchCall` to align better with the `batchCallFrom` method. + +```diff +interface IBaseWorld { +- function callBatch(SystemCallData[] calldata systemCalls) external returns (bytes[] memory returnDatas); ++ function batchCall(SystemCallData[] calldata systemCalls) external returns (bytes[] memory returnDatas); +} +``` + +**[feat(store): codegen index and common files (#1318)](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130)** (@latticexyz/cli, @latticexyz/store, create-mud) + +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"; +``` + +**[feat(store,): add splice events (#1354)](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853)** (@latticexyz/dev-tools, @latticexyz/store-sync, create-mud) + +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. + +**[feat(store,world): replace `ephemeral` tables with `offchain` tables (#1558)](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f)** (@latticexyz/block-logs-stream, @latticexyz/cli, @latticexyz/common, @latticexyz/dev-tools, @latticexyz/store-sync, @latticexyz/store, create-mud) + +What used to be known as `ephemeral` table is now called `offchain` table. +The previous `ephemeral` tables only supported an `emitEphemeral` method, which emitted a `StoreSetEphemeralRecord` event. + +Now `offchain` tables support all regular table methods, except partial operations on dynamic fields (`push`, `pop`, `update`). +Unlike regular tables they don't store data on-chain but emit the same events as regular tables (`StoreSetRecord`, `StoreSpliceStaticData`, `StoreDeleteRecord`), so their data can be indexed by offchain indexers/clients. + +```diff +- EphemeralTable.emitEphemeral(value); ++ OffchainTable.set(value); +``` + +**[feat(store): rename events for readability and consistency with errors (#1577)](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c)** (@latticexyz/block-logs-stream, @latticexyz/dev-tools, @latticexyz/store-sync, @latticexyz/store) + +`Store` events have been renamed for consistency and readability. +If you're parsing `Store` events manually, you need to update your ABI. +If you're using the MUD sync stack, the new events are already integrated and no further changes are necessary. + +```diff +- event StoreSetRecord( ++ event Store_SetRecord( + ResourceId indexed tableId, + bytes32[] keyTuple, + bytes staticData, + bytes32 encodedLengths, + bytes dynamicData + ); +- event StoreSpliceStaticData( ++ event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data + ); +- event StoreSpliceDynamicData( ++ event Store_SpliceDynamicData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data, + bytes32 encodedLengths + ); +- event StoreDeleteRecord( ++ event Store_DeleteRecord( + ResourceId indexed tableId, + bytes32[] keyTuple + ); +``` + +**[feat(store,world): replace `ResourceSelector` with `ResourceId` and `WorldResourceId` (#1544)](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae)** (@latticexyz/cli, @latticexyz/common, @latticexyz/config, @latticexyz/store) + +- `ResourceSelector` is replaced with `ResourceId`, `ResourceIdLib`, `ResourceIdInstance`, `WorldResourceIdLib` and `WorldResourceIdInstance`. + + Previously a "resource selector" was a `bytes32` value with the first 16 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + Now a "resource ID" is a `bytes32` value with the first 2 bytes reserved for the resource type, the next 14 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + + Previously `ResouceSelector` was a library and the resource selector type was a plain `bytes32`. + Now `ResourceId` is a user type, and the functionality is implemented in the `ResourceIdInstance` (for type) and `WorldResourceIdInstance` (for namespace and name) libraries. + We split the logic into two libraries, because `Store` now also uses `ResourceId` and needs to be aware of resource types, but not of namespaces/names. + + ```diff + - import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol"; + + import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; + + import { WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol"; + + import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol"; + + - bytes32 systemId = ResourceSelector.from("namespace", "name"); + + ResourceId systemId = WorldResourceIdLib.encode(RESOURCE_SYSTEM, "namespace", "name"); + + - using ResourceSelector for bytes32; + + using WorldResourceIdInstance for ResourceId; + + using ResourceIdInstance for ResourceId; + + systemId.getName(); + systemId.getNamespace(); + + systemId.getType(); + + ``` + +- All `Store` and `World` methods now use the `ResourceId` type for `tableId`, `systemId`, `moduleId` and `namespaceId`. + All mentions of `resourceSelector` were renamed to `resourceId` or the more specific type (e.g. `tableId`, `systemId`) + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IStore { + function setRecord( + - bytes32 tableId, + + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + FieldLayout fieldLayout + ) external; + + // Same for all other methods + } + ``` + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IBaseWorld { + function callFrom( + address delegator, + - bytes32 resourceSelector, + + ResourceId systemId, + bytes memory callData + ) external payable returns (bytes memory); + + // Same for all other methods + } + ``` + +**[feat(store): indexed `tableId` in store events (#1520)](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380)** (@latticexyz/store) + +Store events now use an `indexed` `tableId`. This adds ~100 gas per write, but means we our sync stack can filter events by table. + +**[feat(world,store): add initialize method, initialize core tables in core module (#1472)](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf)** (@latticexyz/store) + +- `StoreCore`'s `initialize` function is split into `initialize` (to set the `StoreSwitch`'s `storeAddress`) and `registerCoreTables` (to register the `Tables` and `StoreHooks` tables). + The purpose of this is to give consumers more granular control over the setup flow. + +- The `StoreRead` contract no longer calls `StoreCore.initialize` in its constructor. + `StoreCore` consumers are expected to call `StoreCore.initialize` and `StoreCore.registerCoreTable` in their own setup logic. + +**[feat(store): add `internalType` property to user types config for type inference (#1587)](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d)** (@latticexyz/cli, @latticexyz/common, @latticexyz/store) + +Changed the `userTypes` property to accept `{ filePath: string, internalType: SchemaAbiType }` to enable strong type inference from the config. + +**[refactor(world,world-modules): move optional modules from `world` to `world-modules` package (#1591)](https://github.com/latticexyz/mud/commit/251170e1ef0b07466c597ea84df0cb49de7d6a23)** (@latticexyz/cli, @latticexyz/world, @latticexyz/world-modules) + +All optional modules have been moved from `@latticexyz/world` to `@latticexyz/world-modules`. +If you're using the MUD CLI, the import is already updated and no changes are necessary. + +**[feat(store,world): polish store methods (#1581)](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b)** (@latticexyz/block-logs-stream, @latticexyz/cli, @latticexyz/common, @latticexyz/dev-tools, @latticexyz/store-sync, @latticexyz/store, @latticexyz/world, create-mud) + +- The external `setRecord` and `deleteRecord` methods of `IStore` no longer accept a `FieldLayout` as input, but load it from storage instead. + This is to prevent invalid `FieldLayout` values being passed, which could cause the onchain state to diverge from the indexer state. + However, the internal `StoreCore` library still exposes a `setRecord` and `deleteRecord` method that allows a `FieldLayout` to be passed. + This is because `StoreCore` can only be used internally, so the `FieldLayout` value can be trusted and we can save the gas for accessing storage. + + ```diff + interface IStore { + function setRecord( + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + - FieldLayout fieldLayout + ) external; + + function deleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + - FieldLayout fieldLayout + ) external; + } + ``` + +- The `spliceStaticData` method and `Store_SpliceStaticData` event of `IStore` and `StoreCore` no longer include `deleteCount` in their signature. + This is because when splicing static data, the data after `start` is always overwritten with `data` instead of being shifted, so `deleteCount` is always the length of the data to be written. + + ```diff + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + - uint40 deleteCount, + bytes data + ); + + interface IStore { + function spliceStaticData( + ResourceId tableId, + bytes32[] calldata keyTuple, + uint48 start, + - uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + +- The `updateInField` method has been removed from `IStore`, as it's almost identical to the more general `spliceDynamicData`. + If you're manually calling `updateInField`, here is how to upgrade to `spliceDynamicData`: + + ```diff + - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); + + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields(); + + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet); + ``` + +- All other methods that are only valid for dynamic fields (`pushToField`, `popFromField`, `getFieldSlice`) + have been renamed to make this more explicit (`pushToDynamicField`, `popFromDynamicField`, `getDynamicFieldSlice`). + + Their `fieldIndex` parameter has been replaced by a `dynamicFieldIndex` parameter, which is the index relative to the first dynamic field (i.e. `dynamicFieldIndex` = `fieldIndex` - `numStaticFields`). + The `FieldLayout` parameter has been removed, as it was only used to calculate the `dynamicFieldIndex` in the method. + + ```diff + interface IStore { + - function pushToField( + + function pushToDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + bytes calldata dataToPush, + - FieldLayout fieldLayout + ) external; + + - function popFromField( + + function popFromDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + uint256 byteLengthToPop, + - FieldLayout fieldLayout + ) external; + + - function getFieldSlice( + + function getDynamicFieldSlice( + ResourceId tableId, + bytes32[] memory keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + - FieldLayout fieldLayout, + uint256 start, + uint256 end + ) external view returns (bytes memory data); + } + ``` + +- `IStore` has a new `getDynamicFieldLength` length method, which returns the byte length of the given dynamic field and doesn't require the `FieldLayout`. + + ```diff + IStore { + + function getDynamicFieldLength( + + ResourceId tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex + + ) external view returns (uint256); + } + + ``` + +- `IStore` now has additional overloads for `getRecord`, `getField`, `getFieldLength` and `setField` that don't require a `FieldLength` to be passed, but instead load it from storage. + +- `IStore` now exposes `setStaticField` and `setDynamicField` to save gas by avoiding the dynamic inference of whether the field is static or dynamic. + +- The `getDynamicFieldSlice` method no longer accepts reading outside the bounds of the dynamic field. + This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero. + +### Minor changes + +**[feat(dev-tools): update actions to display function name instead of callFrom (#1497)](https://github.com/latticexyz/mud/commit/24a0dd4440d6fe661640c581ff5348d62eae9302)** (@latticexyz/dev-tools) + +Improved rendering of transactions that make calls via World's `call` and `callFrom` methods + +**[feat(faucet): add faucet service (#1517)](https://github.com/latticexyz/mud/commit/9940fdb3e036e03aa8ede1ca80cd44d86d3b85b7)** (@latticexyz/faucet) + +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 }); +``` + +**[feat(world): add `registerNamespaceDelegation` for namespace-bound fallback delegation controls (#1590)](https://github.com/latticexyz/mud/commit/1f80a0b52a5c2d051e3697d6e60aad7364b0a925)** (@latticexyz/world) + +It is now possible for namespace owners to register a fallback delegation control system for the namespace. +This fallback delegation control system is used to verify a delegation in `IBaseWorld.callFrom`, after the user's individual and fallback delegations have been checked. + +```solidity +IBaseWorld { + function registerNamespaceDelegation( + ResourceId namespaceId, + ResourceId delegationControlId, + bytes memory initCallData + ) external; +} +``` + +**[feat: move forge build + abi + abi-ts to out (#1483)](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab)** (create-mud) + +Templates now use `out` for their `forge build` artifacts, including ABIs. If you have a project created from a previous template, you can update your `packages/contracts/package.json` with: + +```diff +- "build:abi": "rimraf abi && forge build --extra-output-files abi --out abi --skip test script MudTest.sol", +- "build:abi-ts": "mud abi-ts --input 'abi/IWorld.sol/IWorld.abi.json' && prettier --write '**/*.abi.json.d.ts'", ++ "build:abi": "forge clean && forge build --skip test script", ++ "build:abi-ts": "mud abi-ts && prettier --write '**/*.abi.json.d.ts'", +``` + +And your `packages/client/src/mud/setupNetwork` with: + +```diff +- import IWorldAbi from "contracts/abi/IWorld.sol/IWorld.abi.json"; ++ import IWorldAbi from "contracts/out/IWorld.sol/IWorld.abi.json"; +``` + +**[feat(common,store): add support for user-defined types (#1566)](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9)** (@latticexyz/common) + +- Add `getRemappings` to get foundry remappings as an array of `[to, from]` tuples. +- Add `extractUserTypes` solidity parser utility to extract user-defined types. +- Add `loadAndExtractUserTypes` helper to load and parse a solidity file, extracting user-defined types. + +**[feat(store-indexer): run indexers with npx (#1526)](https://github.com/latticexyz/mud/commit/498d05e3604cd422064e5548dc53bec327e936ee)** (@latticexyz/store-indexer) + +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). + +**[feat(store,): add splice events (#1354)](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853)** (@latticexyz/common) + +`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" +``` + +**[feat(protoocl-parser): add valueSchemaToFieldLayoutHex (#1476)](https://github.com/latticexyz/mud/commit/9ff4dd955fd6dca36eb15cfe7e46bb522d2e943b)** (@latticexyz/protocol-parser) + +Adds `valueSchemaToFieldLayoutHex` helper + +**[feat(store,world): emit Store/World versions (#1511)](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7)** (@latticexyz/store, @latticexyz/world) + +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); +``` + +**[feat(store): expose `getStaticField` and `getDynamicField` on `IStore` and use it in codegen tables (#1521)](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314)** (@latticexyz/cli, @latticexyz/store, @latticexyz/world) + +`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); +} +``` + +**[refactor(store): inline logic in codegenned set method which uses struct (#1542)](https://github.com/latticexyz/mud/commit/80dd6992e98c90a91d417fc785d0d53260df6ce2)** (@latticexyz/store) + +Add an optional `namePrefix` argument to `renderRecordData`, to support inlined logic in codegenned `set` method which uses a struct. + +**[feat(store): indexed `tableId` in store events (#1520)](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380)** (@latticexyz/cli, @latticexyz/common, @latticexyz/store, @latticexyz/world) + +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 +} +``` + +**[feat(world,store): add initialize method, initialize core tables in core module (#1472)](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf)** (@latticexyz/cli, @latticexyz/world) + +- The `World` contract now has an `initialize` function, which can be called once by the creator of the World to install the core module. + This change allows the registration of all core tables to happen in the `CoreModule`, so no table metadata has to be included in the `World`'s bytecode. + + ```solidity + interface IBaseWorld { + function initialize(IModule coreModule) public; + } + ``` + +- The `World` contract now stores the original creator of the `World` in an immutable state variable. + It is used internally to only allow the original creator to initialize the `World` in a separate transaction. + + ```solidity + interface IBaseWorld { + function creator() external view returns (address); + } + ``` + +- The deploy script is updated to use the `World`'s `initialize` function to install the `CoreModule` instead of `registerRootModule` as before. + +**[feat(world): add CallBatchSystem to core module (#1500)](https://github.com/latticexyz/mud/commit/95c59b203259c20a6f944c5f9af008b44e2902b6)** (@latticexyz/world) + +The `World` now has a `callBatch` method which allows multiple system calls to be batched into a single transaction. + +```solidity +import { SystemCallData } from "@latticexyz/world/modules/core/types.sol"; + +interface IBaseWorld { + function callBatch(SystemCallData[] calldata systemCalls) external returns (bytes[] memory returnDatas); +} +``` + +### Patch changes + +**[fix(store-indexer): subscribe postgres indexer to stream (#1514)](https://github.com/latticexyz/mud/commit/ed07018b86046fec20786f4752ac98a4175eb5eb)** (@latticexyz/store-indexer) + +Fixes postgres indexer stopping sync after it catches up to the latest block. + +**[fix: release bytecode on npm and import abi in cli deploy (#1490)](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84)** (@latticexyz/cli, @latticexyz/store, @latticexyz/world) + +Include bytecode for `World` and `Store` in npm packages. + +**[fix(common): always import relative sol files from ./ (#1585)](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96)** (@latticexyz/common) + +Minor fix to resolving user types: `solc` doesn't like relative imports without `./`, but is fine with relative imports from `./../`, so we always append `./` to the relative path. + +**[feat(store): compute FieldLayout at compile time (#1508)](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9)** (@latticexyz/cli, @latticexyz/store, @latticexyz/world) + +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. + +**[feat(store): add Storage.loadField for optimized loading of 32 bytes or less from storage (#1512)](https://github.com/latticexyz/mud/commit/0f3e2e02b5114e08fe700c18326db76816ffad3c)** (@latticexyz/store) + +Added `Storage.loadField` to optimize loading 32 bytes or less from storage (which is always the case when loading data for static fields). + +**[refactor(store,world): prefix errors with library/contract name (#1568)](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c)** (@latticexyz/store, @latticexyz/world) + +Prefixed all errors with their respective library/contract for improved debugging. + +**[refactor(world): remove workaround in mud config (#1501)](https://github.com/latticexyz/mud/commit/4c7fd3eb29e3d3954f2f1f36ace474a436082651)** (@latticexyz/world) + +Remove a workaround for the internal `InstalledModules` table that is not needed anymore. + +**[feat(world): rename `funcSelectorAndArgs` to `callData` (#1524)](https://github.com/latticexyz/mud/commit/a0341daf9fd87e8072ffa292a33f508dd37b8ca6)** (@latticexyz/world) + +Renamed all `funcSelectorAndArgs` arguments to `callData` for clarity. + +**[fix(faucet,store-indexer): fix invalid env message (#1546)](https://github.com/latticexyz/mud/commit/301bcb75dd8c15b8ea1a9d0ca8c75c15d7cd92bd)** (@latticexyz/faucet, @latticexyz/store-indexer) + +Improves error message when parsing env variables + +**[feat(store,world): replace `ResourceSelector` with `ResourceId` and `WorldResourceId` (#1544)](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae)** (@latticexyz/world, @latticexyz/store) + +The `ResourceType` table is removed. +It was previously used to store the resource type for each resource ID in a `World`. This is no longer necessary as the [resource type is now encoded in the resource ID](https://github.com/latticexyz/mud/pull/1544). + +To still be able to determine whether a given resource ID exists, a `ResourceIds` table has been added. +The previous `ResourceType` table was part of `World` and missed tables that were registered directly via `StoreCore.registerTable` instead of via `World.registerTable` (e.g. when a table was registered as part of a root module). +This problem is solved by the new table `ResourceIds` being part of `Store`. + +`StoreCore`'s `hasTable` function was removed in favor of using `ResourceIds.getExists(tableId)` directly. + +```diff +- import { ResourceType } from "@latticexyz/world/src/tables/ResourceType.sol"; +- import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; ++ import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol"; + +- bool tableExists = StoreCore.hasTable(tableId); ++ bool tableExists = ResourceIds.getExists(tableId); + +- bool systemExists = ResourceType.get(systemId) != Resource.NONE; ++ bool systemExists = ResourceIds.getExists(systemId); +``` + +**[feat: rename table to tableId (#1484)](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847)** (@latticexyz/block-logs-stream, @latticexyz/store-sync, @latticexyz/store) + +Renamed all occurrences of `table` where it is used as "table ID" to `tableId`. +This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + +```diff +event StoreSetRecord( +- bytes32 table, ++ bytes32 tableId, + bytes32[] key, + bytes data +); + +event StoreSetField( +- bytes32 table, ++ bytes32 tableId, + bytes32[] key, + uint8 fieldIndex, + bytes data +); + +event StoreDeleteRecord( +- bytes32 table, ++ bytes32 tableId, + bytes32[] key +); + +event StoreEphemeralRecord( +- bytes32 table, ++ bytes32 tableId, + bytes32[] key, + bytes data +); +``` + +**[docs: cli changeset after deploy changes (#1503)](https://github.com/latticexyz/mud/commit/bd9cc8ec2608efcb05ef95df64448b2ec28bcb49)** (@latticexyz/cli) + +Refactor `deploy` command to break up logic into modules + +**[feat: rename key to keyTuple (#1492)](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96)** (@latticexyz/block-logs-stream, @latticexyz/store-sync, @latticexyz/store, @latticexyz/world) + +Renamed all occurrences of `key` where it is used as "key tuple" to `keyTuple`. +This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + +```diff +event StoreSetRecord( + bytes32 tableId, +- bytes32[] key, ++ bytes32[] keyTuple, + bytes data +); + +event StoreSetField( + bytes32 tableId, +- bytes32[] key, ++ bytes32[] keyTuple, + uint8 fieldIndex, + bytes data +); + +event StoreDeleteRecord( + bytes32 tableId, +- bytes32[] key, ++ bytes32[] keyTuple, +); + +event StoreEphemeralRecord( + bytes32 tableId, +- bytes32[] key, ++ bytes32[] keyTuple, + bytes data +); +``` + +**[fix(protocol-parser): export valueSchemaToFieldLayoutHex (#1481)](https://github.com/latticexyz/mud/commit/f8a01a047d73a15326ebf6577ea033674d8e61a9)** (@latticexyz/protocol-parser) + +Export `valueSchemaToFieldLayoutHex` helper + +**[fix(world): register Delegations table in CoreModule (#1452)](https://github.com/latticexyz/mud/commit/f1cd43bf9264d5a23a3edf2a1ea4212361a72203)** (@latticexyz/world) + +Register `Delegations` table in the `CoreModule` + +**[fix(store-indexer): catch errors when parsing logs to tables and storage operations (#1488)](https://github.com/latticexyz/mud/commit/7e6e5157bb124f19bd8ed9f02b93afadc97cdf50)** (@latticexyz/store-sync) + +Catch errors when parsing logs to tables and storage operations, log and skip + +**[refactor(store): rename `Utils.sol` to `leftMask.sol` and minor cleanup (#1599)](https://github.com/latticexyz/mud/commit/63831a264b6b09501f380a4601f82ba7bf07a619)** (@latticexyz/store) + +Minor `Store` cleanups: renamed `Utils.sol` to `leftMask.sol` since it only contains a single free function, and removed a leftover sanity check. + +**[feat(store,world): use user-types for `ResourceId`, `FieldLayout` and `Schema` in table libraries (#1586)](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612)** (@latticexyz/store-sync, @latticexyz/store, @latticexyz/world) + +All `Store` and `World` tables now use the appropriate user-types for `ResourceId`, `FieldLayout` and `Schema` to avoid manual `wrap`/`unwrap`. + +**[feat(store): optimize storage location hash (#1509)](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87)** (@latticexyz/store, @latticexyz/world) + +Optimized the `StoreCore` hash function determining the data location to use less gas. + +**[fix(dev-tools): key -> keyTuple (#1505)](https://github.com/latticexyz/mud/commit/e0193e5737fa2148d5d2b888d71df01d1e46b6d5)** (@latticexyz/dev-tools) + +Updates store event `key` reference to `keyTuple` + +**[fix(dev-tools): table -> tableId (#1502)](https://github.com/latticexyz/mud/commit/e0377761c3a3f83a23de78f6bcb0733c500a0825)** (@latticexyz/dev-tools) + +Updates `table` reference to `tableId` + +**[feat: move forge build + abi + abi-ts to out (#1483)](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab)** (@latticexyz/cli) + +`deploy` and `dev-contracts` CLI commands now use `forge build --skip test script` before deploying and run `mud abi-ts` to generate strong types for ABIs. + +**[refactor(store-indexer): add readme, refactor common env (#1533)](https://github.com/latticexyz/mud/commit/b3c22a183c0b288b9eb1487e4fef125bf7dae915)** (@latticexyz/store-indexer) + +Added README and refactored handling of common environment variables + +**[refactor(store,world): simplify constants (#1569)](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7)** (@latticexyz/store, @latticexyz/world) + +Simplified a couple internal constants used for bitshifting. + +**[docs(faucet): add readme (#1534)](https://github.com/latticexyz/mud/commit/fa409e83db6b76422d525f7d2e9c947dc3c51262)** (@latticexyz/faucet) + +Added README + +**[fix(common): fix memory corruption for dynamic to static array conversion (#1598)](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04)** (@latticexyz/cli, @latticexyz/common) + +Table libraries now correctly handle uninitialized fixed length arrays. + +--- + ## Version 2.0.0-next.8 ### Major changes diff --git a/packages/abi-ts/CHANGELOG.md b/packages/abi-ts/CHANGELOG.md index 4410450fd1..d5b73cd002 100644 --- a/packages/abi-ts/CHANGELOG.md +++ b/packages/abi-ts/CHANGELOG.md @@ -1,5 +1,7 @@ # @latticexyz/abi-ts +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/abi-ts/package.json b/packages/abi-ts/package.json index 6eb24d5d16..51b786922c 100644 --- a/packages/abi-ts/package.json +++ b/packages/abi-ts/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/abi-ts", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Create TypeScript type declaration files (`.d.ts`) for your ABI JSON files.", "repository": { "type": "git", diff --git a/packages/block-logs-stream/CHANGELOG.md b/packages/block-logs-stream/CHANGELOG.md index dd9e7bd533..50085f7775 100644 --- a/packages/block-logs-stream/CHANGELOG.md +++ b/packages/block-logs-stream/CHANGELOG.md @@ -1,5 +1,244 @@ # @latticexyz/block-logs-stream +## 2.0.0-next.9 + +### Patch Changes + +- [#1484](https://github.com/latticexyz/mud/pull/1484) [`6573e38e`](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `table` where it is used as "table ID" to `tableId`. + This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + + ```diff + event StoreSetRecord( + - bytes32 table, + + bytes32 tableId, + bytes32[] key, + bytes data + ); + + event StoreSetField( + - bytes32 table, + + bytes32 tableId, + bytes32[] key, + uint8 fieldIndex, + bytes data + ); + + event StoreDeleteRecord( + - bytes32 table, + + bytes32 tableId, + bytes32[] key + ); + + event StoreEphemeralRecord( + - bytes32 table, + + bytes32 tableId, + bytes32[] key, + bytes data + ); + ``` + +- [#1492](https://github.com/latticexyz/mud/pull/1492) [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `key` where it is used as "key tuple" to `keyTuple`. + This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + + ```diff + event StoreSetRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + bytes data + ); + + event StoreSetField( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + uint8 fieldIndex, + bytes data + ); + + event StoreDeleteRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + ); + + event StoreEphemeralRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + bytes data + ); + ``` + +- [#1558](https://github.com/latticexyz/mud/pull/1558) [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f) Thanks [@alvrs](https://github.com/alvrs)! - What used to be known as `ephemeral` table is now called `offchain` table. + The previous `ephemeral` tables only supported an `emitEphemeral` method, which emitted a `StoreSetEphemeralRecord` event. + + Now `offchain` tables support all regular table methods, except partial operations on dynamic fields (`push`, `pop`, `update`). + Unlike regular tables they don't store data on-chain but emit the same events as regular tables (`StoreSetRecord`, `StoreSpliceStaticData`, `StoreDeleteRecord`), so their data can be indexed by offchain indexers/clients. + + ```diff + - EphemeralTable.emitEphemeral(value); + + OffchainTable.set(value); + ``` + +- [#1577](https://github.com/latticexyz/mud/pull/1577) [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c) Thanks [@alvrs](https://github.com/alvrs)! - `Store` events have been renamed for consistency and readability. + If you're parsing `Store` events manually, you need to update your ABI. + If you're using the MUD sync stack, the new events are already integrated and no further changes are necessary. + + ```diff + - event StoreSetRecord( + + event Store_SetRecord( + ResourceId indexed tableId, + bytes32[] keyTuple, + bytes staticData, + bytes32 encodedLengths, + bytes dynamicData + ); + - event StoreSpliceStaticData( + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data + ); + - event StoreSpliceDynamicData( + + event Store_SpliceDynamicData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data, + bytes32 encodedLengths + ); + - event StoreDeleteRecord( + + event Store_DeleteRecord( + ResourceId indexed tableId, + bytes32[] keyTuple + ); + ``` + +- [#1581](https://github.com/latticexyz/mud/pull/1581) [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b) Thanks [@alvrs](https://github.com/alvrs)! - - The external `setRecord` and `deleteRecord` methods of `IStore` no longer accept a `FieldLayout` as input, but load it from storage instead. + This is to prevent invalid `FieldLayout` values being passed, which could cause the onchain state to diverge from the indexer state. + However, the internal `StoreCore` library still exposes a `setRecord` and `deleteRecord` method that allows a `FieldLayout` to be passed. + This is because `StoreCore` can only be used internally, so the `FieldLayout` value can be trusted and we can save the gas for accessing storage. + + ```diff + interface IStore { + function setRecord( + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + - FieldLayout fieldLayout + ) external; + + function deleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + - FieldLayout fieldLayout + ) external; + } + ``` + + - The `spliceStaticData` method and `Store_SpliceStaticData` event of `IStore` and `StoreCore` no longer include `deleteCount` in their signature. + This is because when splicing static data, the data after `start` is always overwritten with `data` instead of being shifted, so `deleteCount` is always the length of the data to be written. + + ```diff + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + - uint40 deleteCount, + bytes data + ); + + interface IStore { + function spliceStaticData( + ResourceId tableId, + bytes32[] calldata keyTuple, + uint48 start, + - uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + + - The `updateInField` method has been removed from `IStore`, as it's almost identical to the more general `spliceDynamicData`. + If you're manually calling `updateInField`, here is how to upgrade to `spliceDynamicData`: + + ```diff + - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); + + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields(); + + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet); + ``` + + - All other methods that are only valid for dynamic fields (`pushToField`, `popFromField`, `getFieldSlice`) + have been renamed to make this more explicit (`pushToDynamicField`, `popFromDynamicField`, `getDynamicFieldSlice`). + + Their `fieldIndex` parameter has been replaced by a `dynamicFieldIndex` parameter, which is the index relative to the first dynamic field (i.e. `dynamicFieldIndex` = `fieldIndex` - `numStaticFields`). + The `FieldLayout` parameter has been removed, as it was only used to calculate the `dynamicFieldIndex` in the method. + + ```diff + interface IStore { + - function pushToField( + + function pushToDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + bytes calldata dataToPush, + - FieldLayout fieldLayout + ) external; + + - function popFromField( + + function popFromDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + uint256 byteLengthToPop, + - FieldLayout fieldLayout + ) external; + + - function getFieldSlice( + + function getDynamicFieldSlice( + ResourceId tableId, + bytes32[] memory keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + - FieldLayout fieldLayout, + uint256 start, + uint256 end + ) external view returns (bytes memory data); + } + ``` + + - `IStore` has a new `getDynamicFieldLength` length method, which returns the byte length of the given dynamic field and doesn't require the `FieldLayout`. + + ```diff + IStore { + + function getDynamicFieldLength( + + ResourceId tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex + + ) external view returns (uint256); + } + + ``` + + - `IStore` now has additional overloads for `getRecord`, `getField`, `getFieldLength` and `setField` that don't require a `FieldLength` to be passed, but instead load it from storage. + + - `IStore` now exposes `setStaticField` and `setDynamicField` to save gas by avoiding the dynamic inference of whether the field is static or dynamic. + + - The `getDynamicFieldSlice` method no longer accepts reading outside the bounds of the dynamic field. + This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero. + +- Updated dependencies [[`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b)]: + - @latticexyz/common@2.0.0-next.9 + ## 2.0.0-next.8 ### Patch Changes diff --git a/packages/block-logs-stream/package.json b/packages/block-logs-stream/package.json index 739cc8e433..7abd61c129 100644 --- a/packages/block-logs-stream/package.json +++ b/packages/block-logs-stream/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/block-logs-stream", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Create a stream of EVM block logs for events", "repository": { "type": "git", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 49f56d7598..d71f74120a 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,416 @@ # Change Log +## 2.0.0-next.9 + +### Major Changes + +- [#1482](https://github.com/latticexyz/mud/pull/1482) [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `schema` where it is used as "value schema" to `valueSchema` to clearly distinguish it from "key schema". + The only breaking change for users is the change from `schema` to `valueSchema` in `mud.config.ts`. + + ```diff + // mud.config.ts + export default mudConfig({ + tables: { + CounterTable: { + keySchema: {}, + - schema: { + + valueSchema: { + value: "uint32", + }, + }, + } + } + ``` + +- [#1336](https://github.com/latticexyz/mud/pull/1336) [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e) Thanks [@dk1a](https://github.com/dk1a)! - - Add `FieldLayout`, which is a `bytes32` user-type similar to `Schema`. + + Both `FieldLayout` and `Schema` have the same kind of data in the first 4 bytes. + + - 2 bytes for total length of all static fields + - 1 byte for number of static size fields + - 1 byte for number of dynamic size fields + + But whereas `Schema` has `SchemaType` enum in each of the other 28 bytes, `FieldLayout` has static byte lengths in each of the other 28 bytes. + + - Replace `Schema valueSchema` with `FieldLayout fieldLayout` in Store and World contracts. + + `FieldLayout` is more gas-efficient because it already has lengths, and `Schema` has types which need to be converted to lengths. + + - Add `getFieldLayout` to `IStore` interface. + + There is no `FieldLayout` for keys, only for values, because key byte lengths aren't usually relevant on-chain. You can still use `getKeySchema` if you need key types. + + - Add `fieldLayoutToHex` utility to `protocol-parser` package. + + - Add `constants.sol` for constants shared between `FieldLayout`, `Schema` and `PackedCounter`. + +- [#1575](https://github.com/latticexyz/mud/pull/1575) [`e5d208e4`](https://github.com/latticexyz/mud/commit/e5d208e40b2b2fae223b48716ce3f62c530ea1ca) Thanks [@alvrs](https://github.com/alvrs)! - The `registerRootFunctionSelector` function's signature was changed to accept a `string functionSignature` parameter instead of a `bytes4 functionSelector` parameter. + This change enables the `World` to store the function signatures of all registered functions in a `FunctionSignatures` offchain table, which will allow for the automatic generation of interfaces for a given `World` address in the future. + + ```diff + IBaseWorld { + function registerRootFunctionSelector( + ResourceId systemId, + - bytes4 worldFunctionSelector, + + string memory worldFunctionSignature, + bytes4 systemFunctionSelector + ) external returns (bytes4 worldFunctionSelector); + } + ``` + +- [#1574](https://github.com/latticexyz/mud/pull/1574) [`31ffc9d5`](https://github.com/latticexyz/mud/commit/31ffc9d5d0a6d030cc61349f0f8fbcf6748ebc48) Thanks [@alvrs](https://github.com/alvrs)! - The `registerFunctionSelector` function now accepts a single `functionSignature` string paramemer instead of separating function name and function arguments into separate parameters. + + ```diff + IBaseWorld { + function registerFunctionSelector( + ResourceId systemId, + - string memory systemFunctionName, + - string memory systemFunctionArguments + + string memory systemFunctionSignature + ) external returns (bytes4 worldFunctionSelector); + } + ``` + + This is a breaking change if you were manually registering function selectors, e.g. in a `PostDeploy.s.sol` script or a module. + To upgrade, simply replace the separate `systemFunctionName` and `systemFunctionArguments` parameters with a single `systemFunctionSignature` parameter. + + ```diff + world.registerFunctionSelector( + systemId, + - systemFunctionName, + - systemFunctionArguments, + + string(abi.encodePacked(systemFunctionName, systemFunctionArguments)) + ); + ``` + +- [#1318](https://github.com/latticexyz/mud/pull/1318) [`ac508bf1`](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130) Thanks [@holic](https://github.com/holic)! - 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"; + ``` + +- [#1544](https://github.com/latticexyz/mud/pull/1544) [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae) Thanks [@alvrs](https://github.com/alvrs)! - - `ResourceSelector` is replaced with `ResourceId`, `ResourceIdLib`, `ResourceIdInstance`, `WorldResourceIdLib` and `WorldResourceIdInstance`. + + Previously a "resource selector" was a `bytes32` value with the first 16 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + Now a "resource ID" is a `bytes32` value with the first 2 bytes reserved for the resource type, the next 14 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + + Previously `ResouceSelector` was a library and the resource selector type was a plain `bytes32`. + Now `ResourceId` is a user type, and the functionality is implemented in the `ResourceIdInstance` (for type) and `WorldResourceIdInstance` (for namespace and name) libraries. + We split the logic into two libraries, because `Store` now also uses `ResourceId` and needs to be aware of resource types, but not of namespaces/names. + + ```diff + - import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol"; + + import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; + + import { WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol"; + + import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol"; + + - bytes32 systemId = ResourceSelector.from("namespace", "name"); + + ResourceId systemId = WorldResourceIdLib.encode(RESOURCE_SYSTEM, "namespace", "name"); + + - using ResourceSelector for bytes32; + + using WorldResourceIdInstance for ResourceId; + + using ResourceIdInstance for ResourceId; + + systemId.getName(); + systemId.getNamespace(); + + systemId.getType(); + + ``` + + - All `Store` and `World` methods now use the `ResourceId` type for `tableId`, `systemId`, `moduleId` and `namespaceId`. + All mentions of `resourceSelector` were renamed to `resourceId` or the more specific type (e.g. `tableId`, `systemId`) + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IStore { + function setRecord( + - bytes32 tableId, + + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + FieldLayout fieldLayout + ) external; + + // Same for all other methods + } + ``` + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IBaseWorld { + function callFrom( + address delegator, + - bytes32 resourceSelector, + + ResourceId systemId, + bytes memory callData + ) external payable returns (bytes memory); + + // Same for all other methods + } + ``` + +### Minor Changes + +- [#1473](https://github.com/latticexyz/mud/pull/1473) [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a) Thanks [@holic](https://github.com/holic)! - Bump Solidity version to 0.8.21 + +### Patch Changes + +- [#1490](https://github.com/latticexyz/mud/pull/1490) [`aea67c58`](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84) Thanks [@alvrs](https://github.com/alvrs)! - Include bytecode for `World` and `Store` in npm packages. + +- [#1592](https://github.com/latticexyz/mud/pull/1592) [`c07fa021`](https://github.com/latticexyz/mud/commit/c07fa021501ff92be35c0491dd89bbb8161e1c07) Thanks [@alvrs](https://github.com/alvrs)! - Tables and interfaces in the `world` package are now generated to the `codegen` folder. + This is only a breaking change if you imported tables or codegenerated interfaces from `@latticexyz/world` directly. + If you're using the MUD CLI, the changed import paths are already integrated and no further changes are necessary. + + ```diff + - import { IBaseWorld } from "@latticexyz/world/src/interfaces/IBaseWorld.sol"; + + import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol"; + + ``` + +- [#1508](https://github.com/latticexyz/mud/pull/1508) [`211be2a1`](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9) Thanks [@Boffee](https://github.com/Boffee)! - 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. + +- [#1503](https://github.com/latticexyz/mud/pull/1503) [`bd9cc8ec`](https://github.com/latticexyz/mud/commit/bd9cc8ec2608efcb05ef95df64448b2ec28bcb49) Thanks [@holic](https://github.com/holic)! - Refactor `deploy` command to break up logic into modules + +- [#1558](https://github.com/latticexyz/mud/pull/1558) [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f) Thanks [@alvrs](https://github.com/alvrs)! - What used to be known as `ephemeral` table is now called `offchain` table. + The previous `ephemeral` tables only supported an `emitEphemeral` method, which emitted a `StoreSetEphemeralRecord` event. + + Now `offchain` tables support all regular table methods, except partial operations on dynamic fields (`push`, `pop`, `update`). + Unlike regular tables they don't store data on-chain but emit the same events as regular tables (`StoreSetRecord`, `StoreSpliceStaticData`, `StoreDeleteRecord`), so their data can be indexed by offchain indexers/clients. + + ```diff + - EphemeralTable.emitEphemeral(value); + + OffchainTable.set(value); + ``` + +- [#1521](https://github.com/latticexyz/mud/pull/1521) [`55ab88a6`](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314) Thanks [@alvrs](https://github.com/alvrs)! - `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); + } + ``` + +- [#1483](https://github.com/latticexyz/mud/pull/1483) [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab) Thanks [@holic](https://github.com/holic)! - `deploy` and `dev-contracts` CLI commands now use `forge build --skip test script` before deploying and run `mud abi-ts` to generate strong types for ABIs. + +- [#1587](https://github.com/latticexyz/mud/pull/1587) [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d) Thanks [@alvrs](https://github.com/alvrs)! - Changed the `userTypes` property to accept `{ filePath: string, internalType: SchemaAbiType }` to enable strong type inference from the config. + +- [#1513](https://github.com/latticexyz/mud/pull/1513) [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280) Thanks [@Boffee](https://github.com/Boffee)! - 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 + } + ``` + +- [#1472](https://github.com/latticexyz/mud/pull/1472) [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf) Thanks [@alvrs](https://github.com/alvrs)! - - The `World` contract now has an `initialize` function, which can be called once by the creator of the World to install the core module. + This change allows the registration of all core tables to happen in the `CoreModule`, so no table metadata has to be included in the `World`'s bytecode. + + ```solidity + interface IBaseWorld { + function initialize(IModule coreModule) public; + } + ``` + + - The `World` contract now stores the original creator of the `World` in an immutable state variable. + It is used internally to only allow the original creator to initialize the `World` in a separate transaction. + + ```solidity + interface IBaseWorld { + function creator() external view returns (address); + } + ``` + + - The deploy script is updated to use the `World`'s `initialize` function to install the `CoreModule` instead of `registerRootModule` as before. + +- [#1591](https://github.com/latticexyz/mud/pull/1591) [`251170e1`](https://github.com/latticexyz/mud/commit/251170e1ef0b07466c597ea84df0cb49de7d6a23) Thanks [@alvrs](https://github.com/alvrs)! - All optional modules have been moved from `@latticexyz/world` to `@latticexyz/world-modules`. + If you're using the MUD CLI, the import is already updated and no changes are necessary. + +- [#1598](https://github.com/latticexyz/mud/pull/1598) [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04) Thanks [@dk1a](https://github.com/dk1a)! - Table libraries now correctly handle uninitialized fixed length arrays. + +- [#1581](https://github.com/latticexyz/mud/pull/1581) [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b) Thanks [@alvrs](https://github.com/alvrs)! - - The external `setRecord` and `deleteRecord` methods of `IStore` no longer accept a `FieldLayout` as input, but load it from storage instead. + This is to prevent invalid `FieldLayout` values being passed, which could cause the onchain state to diverge from the indexer state. + However, the internal `StoreCore` library still exposes a `setRecord` and `deleteRecord` method that allows a `FieldLayout` to be passed. + This is because `StoreCore` can only be used internally, so the `FieldLayout` value can be trusted and we can save the gas for accessing storage. + + ```diff + interface IStore { + function setRecord( + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + - FieldLayout fieldLayout + ) external; + + function deleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + - FieldLayout fieldLayout + ) external; + } + ``` + + - The `spliceStaticData` method and `Store_SpliceStaticData` event of `IStore` and `StoreCore` no longer include `deleteCount` in their signature. + This is because when splicing static data, the data after `start` is always overwritten with `data` instead of being shifted, so `deleteCount` is always the length of the data to be written. + + ```diff + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + - uint40 deleteCount, + bytes data + ); + + interface IStore { + function spliceStaticData( + ResourceId tableId, + bytes32[] calldata keyTuple, + uint48 start, + - uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + + - The `updateInField` method has been removed from `IStore`, as it's almost identical to the more general `spliceDynamicData`. + If you're manually calling `updateInField`, here is how to upgrade to `spliceDynamicData`: + + ```diff + - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); + + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields(); + + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet); + ``` + + - All other methods that are only valid for dynamic fields (`pushToField`, `popFromField`, `getFieldSlice`) + have been renamed to make this more explicit (`pushToDynamicField`, `popFromDynamicField`, `getDynamicFieldSlice`). + + Their `fieldIndex` parameter has been replaced by a `dynamicFieldIndex` parameter, which is the index relative to the first dynamic field (i.e. `dynamicFieldIndex` = `fieldIndex` - `numStaticFields`). + The `FieldLayout` parameter has been removed, as it was only used to calculate the `dynamicFieldIndex` in the method. + + ```diff + interface IStore { + - function pushToField( + + function pushToDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + bytes calldata dataToPush, + - FieldLayout fieldLayout + ) external; + + - function popFromField( + + function popFromDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + uint256 byteLengthToPop, + - FieldLayout fieldLayout + ) external; + + - function getFieldSlice( + + function getDynamicFieldSlice( + ResourceId tableId, + bytes32[] memory keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + - FieldLayout fieldLayout, + uint256 start, + uint256 end + ) external view returns (bytes memory data); + } + ``` + + - `IStore` has a new `getDynamicFieldLength` length method, which returns the byte length of the given dynamic field and doesn't require the `FieldLayout`. + + ```diff + IStore { + + function getDynamicFieldLength( + + ResourceId tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex + + ) external view returns (uint256); + } + + ``` + + - `IStore` now has additional overloads for `getRecord`, `getField`, `getFieldLength` and `setField` that don't require a `FieldLength` to be passed, but instead load it from storage. + + - `IStore` now exposes `setStaticField` and `setDynamicField` to save gas by avoiding the dynamic inference of whether the field is static or dynamic. + + - The `getDynamicFieldSlice` method no longer accepts reading outside the bounds of the dynamic field. + This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero. + +- Updated dependencies [[`748f4588`](https://github.com/latticexyz/mud/commit/748f4588a218928bca041760448c26991c0d8033), [`aea67c58`](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84), [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9), [`c07fa021`](https://github.com/latticexyz/mud/commit/c07fa021501ff92be35c0491dd89bbb8161e1c07), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`f9f9609e`](https://github.com/latticexyz/mud/commit/f9f9609ef69d7fa58cad6a9af3fe6d2eed6d8aa2), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`759514d8`](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8), [`d5094a24`](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4), [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96), [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e), [`ae340b2b`](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623), [`e5d208e4`](https://github.com/latticexyz/mud/commit/e5d208e40b2b2fae223b48716ce3f62c530ea1ca), [`211be2a1`](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9), [`0f3e2e02`](https://github.com/latticexyz/mud/commit/0f3e2e02b5114e08fe700c18326db76816ffad3c), [`1f80a0b5`](https://github.com/latticexyz/mud/commit/1f80a0b52a5c2d051e3697d6e60aad7364b0a925), [`d0878928`](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c), [`4c7fd3eb`](https://github.com/latticexyz/mud/commit/4c7fd3eb29e3d3954f2f1f36ace474a436082651), [`a0341daf`](https://github.com/latticexyz/mud/commit/a0341daf9fd87e8072ffa292a33f508dd37b8ca6), [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`6573e38e`](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`f8a01a04`](https://github.com/latticexyz/mud/commit/f8a01a047d73a15326ebf6577ea033674d8e61a9), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`f1cd43bf`](https://github.com/latticexyz/mud/commit/f1cd43bf9264d5a23a3edf2a1ea4212361a72203), [`31ffc9d5`](https://github.com/latticexyz/mud/commit/31ffc9d5d0a6d030cc61349f0f8fbcf6748ebc48), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`63831a26`](https://github.com/latticexyz/mud/commit/63831a264b6b09501f380a4601f82ba7bf07a619), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`5741d53d`](https://github.com/latticexyz/mud/commit/5741d53d0a39990a0d7b2842f1f012973655e060), [`22ee4470`](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612), [`be313068`](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87), [`ac508bf1`](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130), [`9ff4dd95`](https://github.com/latticexyz/mud/commit/9ff4dd955fd6dca36eb15cfe7e46bb522d2e943b), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`9b43029c`](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7), [`55ab88a6`](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314), [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`99ab9cd6`](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`80dd6992`](https://github.com/latticexyz/mud/commit/80dd6992e98c90a91d417fc785d0d53260df6ce2), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`22ba7b67`](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`251170e1`](https://github.com/latticexyz/mud/commit/251170e1ef0b07466c597ea84df0cb49de7d6a23), [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b), [`95c59b20`](https://github.com/latticexyz/mud/commit/95c59b203259c20a6f944c5f9af008b44e2902b6)]: + - @latticexyz/world@2.0.0-next.9 + - @latticexyz/store@2.0.0-next.9 + - @latticexyz/protocol-parser@2.0.0-next.9 + - @latticexyz/world-modules@2.0.0-next.9 + - @latticexyz/common@2.0.0-next.9 + - @latticexyz/gas-report@2.0.0-next.9 + - @latticexyz/schema-type@2.0.0-next.9 + - @latticexyz/config@2.0.0-next.9 + - @latticexyz/abi-ts@2.0.0-next.9 + - @latticexyz/services@2.0.0-next.9 + - @latticexyz/utils@2.0.0-next.9 + ## 2.0.0-next.8 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 0c88d7b846..5bffe9e741 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/cli", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Command line interface for mud", "repository": { "type": "git", diff --git a/packages/common/CHANGELOG.md b/packages/common/CHANGELOG.md index 521aefc567..e4d0480d4c 100644 --- a/packages/common/CHANGELOG.md +++ b/packages/common/CHANGELOG.md @@ -1,5 +1,251 @@ # Change Log +## 2.0.0-next.9 + +### Major Changes + +- [#1550](https://github.com/latticexyz/mud/pull/1550) [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e) Thanks [@dk1a](https://github.com/dk1a)! - - Add `renderWithFieldSuffix` helper method to always render a field function with a suffix, and optionally render the same function without a suffix. + + - Remove `methodNameSuffix` from `RenderField` interface, because the suffix is now computed as part of `renderWithFieldSuffix`. + +- [#1558](https://github.com/latticexyz/mud/pull/1558) [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f) Thanks [@alvrs](https://github.com/alvrs)! - What used to be known as `ephemeral` table is now called `offchain` table. + The previous `ephemeral` tables only supported an `emitEphemeral` method, which emitted a `StoreSetEphemeralRecord` event. + + Now `offchain` tables support all regular table methods, except partial operations on dynamic fields (`push`, `pop`, `update`). + Unlike regular tables they don't store data on-chain but emit the same events as regular tables (`StoreSetRecord`, `StoreSpliceStaticData`, `StoreDeleteRecord`), so their data can be indexed by offchain indexers/clients. + + ```diff + - EphemeralTable.emitEphemeral(value); + + OffchainTable.set(value); + ``` + +- [#1544](https://github.com/latticexyz/mud/pull/1544) [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae) Thanks [@alvrs](https://github.com/alvrs)! - - `ResourceSelector` is replaced with `ResourceId`, `ResourceIdLib`, `ResourceIdInstance`, `WorldResourceIdLib` and `WorldResourceIdInstance`. + + Previously a "resource selector" was a `bytes32` value with the first 16 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + Now a "resource ID" is a `bytes32` value with the first 2 bytes reserved for the resource type, the next 14 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + + Previously `ResouceSelector` was a library and the resource selector type was a plain `bytes32`. + Now `ResourceId` is a user type, and the functionality is implemented in the `ResourceIdInstance` (for type) and `WorldResourceIdInstance` (for namespace and name) libraries. + We split the logic into two libraries, because `Store` now also uses `ResourceId` and needs to be aware of resource types, but not of namespaces/names. + + ```diff + - import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol"; + + import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; + + import { WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol"; + + import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol"; + + - bytes32 systemId = ResourceSelector.from("namespace", "name"); + + ResourceId systemId = WorldResourceIdLib.encode(RESOURCE_SYSTEM, "namespace", "name"); + + - using ResourceSelector for bytes32; + + using WorldResourceIdInstance for ResourceId; + + using ResourceIdInstance for ResourceId; + + systemId.getName(); + systemId.getNamespace(); + + systemId.getType(); + + ``` + + - All `Store` and `World` methods now use the `ResourceId` type for `tableId`, `systemId`, `moduleId` and `namespaceId`. + All mentions of `resourceSelector` were renamed to `resourceId` or the more specific type (e.g. `tableId`, `systemId`) + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IStore { + function setRecord( + - bytes32 tableId, + + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + FieldLayout fieldLayout + ) external; + + // Same for all other methods + } + ``` + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IBaseWorld { + function callFrom( + address delegator, + - bytes32 resourceSelector, + + ResourceId systemId, + bytes memory callData + ) external payable returns (bytes memory); + + // Same for all other methods + } + ``` + +### Minor Changes + +- [#1354](https://github.com/latticexyz/mud/pull/1354) [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853) Thanks [@dk1a](https://github.com/dk1a)! - `readHex` was moved from `@latticexyz/protocol-parser` to `@latticexyz/common` + +- [#1566](https://github.com/latticexyz/mud/pull/1566) [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9) Thanks [@dk1a](https://github.com/dk1a)! - - Add `getRemappings` to get foundry remappings as an array of `[to, from]` tuples. + + - Add `extractUserTypes` solidity parser utility to extract user-defined types. + - Add `loadAndExtractUserTypes` helper to load and parse a solidity file, extracting user-defined types. + +- [#1354](https://github.com/latticexyz/mud/pull/1354) [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853) Thanks [@dk1a](https://github.com/dk1a)! - `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" + ``` + +- [#1473](https://github.com/latticexyz/mud/pull/1473) [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a) Thanks [@holic](https://github.com/holic)! - Bump Solidity version to 0.8.21 + +- [#1513](https://github.com/latticexyz/mud/pull/1513) [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280) Thanks [@Boffee](https://github.com/Boffee)! - 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 + } + ``` + +- [#1581](https://github.com/latticexyz/mud/pull/1581) [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b) Thanks [@alvrs](https://github.com/alvrs)! - - The external `setRecord` and `deleteRecord` methods of `IStore` no longer accept a `FieldLayout` as input, but load it from storage instead. + This is to prevent invalid `FieldLayout` values being passed, which could cause the onchain state to diverge from the indexer state. + However, the internal `StoreCore` library still exposes a `setRecord` and `deleteRecord` method that allows a `FieldLayout` to be passed. + This is because `StoreCore` can only be used internally, so the `FieldLayout` value can be trusted and we can save the gas for accessing storage. + + ```diff + interface IStore { + function setRecord( + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + - FieldLayout fieldLayout + ) external; + + function deleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + - FieldLayout fieldLayout + ) external; + } + ``` + + - The `spliceStaticData` method and `Store_SpliceStaticData` event of `IStore` and `StoreCore` no longer include `deleteCount` in their signature. + This is because when splicing static data, the data after `start` is always overwritten with `data` instead of being shifted, so `deleteCount` is always the length of the data to be written. + + ```diff + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + - uint40 deleteCount, + bytes data + ); + + interface IStore { + function spliceStaticData( + ResourceId tableId, + bytes32[] calldata keyTuple, + uint48 start, + - uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + + - The `updateInField` method has been removed from `IStore`, as it's almost identical to the more general `spliceDynamicData`. + If you're manually calling `updateInField`, here is how to upgrade to `spliceDynamicData`: + + ```diff + - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); + + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields(); + + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet); + ``` + + - All other methods that are only valid for dynamic fields (`pushToField`, `popFromField`, `getFieldSlice`) + have been renamed to make this more explicit (`pushToDynamicField`, `popFromDynamicField`, `getDynamicFieldSlice`). + + Their `fieldIndex` parameter has been replaced by a `dynamicFieldIndex` parameter, which is the index relative to the first dynamic field (i.e. `dynamicFieldIndex` = `fieldIndex` - `numStaticFields`). + The `FieldLayout` parameter has been removed, as it was only used to calculate the `dynamicFieldIndex` in the method. + + ```diff + interface IStore { + - function pushToField( + + function pushToDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + bytes calldata dataToPush, + - FieldLayout fieldLayout + ) external; + + - function popFromField( + + function popFromDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + uint256 byteLengthToPop, + - FieldLayout fieldLayout + ) external; + + - function getFieldSlice( + + function getDynamicFieldSlice( + ResourceId tableId, + bytes32[] memory keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + - FieldLayout fieldLayout, + uint256 start, + uint256 end + ) external view returns (bytes memory data); + } + ``` + + - `IStore` has a new `getDynamicFieldLength` length method, which returns the byte length of the given dynamic field and doesn't require the `FieldLayout`. + + ```diff + IStore { + + function getDynamicFieldLength( + + ResourceId tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex + + ) external view returns (uint256); + } + + ``` + + - `IStore` now has additional overloads for `getRecord`, `getField`, `getFieldLength` and `setField` that don't require a `FieldLength` to be passed, but instead load it from storage. + + - `IStore` now exposes `setStaticField` and `setDynamicField` to save gas by avoiding the dynamic inference of whether the field is static or dynamic. + + - The `getDynamicFieldSlice` method no longer accepts reading outside the bounds of the dynamic field. + This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero. + +### Patch Changes + +- [#1585](https://github.com/latticexyz/mud/pull/1585) [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96) Thanks [@alvrs](https://github.com/alvrs)! - Minor fix to resolving user types: `solc` doesn't like relative imports without `./`, but is fine with relative imports from `./../`, so we always append `./` to the relative path. + +- [#1587](https://github.com/latticexyz/mud/pull/1587) [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d) Thanks [@alvrs](https://github.com/alvrs)! - Changed the `userTypes` property to accept `{ filePath: string, internalType: SchemaAbiType }` to enable strong type inference from the config. + +- [#1598](https://github.com/latticexyz/mud/pull/1598) [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04) Thanks [@dk1a](https://github.com/dk1a)! - Table libraries now correctly handle uninitialized fixed length arrays. + +- Updated dependencies [[`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a)]: + - @latticexyz/schema-type@2.0.0-next.9 + ## 2.0.0-next.8 ### Patch Changes diff --git a/packages/common/package.json b/packages/common/package.json index e269b73d8f..280a425bdf 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/common", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Common low level logic shared between packages", "repository": { "type": "git", diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index cd74617d7c..e0d4128cef 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,79 @@ # Change Log +## 2.0.0-next.9 + +### Major Changes + +- [#1544](https://github.com/latticexyz/mud/pull/1544) [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae) Thanks [@alvrs](https://github.com/alvrs)! - - `ResourceSelector` is replaced with `ResourceId`, `ResourceIdLib`, `ResourceIdInstance`, `WorldResourceIdLib` and `WorldResourceIdInstance`. + + Previously a "resource selector" was a `bytes32` value with the first 16 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + Now a "resource ID" is a `bytes32` value with the first 2 bytes reserved for the resource type, the next 14 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + + Previously `ResouceSelector` was a library and the resource selector type was a plain `bytes32`. + Now `ResourceId` is a user type, and the functionality is implemented in the `ResourceIdInstance` (for type) and `WorldResourceIdInstance` (for namespace and name) libraries. + We split the logic into two libraries, because `Store` now also uses `ResourceId` and needs to be aware of resource types, but not of namespaces/names. + + ```diff + - import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol"; + + import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; + + import { WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol"; + + import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol"; + + - bytes32 systemId = ResourceSelector.from("namespace", "name"); + + ResourceId systemId = WorldResourceIdLib.encode(RESOURCE_SYSTEM, "namespace", "name"); + + - using ResourceSelector for bytes32; + + using WorldResourceIdInstance for ResourceId; + + using ResourceIdInstance for ResourceId; + + systemId.getName(); + systemId.getNamespace(); + + systemId.getType(); + + ``` + + - All `Store` and `World` methods now use the `ResourceId` type for `tableId`, `systemId`, `moduleId` and `namespaceId`. + All mentions of `resourceSelector` were renamed to `resourceId` or the more specific type (e.g. `tableId`, `systemId`) + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IStore { + function setRecord( + - bytes32 tableId, + + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + FieldLayout fieldLayout + ) external; + + // Same for all other methods + } + ``` + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IBaseWorld { + function callFrom( + address delegator, + - bytes32 resourceSelector, + + ResourceId systemId, + bytes memory callData + ) external payable returns (bytes memory); + + // Same for all other methods + } + ``` + +### Patch Changes + +- Updated dependencies [[`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b)]: + - @latticexyz/common@2.0.0-next.9 + - @latticexyz/schema-type@2.0.0-next.9 + ## 2.0.0-next.8 ### Patch Changes diff --git a/packages/config/package.json b/packages/config/package.json index c40af6e11d..3b905a9372 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/config", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Config for Store and World", "repository": { "type": "git", diff --git a/packages/create-mud/CHANGELOG.md b/packages/create-mud/CHANGELOG.md index 2a64f39d79..30dc1e1a3b 100644 --- a/packages/create-mud/CHANGELOG.md +++ b/packages/create-mud/CHANGELOG.md @@ -1,5 +1,204 @@ # Change Log +## 2.0.0-next.9 + +### Minor Changes + +- [#1482](https://github.com/latticexyz/mud/pull/1482) [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `schema` where it is used as "value schema" to `valueSchema` to clearly distinguish it from "key schema". + The only breaking change for users is the change from `schema` to `valueSchema` in `mud.config.ts`. + + ```diff + // mud.config.ts + export default mudConfig({ + tables: { + CounterTable: { + keySchema: {}, + - schema: { + + valueSchema: { + value: "uint32", + }, + }, + } + } + ``` + +- [#1483](https://github.com/latticexyz/mud/pull/1483) [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab) Thanks [@holic](https://github.com/holic)! - Templates now use `out` for their `forge build` artifacts, including ABIs. If you have a project created from a previous template, you can update your `packages/contracts/package.json` with: + + ```diff + - "build:abi": "rimraf abi && forge build --extra-output-files abi --out abi --skip test script MudTest.sol", + - "build:abi-ts": "mud abi-ts --input 'abi/IWorld.sol/IWorld.abi.json' && prettier --write '**/*.abi.json.d.ts'", + + "build:abi": "forge clean && forge build --skip test script", + + "build:abi-ts": "mud abi-ts && prettier --write '**/*.abi.json.d.ts'", + ``` + + And your `packages/client/src/mud/setupNetwork` with: + + ```diff + - import IWorldAbi from "contracts/abi/IWorld.sol/IWorld.abi.json"; + + import IWorldAbi from "contracts/out/IWorld.sol/IWorld.abi.json"; + ``` + +- [#1473](https://github.com/latticexyz/mud/pull/1473) [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a) Thanks [@holic](https://github.com/holic)! - Bump Solidity version to 0.8.21 + +- [#1354](https://github.com/latticexyz/mud/pull/1354) [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853) Thanks [@dk1a](https://github.com/dk1a)! - 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# Change Log with `storedBlockLogs# Change Log, 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. + +- [#1558](https://github.com/latticexyz/mud/pull/1558) [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f) Thanks [@alvrs](https://github.com/alvrs)! - What used to be known as `ephemeral` table is now called `offchain` table. + The previous `ephemeral` tables only supported an `emitEphemeral` method, which emitted a `StoreSetEphemeralRecord` event. + + Now `offchain` tables support all regular table methods, except partial operations on dynamic fields (`push`, `pop`, `update`). + Unlike regular tables they don't store data on-chain but emit the same events as regular tables (`StoreSetRecord`, `StoreSpliceStaticData`, `StoreDeleteRecord`), so their data can be indexed by offchain indexers/clients. + + ```diff + - EphemeralTable.emitEphemeral(value); + + OffchainTable.set(value); + ``` + +### Patch Changes + +- [#1318](https://github.com/latticexyz/mud/pull/1318) [`ac508bf1`](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130) Thanks [@holic](https://github.com/holic)! - 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"; + ``` + +- [#1581](https://github.com/latticexyz/mud/pull/1581) [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b) Thanks [@alvrs](https://github.com/alvrs)! - - The external `setRecord` and `deleteRecord` methods of `IStore` no longer accept a `FieldLayout` as input, but load it from storage instead. + This is to prevent invalid `FieldLayout` values being passed, which could cause the onchain state to diverge from the indexer state. + However, the internal `StoreCore` library still exposes a `setRecord` and `deleteRecord` method that allows a `FieldLayout` to be passed. + This is because `StoreCore` can only be used internally, so the `FieldLayout` value can be trusted and we can save the gas for accessing storage. + + ```diff + interface IStore { + function setRecord( + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + - FieldLayout fieldLayout + ) external; + + function deleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + - FieldLayout fieldLayout + ) external; + } + ``` + + - The `spliceStaticData` method and `Store_SpliceStaticData` event of `IStore` and `StoreCore` no longer include `deleteCount` in their signature. + This is because when splicing static data, the data after `start` is always overwritten with `data` instead of being shifted, so `deleteCount` is always the length of the data to be written. + + ```diff + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + - uint40 deleteCount, + bytes data + ); + + interface IStore { + function spliceStaticData( + ResourceId tableId, + bytes32[] calldata keyTuple, + uint48 start, + - uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + + - The `updateInField` method has been removed from `IStore`, as it's almost identical to the more general `spliceDynamicData`. + If you're manually calling `updateInField`, here is how to upgrade to `spliceDynamicData`: + + ```diff + - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); + + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields(); + + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet); + ``` + + - All other methods that are only valid for dynamic fields (`pushToField`, `popFromField`, `getFieldSlice`) + have been renamed to make this more explicit (`pushToDynamicField`, `popFromDynamicField`, `getDynamicFieldSlice`). + + Their `fieldIndex` parameter has been replaced by a `dynamicFieldIndex` parameter, which is the index relative to the first dynamic field (i.e. `dynamicFieldIndex` = `fieldIndex` - `numStaticFields`). + The `FieldLayout` parameter has been removed, as it was only used to calculate the `dynamicFieldIndex` in the method. + + ```diff + interface IStore { + - function pushToField( + + function pushToDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + bytes calldata dataToPush, + - FieldLayout fieldLayout + ) external; + + - function popFromField( + + function popFromDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + uint256 byteLengthToPop, + - FieldLayout fieldLayout + ) external; + + - function getFieldSlice( + + function getDynamicFieldSlice( + ResourceId tableId, + bytes32[] memory keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + - FieldLayout fieldLayout, + uint256 start, + uint256 end + ) external view returns (bytes memory data); + } + ``` + + - `IStore` has a new `getDynamicFieldLength` length method, which returns the byte length of the given dynamic field and doesn't require the `FieldLayout`. + + ```diff + IStore { + + function getDynamicFieldLength( + + ResourceId tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex + + ) external view returns (uint256); + } + + ``` + + - `IStore` now has additional overloads for `getRecord`, `getField`, `getFieldLength` and `setField` that don't require a `FieldLength` to be passed, but instead load it from storage. + + - `IStore` now exposes `setStaticField` and `setDynamicField` to save gas by avoiding the dynamic inference of whether the field is static or dynamic. + + - The `getDynamicFieldSlice` method no longer accepts reading outside the bounds of the dynamic field. + This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero. + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/create-mud/package.json b/packages/create-mud/package.json index 0a7d9ce420..fbc0f232ab 100644 --- a/packages/create-mud/package.json +++ b/packages/create-mud/package.json @@ -1,6 +1,6 @@ { "name": "create-mud", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Create a new MUD project", "license": "MIT", "author": "Lattice ", diff --git a/packages/dev-tools/CHANGELOG.md b/packages/dev-tools/CHANGELOG.md index 10c12d7fa8..9458eefed7 100644 --- a/packages/dev-tools/CHANGELOG.md +++ b/packages/dev-tools/CHANGELOG.md @@ -1,5 +1,198 @@ # @latticexyz/dev-tools +## 2.0.0-next.9 + +### Major Changes + +- [#1354](https://github.com/latticexyz/mud/pull/1354) [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853) Thanks [@dk1a](https://github.com/dk1a)! - 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# @latticexyz/dev-tools with `storedBlockLogs# @latticexyz/dev-tools, 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. + +### Minor Changes + +- [#1497](https://github.com/latticexyz/mud/pull/1497) [`24a0dd44`](https://github.com/latticexyz/mud/commit/24a0dd4440d6fe661640c581ff5348d62eae9302) Thanks [@y77cao](https://github.com/y77cao)! - Improved rendering of transactions that make calls via World's `call` and `callFrom` methods + +### Patch Changes + +- [#1505](https://github.com/latticexyz/mud/pull/1505) [`e0193e57`](https://github.com/latticexyz/mud/commit/e0193e5737fa2148d5d2b888d71df01d1e46b6d5) Thanks [@holic](https://github.com/holic)! - Updates store event `key` reference to `keyTuple` + +- [#1502](https://github.com/latticexyz/mud/pull/1502) [`e0377761`](https://github.com/latticexyz/mud/commit/e0377761c3a3f83a23de78f6bcb0733c500a0825) Thanks [@holic](https://github.com/holic)! - Updates `table` reference to `tableId` + +- [#1558](https://github.com/latticexyz/mud/pull/1558) [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f) Thanks [@alvrs](https://github.com/alvrs)! - What used to be known as `ephemeral` table is now called `offchain` table. + The previous `ephemeral` tables only supported an `emitEphemeral` method, which emitted a `StoreSetEphemeralRecord` event. + + Now `offchain` tables support all regular table methods, except partial operations on dynamic fields (`push`, `pop`, `update`). + Unlike regular tables they don't store data on-chain but emit the same events as regular tables (`StoreSetRecord`, `StoreSpliceStaticData`, `StoreDeleteRecord`), so their data can be indexed by offchain indexers/clients. + + ```diff + - EphemeralTable.emitEphemeral(value); + + OffchainTable.set(value); + ``` + +- [#1577](https://github.com/latticexyz/mud/pull/1577) [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c) Thanks [@alvrs](https://github.com/alvrs)! - `Store` events have been renamed for consistency and readability. + If you're parsing `Store` events manually, you need to update your ABI. + If you're using the MUD sync stack, the new events are already integrated and no further changes are necessary. + + ```diff + - event StoreSetRecord( + + event Store_SetRecord( + ResourceId indexed tableId, + bytes32[] keyTuple, + bytes staticData, + bytes32 encodedLengths, + bytes dynamicData + ); + - event StoreSpliceStaticData( + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data + ); + - event StoreSpliceDynamicData( + + event Store_SpliceDynamicData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data, + bytes32 encodedLengths + ); + - event StoreDeleteRecord( + + event Store_DeleteRecord( + ResourceId indexed tableId, + bytes32[] keyTuple + ); + ``` + +- [#1581](https://github.com/latticexyz/mud/pull/1581) [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b) Thanks [@alvrs](https://github.com/alvrs)! - - The external `setRecord` and `deleteRecord` methods of `IStore` no longer accept a `FieldLayout` as input, but load it from storage instead. + This is to prevent invalid `FieldLayout` values being passed, which could cause the onchain state to diverge from the indexer state. + However, the internal `StoreCore` library still exposes a `setRecord` and `deleteRecord` method that allows a `FieldLayout` to be passed. + This is because `StoreCore` can only be used internally, so the `FieldLayout` value can be trusted and we can save the gas for accessing storage. + + ```diff + interface IStore { + function setRecord( + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + - FieldLayout fieldLayout + ) external; + + function deleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + - FieldLayout fieldLayout + ) external; + } + ``` + + - The `spliceStaticData` method and `Store_SpliceStaticData` event of `IStore` and `StoreCore` no longer include `deleteCount` in their signature. + This is because when splicing static data, the data after `start` is always overwritten with `data` instead of being shifted, so `deleteCount` is always the length of the data to be written. + + ```diff + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + - uint40 deleteCount, + bytes data + ); + + interface IStore { + function spliceStaticData( + ResourceId tableId, + bytes32[] calldata keyTuple, + uint48 start, + - uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + + - The `updateInField` method has been removed from `IStore`, as it's almost identical to the more general `spliceDynamicData`. + If you're manually calling `updateInField`, here is how to upgrade to `spliceDynamicData`: + + ```diff + - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); + + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields(); + + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet); + ``` + + - All other methods that are only valid for dynamic fields (`pushToField`, `popFromField`, `getFieldSlice`) + have been renamed to make this more explicit (`pushToDynamicField`, `popFromDynamicField`, `getDynamicFieldSlice`). + + Their `fieldIndex` parameter has been replaced by a `dynamicFieldIndex` parameter, which is the index relative to the first dynamic field (i.e. `dynamicFieldIndex` = `fieldIndex` - `numStaticFields`). + The `FieldLayout` parameter has been removed, as it was only used to calculate the `dynamicFieldIndex` in the method. + + ```diff + interface IStore { + - function pushToField( + + function pushToDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + bytes calldata dataToPush, + - FieldLayout fieldLayout + ) external; + + - function popFromField( + + function popFromDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + uint256 byteLengthToPop, + - FieldLayout fieldLayout + ) external; + + - function getFieldSlice( + + function getDynamicFieldSlice( + ResourceId tableId, + bytes32[] memory keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + - FieldLayout fieldLayout, + uint256 start, + uint256 end + ) external view returns (bytes memory data); + } + ``` + + - `IStore` has a new `getDynamicFieldLength` length method, which returns the byte length of the given dynamic field and doesn't require the `FieldLayout`. + + ```diff + IStore { + + function getDynamicFieldLength( + + ResourceId tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex + + ) external view returns (uint256); + } + + ``` + + - `IStore` now has additional overloads for `getRecord`, `getField`, `getFieldLength` and `setField` that don't require a `FieldLength` to be passed, but instead load it from storage. + + - `IStore` now exposes `setStaticField` and `setDynamicField` to save gas by avoiding the dynamic inference of whether the field is static or dynamic. + + - The `getDynamicFieldSlice` method no longer accepts reading outside the bounds of the dynamic field. + This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero. + +- Updated dependencies [[`748f4588`](https://github.com/latticexyz/mud/commit/748f4588a218928bca041760448c26991c0d8033), [`aea67c58`](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84), [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9), [`c07fa021`](https://github.com/latticexyz/mud/commit/c07fa021501ff92be35c0491dd89bbb8161e1c07), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`f9f9609e`](https://github.com/latticexyz/mud/commit/f9f9609ef69d7fa58cad6a9af3fe6d2eed6d8aa2), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`759514d8`](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8), [`d5094a24`](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4), [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96), [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e), [`ae340b2b`](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623), [`e5d208e4`](https://github.com/latticexyz/mud/commit/e5d208e40b2b2fae223b48716ce3f62c530ea1ca), [`211be2a1`](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9), [`0f3e2e02`](https://github.com/latticexyz/mud/commit/0f3e2e02b5114e08fe700c18326db76816ffad3c), [`1f80a0b5`](https://github.com/latticexyz/mud/commit/1f80a0b52a5c2d051e3697d6e60aad7364b0a925), [`d0878928`](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c), [`4c7fd3eb`](https://github.com/latticexyz/mud/commit/4c7fd3eb29e3d3954f2f1f36ace474a436082651), [`a0341daf`](https://github.com/latticexyz/mud/commit/a0341daf9fd87e8072ffa292a33f508dd37b8ca6), [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`6573e38e`](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`f1cd43bf`](https://github.com/latticexyz/mud/commit/f1cd43bf9264d5a23a3edf2a1ea4212361a72203), [`7e6e5157`](https://github.com/latticexyz/mud/commit/7e6e5157bb124f19bd8ed9f02b93afadc97cdf50), [`31ffc9d5`](https://github.com/latticexyz/mud/commit/31ffc9d5d0a6d030cc61349f0f8fbcf6748ebc48), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`63831a26`](https://github.com/latticexyz/mud/commit/63831a264b6b09501f380a4601f82ba7bf07a619), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`5741d53d`](https://github.com/latticexyz/mud/commit/5741d53d0a39990a0d7b2842f1f012973655e060), [`22ee4470`](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612), [`be313068`](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87), [`ac508bf1`](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`9b43029c`](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7), [`55ab88a6`](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314), [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`99ab9cd6`](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`80dd6992`](https://github.com/latticexyz/mud/commit/80dd6992e98c90a91d417fc785d0d53260df6ce2), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`22ba7b67`](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`251170e1`](https://github.com/latticexyz/mud/commit/251170e1ef0b07466c597ea84df0cb49de7d6a23), [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b), [`95c59b20`](https://github.com/latticexyz/mud/commit/95c59b203259c20a6f944c5f9af008b44e2902b6)]: + - @latticexyz/world@2.0.0-next.9 + - @latticexyz/store@2.0.0-next.9 + - @latticexyz/store-sync@2.0.0-next.9 + - @latticexyz/common@2.0.0-next.9 + - @latticexyz/react@2.0.0-next.9 + - @latticexyz/recs@2.0.0-next.9 + - @latticexyz/utils@2.0.0-next.9 + ## 2.0.0-next.8 ### Patch Changes diff --git a/packages/dev-tools/package.json b/packages/dev-tools/package.json index 26e18693d9..839f811e16 100644 --- a/packages/dev-tools/package.json +++ b/packages/dev-tools/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/dev-tools", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "MUD developer tools", "repository": { "type": "git", @@ -51,12 +51,12 @@ "vitest": "0.31.4" }, "peerDependencies": { - "@latticexyz/common": "2.0.0-next.8", - "@latticexyz/recs": "2.0.0-next.8", - "@latticexyz/store": "2.0.0-next.8", - "@latticexyz/store-sync": "2.0.0-next.8", - "@latticexyz/utils": "2.0.0-next.8", - "@latticexyz/world": "2.0.0-next.8" + "@latticexyz/common": "2.0.0-next.9", + "@latticexyz/recs": "2.0.0-next.9", + "@latticexyz/store": "2.0.0-next.9", + "@latticexyz/store-sync": "2.0.0-next.9", + "@latticexyz/utils": "2.0.0-next.9", + "@latticexyz/world": "2.0.0-next.9" }, "publishConfig": { "access": "public" diff --git a/packages/ecs-browser/CHANGELOG.md b/packages/ecs-browser/CHANGELOG.md index 8544b652c7..697be0a67d 100644 --- a/packages/ecs-browser/CHANGELOG.md +++ b/packages/ecs-browser/CHANGELOG.md @@ -1,5 +1,7 @@ # @latticexyz/ecs-browser +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/ecs-browser/package.json b/packages/ecs-browser/package.json index d9fe5088a7..a2a8a63dbb 100644 --- a/packages/ecs-browser/package.json +++ b/packages/ecs-browser/package.json @@ -1,5 +1,5 @@ { "name": "@latticexyz/ecs-browser", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "private": true } diff --git a/packages/faucet/CHANGELOG.md b/packages/faucet/CHANGELOG.md new file mode 100644 index 0000000000..2a4b26d03f --- /dev/null +++ b/packages/faucet/CHANGELOG.md @@ -0,0 +1,31 @@ +# @latticexyz/faucet + +## 2.0.0-next.9 + +### Minor Changes + +- [#1517](https://github.com/latticexyz/mud/pull/1517) [`9940fdb3`](https://github.com/latticexyz/mud/commit/9940fdb3e036e03aa8ede1ca80cd44d86d3b85b7) Thanks [@holic](https://github.com/holic)! - 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 }); + ``` + +### Patch Changes + +- [#1546](https://github.com/latticexyz/mud/pull/1546) [`301bcb75`](https://github.com/latticexyz/mud/commit/301bcb75dd8c15b8ea1a9d0ca8c75c15d7cd92bd) Thanks [@holic](https://github.com/holic)! - Improves error message when parsing env variables + +- [#1534](https://github.com/latticexyz/mud/pull/1534) [`fa409e83`](https://github.com/latticexyz/mud/commit/fa409e83db6b76422d525f7d2e9c947dc3c51262) Thanks [@holic](https://github.com/holic)! - Added README diff --git a/packages/faucet/package.json b/packages/faucet/package.json index 9bf3daa1e7..b096dd61e1 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/faucet", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Faucet API for Lattice testnet", "repository": { "type": "git", diff --git a/packages/gas-report/CHANGELOG.md b/packages/gas-report/CHANGELOG.md index 5a6f1590d1..c08d4cd306 100644 --- a/packages/gas-report/CHANGELOG.md +++ b/packages/gas-report/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 2.0.0-next.9 + +### Major Changes + +- [#1473](https://github.com/latticexyz/mud/pull/1473) [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a) Thanks [@holic](https://github.com/holic)! - Bump Solidity version to 0.8.21 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/gas-report/package.json b/packages/gas-report/package.json index 5ad7eeeb7f..4c68268e80 100644 --- a/packages/gas-report/package.json +++ b/packages/gas-report/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/gas-report", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Gas reporter for specific lines within forge tests", "repository": { "type": "git", diff --git a/packages/network/CHANGELOG.md b/packages/network/CHANGELOG.md index f67d572e1b..40d6fc9e7f 100644 --- a/packages/network/CHANGELOG.md +++ b/packages/network/CHANGELOG.md @@ -1,5 +1,7 @@ # @latticexyz/network +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/network/package.json b/packages/network/package.json index 9eb328626a..39c9eb3b18 100644 --- a/packages/network/package.json +++ b/packages/network/package.json @@ -1,5 +1,5 @@ { "name": "@latticexyz/network", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "private": true } diff --git a/packages/noise/CHANGELOG.md b/packages/noise/CHANGELOG.md index da095e5407..e6806a6b0e 100644 --- a/packages/noise/CHANGELOG.md +++ b/packages/noise/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 2.0.0-next.9 + +### Major Changes + +- [#1473](https://github.com/latticexyz/mud/pull/1473) [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a) Thanks [@holic](https://github.com/holic)! - Bump Solidity version to 0.8.21 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/noise/package.json b/packages/noise/package.json index 34f8665f64..8b8f6a0fe4 100644 --- a/packages/noise/package.json +++ b/packages/noise/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/noise", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "license": "MIT", "type": "module", "exports": { diff --git a/packages/phaserx/CHANGELOG.md b/packages/phaserx/CHANGELOG.md index 9f9f0b4af8..e6cd3e208b 100644 --- a/packages/phaserx/CHANGELOG.md +++ b/packages/phaserx/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## 2.0.0-next.9 + +### Patch Changes + +- Updated dependencies []: + - @latticexyz/utils@2.0.0-next.9 + ## 2.0.0-next.8 ### Patch Changes diff --git a/packages/phaserx/package.json b/packages/phaserx/package.json index 718d1e459d..dee9bdad69 100644 --- a/packages/phaserx/package.json +++ b/packages/phaserx/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/phaserx", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/protocol-parser/CHANGELOG.md b/packages/protocol-parser/CHANGELOG.md index 4bf6a0b363..da1779626a 100644 --- a/packages/protocol-parser/CHANGELOG.md +++ b/packages/protocol-parser/CHANGELOG.md @@ -1,5 +1,63 @@ # @latticexyz/protocol-parser +## 2.0.0-next.9 + +### Major Changes + +- [#1482](https://github.com/latticexyz/mud/pull/1482) [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `schema` where it is used as "value schema" to `valueSchema` to clearly distinguish it from "key schema". + The only breaking change for users is the change from `schema` to `valueSchema` in `mud.config.ts`. + + ```diff + // mud.config.ts + export default mudConfig({ + tables: { + CounterTable: { + keySchema: {}, + - schema: { + + valueSchema: { + value: "uint32", + }, + }, + } + } + ``` + +- [#1354](https://github.com/latticexyz/mud/pull/1354) [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853) Thanks [@dk1a](https://github.com/dk1a)! - `readHex` was moved from `@latticexyz/protocol-parser` to `@latticexyz/common` + +### Minor Changes + +- [#1336](https://github.com/latticexyz/mud/pull/1336) [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e) Thanks [@dk1a](https://github.com/dk1a)! - - Add `FieldLayout`, which is a `bytes32` user-type similar to `Schema`. + + Both `FieldLayout` and `Schema` have the same kind of data in the first 4 bytes. + + - 2 bytes for total length of all static fields + - 1 byte for number of static size fields + - 1 byte for number of dynamic size fields + + But whereas `Schema` has `SchemaType` enum in each of the other 28 bytes, `FieldLayout` has static byte lengths in each of the other 28 bytes. + + - Replace `Schema valueSchema` with `FieldLayout fieldLayout` in Store and World contracts. + + `FieldLayout` is more gas-efficient because it already has lengths, and `Schema` has types which need to be converted to lengths. + + - Add `getFieldLayout` to `IStore` interface. + + There is no `FieldLayout` for keys, only for values, because key byte lengths aren't usually relevant on-chain. You can still use `getKeySchema` if you need key types. + + - Add `fieldLayoutToHex` utility to `protocol-parser` package. + + - Add `constants.sol` for constants shared between `FieldLayout`, `Schema` and `PackedCounter`. + +- [#1476](https://github.com/latticexyz/mud/pull/1476) [`9ff4dd95`](https://github.com/latticexyz/mud/commit/9ff4dd955fd6dca36eb15cfe7e46bb522d2e943b) Thanks [@holic](https://github.com/holic)! - Adds `valueSchemaToFieldLayoutHex` helper + +### Patch Changes + +- [#1481](https://github.com/latticexyz/mud/pull/1481) [`f8a01a04`](https://github.com/latticexyz/mud/commit/f8a01a047d73a15326ebf6577ea033674d8e61a9) Thanks [@holic](https://github.com/holic)! - Export `valueSchemaToFieldLayoutHex` helper + +- Updated dependencies [[`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b)]: + - @latticexyz/common@2.0.0-next.9 + - @latticexyz/schema-type@2.0.0-next.9 + ## 2.0.0-next.8 ### Minor Changes diff --git a/packages/protocol-parser/package.json b/packages/protocol-parser/package.json index f7096b2e4e..689a751943 100644 --- a/packages/protocol-parser/package.json +++ b/packages/protocol-parser/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/protocol-parser", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Parser utilities for the MUD protocol", "repository": { "type": "git", diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index b70a4c7665..3a2af1d45c 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## 2.0.0-next.9 + +### Patch Changes + +- Updated dependencies [[`aea67c58`](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84), [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`f9f9609e`](https://github.com/latticexyz/mud/commit/f9f9609ef69d7fa58cad6a9af3fe6d2eed6d8aa2), [`759514d8`](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8), [`d5094a24`](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4), [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e), [`ae340b2b`](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623), [`211be2a1`](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9), [`0f3e2e02`](https://github.com/latticexyz/mud/commit/0f3e2e02b5114e08fe700c18326db76816ffad3c), [`d0878928`](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c), [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`6573e38e`](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`63831a26`](https://github.com/latticexyz/mud/commit/63831a264b6b09501f380a4601f82ba7bf07a619), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`22ee4470`](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612), [`be313068`](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87), [`ac508bf1`](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`9b43029c`](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7), [`55ab88a6`](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314), [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`99ab9cd6`](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`80dd6992`](https://github.com/latticexyz/mud/commit/80dd6992e98c90a91d417fc785d0d53260df6ce2), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`22ba7b67`](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b)]: + - @latticexyz/store@2.0.0-next.9 + - @latticexyz/recs@2.0.0-next.9 + ## 2.0.0-next.8 ### Patch Changes diff --git a/packages/react/package.json b/packages/react/package.json index 394951f492..e900e67aba 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/react", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "React tools for MUD client.", "repository": { "type": "git", diff --git a/packages/recs/CHANGELOG.md b/packages/recs/CHANGELOG.md index 27d9823cc6..615c554dd9 100644 --- a/packages/recs/CHANGELOG.md +++ b/packages/recs/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## 2.0.0-next.9 + +### Patch Changes + +- Updated dependencies [[`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a)]: + - @latticexyz/schema-type@2.0.0-next.9 + - @latticexyz/utils@2.0.0-next.9 + ## 2.0.0-next.8 ### Patch Changes diff --git a/packages/recs/package.json b/packages/recs/package.json index 5d72ffd027..d4c5eed2e0 100644 --- a/packages/recs/package.json +++ b/packages/recs/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/recs", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/schema-type/CHANGELOG.md b/packages/schema-type/CHANGELOG.md index 98391dc303..734efc9547 100644 --- a/packages/schema-type/CHANGELOG.md +++ b/packages/schema-type/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 2.0.0-next.9 + +### Major Changes + +- [#1473](https://github.com/latticexyz/mud/pull/1473) [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a) Thanks [@holic](https://github.com/holic)! - Bump Solidity version to 0.8.21 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/schema-type/package.json b/packages/schema-type/package.json index e0d57ed90b..68e8868010 100644 --- a/packages/schema-type/package.json +++ b/packages/schema-type/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/schema-type", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "SchemaType enum for various languages", "repository": { "type": "git", diff --git a/packages/services/CHANGELOG.md b/packages/services/CHANGELOG.md index 80ae076555..6818abbb9a 100644 --- a/packages/services/CHANGELOG.md +++ b/packages/services/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/services/package.json b/packages/services/package.json index 97904a6339..8dc5caa275 100644 --- a/packages/services/package.json +++ b/packages/services/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/services", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "MUD services for enhanced interactions with on-chain ECS state", "repository": { "type": "git", diff --git a/packages/solecs/CHANGELOG.md b/packages/solecs/CHANGELOG.md index 71fcc584f1..0daa6a57c7 100644 --- a/packages/solecs/CHANGELOG.md +++ b/packages/solecs/CHANGELOG.md @@ -1,5 +1,7 @@ # @latticexyz/solecs +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/solecs/package.json b/packages/solecs/package.json index 474ec9ccd2..f7120419b7 100644 --- a/packages/solecs/package.json +++ b/packages/solecs/package.json @@ -1,5 +1,5 @@ { "name": "@latticexyz/solecs", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "private": true } diff --git a/packages/solhint-config-mud/CHANGELOG.md b/packages/solhint-config-mud/CHANGELOG.md index 6354ac1eda..8679e38c28 100644 --- a/packages/solhint-config-mud/CHANGELOG.md +++ b/packages/solhint-config-mud/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/solhint-config-mud/package.json b/packages/solhint-config-mud/package.json index 8850d0fb16..3477761019 100644 --- a/packages/solhint-config-mud/package.json +++ b/packages/solhint-config-mud/package.json @@ -1,6 +1,6 @@ { "name": "solhint-config-mud", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/solhint-plugin-mud/CHANGELOG.md b/packages/solhint-plugin-mud/CHANGELOG.md index 6354ac1eda..8679e38c28 100644 --- a/packages/solhint-plugin-mud/CHANGELOG.md +++ b/packages/solhint-plugin-mud/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/solhint-plugin-mud/package.json b/packages/solhint-plugin-mud/package.json index 391eb8b1da..d26ddfe5e2 100644 --- a/packages/solhint-plugin-mud/package.json +++ b/packages/solhint-plugin-mud/package.json @@ -1,6 +1,6 @@ { "name": "solhint-plugin-mud", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/std-client/CHANGELOG.md b/packages/std-client/CHANGELOG.md index ffdbe25dae..6edd94848c 100644 --- a/packages/std-client/CHANGELOG.md +++ b/packages/std-client/CHANGELOG.md @@ -1,5 +1,7 @@ # @latticexyz/std-client +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/std-client/package.json b/packages/std-client/package.json index 4cc879fe7e..f246f9c92f 100644 --- a/packages/std-client/package.json +++ b/packages/std-client/package.json @@ -1,5 +1,5 @@ { "name": "@latticexyz/std-client", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "private": true } diff --git a/packages/std-contracts/CHANGELOG.md b/packages/std-contracts/CHANGELOG.md index 7eb7942733..fce31caf71 100644 --- a/packages/std-contracts/CHANGELOG.md +++ b/packages/std-contracts/CHANGELOG.md @@ -1,5 +1,7 @@ # @latticexyz/std-contracts +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/std-contracts/package.json b/packages/std-contracts/package.json index b6fdb984bb..1a834ab966 100644 --- a/packages/std-contracts/package.json +++ b/packages/std-contracts/package.json @@ -1,5 +1,5 @@ { "name": "@latticexyz/std-contracts", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "private": true } diff --git a/packages/store-cache/CHANGELOG.md b/packages/store-cache/CHANGELOG.md index 2c3e9dfea3..d9385b5dfc 100644 --- a/packages/store-cache/CHANGELOG.md +++ b/packages/store-cache/CHANGELOG.md @@ -1,5 +1,7 @@ # @latticexyz/store-cache +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/store-cache/package.json b/packages/store-cache/package.json index b2054eeeb9..4dee6f6b6c 100644 --- a/packages/store-cache/package.json +++ b/packages/store-cache/package.json @@ -1,5 +1,5 @@ { "name": "@latticexyz/store-cache", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "private": true } diff --git a/packages/store-indexer/CHANGELOG.md b/packages/store-indexer/CHANGELOG.md index ea15b88002..71e3194b99 100644 --- a/packages/store-indexer/CHANGELOG.md +++ b/packages/store-indexer/CHANGELOG.md @@ -1,5 +1,45 @@ # @latticexyz/store-indexer +## 2.0.0-next.9 + +### Minor Changes + +- [#1526](https://github.com/latticexyz/mud/pull/1526) [`498d05e3`](https://github.com/latticexyz/mud/commit/498d05e3604cd422064e5548dc53bec327e936ee) Thanks [@holic](https://github.com/holic)! - 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). + +### Patch Changes + +- [#1514](https://github.com/latticexyz/mud/pull/1514) [`ed07018b`](https://github.com/latticexyz/mud/commit/ed07018b86046fec20786f4752ac98a4175eb5eb) Thanks [@holic](https://github.com/holic)! - Fixes postgres indexer stopping sync after it catches up to the latest block. + +- [#1546](https://github.com/latticexyz/mud/pull/1546) [`301bcb75`](https://github.com/latticexyz/mud/commit/301bcb75dd8c15b8ea1a9d0ca8c75c15d7cd92bd) Thanks [@holic](https://github.com/holic)! - Improves error message when parsing env variables + +- [#1533](https://github.com/latticexyz/mud/pull/1533) [`b3c22a18`](https://github.com/latticexyz/mud/commit/b3c22a183c0b288b9eb1487e4fef125bf7dae915) Thanks [@holic](https://github.com/holic)! - Added README and refactored handling of common environment variables + +- Updated dependencies [[`aea67c58`](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84), [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`f9f9609e`](https://github.com/latticexyz/mud/commit/f9f9609ef69d7fa58cad6a9af3fe6d2eed6d8aa2), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`759514d8`](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8), [`d5094a24`](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4), [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96), [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e), [`ae340b2b`](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623), [`211be2a1`](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9), [`0f3e2e02`](https://github.com/latticexyz/mud/commit/0f3e2e02b5114e08fe700c18326db76816ffad3c), [`d0878928`](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c), [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`6573e38e`](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`7e6e5157`](https://github.com/latticexyz/mud/commit/7e6e5157bb124f19bd8ed9f02b93afadc97cdf50), [`63831a26`](https://github.com/latticexyz/mud/commit/63831a264b6b09501f380a4601f82ba7bf07a619), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`22ee4470`](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612), [`be313068`](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87), [`ac508bf1`](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`9b43029c`](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7), [`55ab88a6`](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314), [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`99ab9cd6`](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`80dd6992`](https://github.com/latticexyz/mud/commit/80dd6992e98c90a91d417fc785d0d53260df6ce2), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`22ba7b67`](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7), [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b)]: + - @latticexyz/store@2.0.0-next.9 + - @latticexyz/store-sync@2.0.0-next.9 + - @latticexyz/common@2.0.0-next.9 + - @latticexyz/block-logs-stream@2.0.0-next.9 + ## 2.0.0-next.8 ### Patch Changes diff --git a/packages/store-indexer/package.json b/packages/store-indexer/package.json index 3a17b7b65b..22197aef9e 100644 --- a/packages/store-indexer/package.json +++ b/packages/store-indexer/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/store-indexer", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Minimal Typescript indexer for Store", "repository": { "type": "git", diff --git a/packages/store-sync/CHANGELOG.md b/packages/store-sync/CHANGELOG.md index 6613bab9da..9cfd580073 100644 --- a/packages/store-sync/CHANGELOG.md +++ b/packages/store-sync/CHANGELOG.md @@ -1,5 +1,278 @@ # @latticexyz/store-sync +## 2.0.0-next.9 + +### Major Changes + +- [#1482](https://github.com/latticexyz/mud/pull/1482) [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `schema` where it is used as "value schema" to `valueSchema` to clearly distinguish it from "key schema". + The only breaking change for users is the change from `schema` to `valueSchema` in `mud.config.ts`. + + ```diff + // mud.config.ts + export default mudConfig({ + tables: { + CounterTable: { + keySchema: {}, + - schema: { + + valueSchema: { + value: "uint32", + }, + }, + } + } + ``` + +- [#1354](https://github.com/latticexyz/mud/pull/1354) [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853) Thanks [@dk1a](https://github.com/dk1a)! - 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# @latticexyz/store-sync with `storedBlockLogs# @latticexyz/store-sync, 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. + +### Patch Changes + +- [#1484](https://github.com/latticexyz/mud/pull/1484) [`6573e38e`](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `table` where it is used as "table ID" to `tableId`. + This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + + ```diff + event StoreSetRecord( + - bytes32 table, + + bytes32 tableId, + bytes32[] key, + bytes data + ); + + event StoreSetField( + - bytes32 table, + + bytes32 tableId, + bytes32[] key, + uint8 fieldIndex, + bytes data + ); + + event StoreDeleteRecord( + - bytes32 table, + + bytes32 tableId, + bytes32[] key + ); + + event StoreEphemeralRecord( + - bytes32 table, + + bytes32 tableId, + bytes32[] key, + bytes data + ); + ``` + +- [#1492](https://github.com/latticexyz/mud/pull/1492) [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `key` where it is used as "key tuple" to `keyTuple`. + This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + + ```diff + event StoreSetRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + bytes data + ); + + event StoreSetField( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + uint8 fieldIndex, + bytes data + ); + + event StoreDeleteRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + ); + + event StoreEphemeralRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + bytes data + ); + ``` + +- [#1488](https://github.com/latticexyz/mud/pull/1488) [`7e6e5157`](https://github.com/latticexyz/mud/commit/7e6e5157bb124f19bd8ed9f02b93afadc97cdf50) Thanks [@holic](https://github.com/holic)! - Catch errors when parsing logs to tables and storage operations, log and skip + +- [#1586](https://github.com/latticexyz/mud/pull/1586) [`22ee4470`](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612) Thanks [@alvrs](https://github.com/alvrs)! - All `Store` and `World` tables now use the appropriate user-types for `ResourceId`, `FieldLayout` and `Schema` to avoid manual `wrap`/`unwrap`. + +- [#1558](https://github.com/latticexyz/mud/pull/1558) [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f) Thanks [@alvrs](https://github.com/alvrs)! - What used to be known as `ephemeral` table is now called `offchain` table. + The previous `ephemeral` tables only supported an `emitEphemeral` method, which emitted a `StoreSetEphemeralRecord` event. + + Now `offchain` tables support all regular table methods, except partial operations on dynamic fields (`push`, `pop`, `update`). + Unlike regular tables they don't store data on-chain but emit the same events as regular tables (`StoreSetRecord`, `StoreSpliceStaticData`, `StoreDeleteRecord`), so their data can be indexed by offchain indexers/clients. + + ```diff + - EphemeralTable.emitEphemeral(value); + + OffchainTable.set(value); + ``` + +- [#1577](https://github.com/latticexyz/mud/pull/1577) [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c) Thanks [@alvrs](https://github.com/alvrs)! - `Store` events have been renamed for consistency and readability. + If you're parsing `Store` events manually, you need to update your ABI. + If you're using the MUD sync stack, the new events are already integrated and no further changes are necessary. + + ```diff + - event StoreSetRecord( + + event Store_SetRecord( + ResourceId indexed tableId, + bytes32[] keyTuple, + bytes staticData, + bytes32 encodedLengths, + bytes dynamicData + ); + - event StoreSpliceStaticData( + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data + ); + - event StoreSpliceDynamicData( + + event Store_SpliceDynamicData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data, + bytes32 encodedLengths + ); + - event StoreDeleteRecord( + + event Store_DeleteRecord( + ResourceId indexed tableId, + bytes32[] keyTuple + ); + ``` + +- [#1581](https://github.com/latticexyz/mud/pull/1581) [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b) Thanks [@alvrs](https://github.com/alvrs)! - - The external `setRecord` and `deleteRecord` methods of `IStore` no longer accept a `FieldLayout` as input, but load it from storage instead. + This is to prevent invalid `FieldLayout` values being passed, which could cause the onchain state to diverge from the indexer state. + However, the internal `StoreCore` library still exposes a `setRecord` and `deleteRecord` method that allows a `FieldLayout` to be passed. + This is because `StoreCore` can only be used internally, so the `FieldLayout` value can be trusted and we can save the gas for accessing storage. + + ```diff + interface IStore { + function setRecord( + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + - FieldLayout fieldLayout + ) external; + + function deleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + - FieldLayout fieldLayout + ) external; + } + ``` + + - The `spliceStaticData` method and `Store_SpliceStaticData` event of `IStore` and `StoreCore` no longer include `deleteCount` in their signature. + This is because when splicing static data, the data after `start` is always overwritten with `data` instead of being shifted, so `deleteCount` is always the length of the data to be written. + + ```diff + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + - uint40 deleteCount, + bytes data + ); + + interface IStore { + function spliceStaticData( + ResourceId tableId, + bytes32[] calldata keyTuple, + uint48 start, + - uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + + - The `updateInField` method has been removed from `IStore`, as it's almost identical to the more general `spliceDynamicData`. + If you're manually calling `updateInField`, here is how to upgrade to `spliceDynamicData`: + + ```diff + - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); + + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields(); + + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet); + ``` + + - All other methods that are only valid for dynamic fields (`pushToField`, `popFromField`, `getFieldSlice`) + have been renamed to make this more explicit (`pushToDynamicField`, `popFromDynamicField`, `getDynamicFieldSlice`). + + Their `fieldIndex` parameter has been replaced by a `dynamicFieldIndex` parameter, which is the index relative to the first dynamic field (i.e. `dynamicFieldIndex` = `fieldIndex` - `numStaticFields`). + The `FieldLayout` parameter has been removed, as it was only used to calculate the `dynamicFieldIndex` in the method. + + ```diff + interface IStore { + - function pushToField( + + function pushToDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + bytes calldata dataToPush, + - FieldLayout fieldLayout + ) external; + + - function popFromField( + + function popFromDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + uint256 byteLengthToPop, + - FieldLayout fieldLayout + ) external; + + - function getFieldSlice( + + function getDynamicFieldSlice( + ResourceId tableId, + bytes32[] memory keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + - FieldLayout fieldLayout, + uint256 start, + uint256 end + ) external view returns (bytes memory data); + } + ``` + + - `IStore` has a new `getDynamicFieldLength` length method, which returns the byte length of the given dynamic field and doesn't require the `FieldLayout`. + + ```diff + IStore { + + function getDynamicFieldLength( + + ResourceId tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex + + ) external view returns (uint256); + } + + ``` + + - `IStore` now has additional overloads for `getRecord`, `getField`, `getFieldLength` and `setField` that don't require a `FieldLength` to be passed, but instead load it from storage. + + - `IStore` now exposes `setStaticField` and `setDynamicField` to save gas by avoiding the dynamic inference of whether the field is static or dynamic. + + - The `getDynamicFieldSlice` method no longer accepts reading outside the bounds of the dynamic field. + This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero. + +- Updated dependencies [[`748f4588`](https://github.com/latticexyz/mud/commit/748f4588a218928bca041760448c26991c0d8033), [`aea67c58`](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84), [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9), [`c07fa021`](https://github.com/latticexyz/mud/commit/c07fa021501ff92be35c0491dd89bbb8161e1c07), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`f9f9609e`](https://github.com/latticexyz/mud/commit/f9f9609ef69d7fa58cad6a9af3fe6d2eed6d8aa2), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`759514d8`](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8), [`d5094a24`](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4), [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96), [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e), [`ae340b2b`](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623), [`e5d208e4`](https://github.com/latticexyz/mud/commit/e5d208e40b2b2fae223b48716ce3f62c530ea1ca), [`211be2a1`](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9), [`0f3e2e02`](https://github.com/latticexyz/mud/commit/0f3e2e02b5114e08fe700c18326db76816ffad3c), [`1f80a0b5`](https://github.com/latticexyz/mud/commit/1f80a0b52a5c2d051e3697d6e60aad7364b0a925), [`d0878928`](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c), [`4c7fd3eb`](https://github.com/latticexyz/mud/commit/4c7fd3eb29e3d3954f2f1f36ace474a436082651), [`a0341daf`](https://github.com/latticexyz/mud/commit/a0341daf9fd87e8072ffa292a33f508dd37b8ca6), [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`6573e38e`](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`f8a01a04`](https://github.com/latticexyz/mud/commit/f8a01a047d73a15326ebf6577ea033674d8e61a9), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`f1cd43bf`](https://github.com/latticexyz/mud/commit/f1cd43bf9264d5a23a3edf2a1ea4212361a72203), [`31ffc9d5`](https://github.com/latticexyz/mud/commit/31ffc9d5d0a6d030cc61349f0f8fbcf6748ebc48), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`63831a26`](https://github.com/latticexyz/mud/commit/63831a264b6b09501f380a4601f82ba7bf07a619), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`5741d53d`](https://github.com/latticexyz/mud/commit/5741d53d0a39990a0d7b2842f1f012973655e060), [`22ee4470`](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612), [`be313068`](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87), [`ac508bf1`](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130), [`9ff4dd95`](https://github.com/latticexyz/mud/commit/9ff4dd955fd6dca36eb15cfe7e46bb522d2e943b), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`9b43029c`](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7), [`55ab88a6`](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314), [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`99ab9cd6`](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`80dd6992`](https://github.com/latticexyz/mud/commit/80dd6992e98c90a91d417fc785d0d53260df6ce2), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`22ba7b67`](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`251170e1`](https://github.com/latticexyz/mud/commit/251170e1ef0b07466c597ea84df0cb49de7d6a23), [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b), [`95c59b20`](https://github.com/latticexyz/mud/commit/95c59b203259c20a6f944c5f9af008b44e2902b6)]: + - @latticexyz/world@2.0.0-next.9 + - @latticexyz/store@2.0.0-next.9 + - @latticexyz/protocol-parser@2.0.0-next.9 + - @latticexyz/common@2.0.0-next.9 + - @latticexyz/block-logs-stream@2.0.0-next.9 + - @latticexyz/schema-type@2.0.0-next.9 + - @latticexyz/recs@2.0.0-next.9 + ## 2.0.0-next.8 ### Patch Changes diff --git a/packages/store-sync/package.json b/packages/store-sync/package.json index ca4ce4abbc..da84428691 100644 --- a/packages/store-sync/package.json +++ b/packages/store-sync/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/store-sync", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Utilities to sync MUD Store events with a client or cache", "repository": { "type": "git", diff --git a/packages/store/CHANGELOG.md b/packages/store/CHANGELOG.md index 12f7db7a53..65a79af3cc 100644 --- a/packages/store/CHANGELOG.md +++ b/packages/store/CHANGELOG.md @@ -1,5 +1,720 @@ # Change Log +## 2.0.0-next.9 + +### Major Changes + +- [#1482](https://github.com/latticexyz/mud/pull/1482) [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `schema` where it is used as "value schema" to `valueSchema` to clearly distinguish it from "key schema". + The only breaking change for users is the change from `schema` to `valueSchema` in `mud.config.ts`. + + ```diff + // mud.config.ts + export default mudConfig({ + tables: { + CounterTable: { + keySchema: {}, + - schema: { + + valueSchema: { + value: "uint32", + }, + }, + } + } + ``` + +- [#1354](https://github.com/latticexyz/mud/pull/1354) [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853) Thanks [@dk1a](https://github.com/dk1a)! - 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. + +- [#1589](https://github.com/latticexyz/mud/pull/1589) [`f9f9609e`](https://github.com/latticexyz/mud/commit/f9f9609ef69d7fa58cad6a9af3fe6d2eed6d8aa2) Thanks [@alvrs](https://github.com/alvrs)! - The argument order on `Store_SpliceDynamicData`, `onBeforeSpliceDynamicData` and `onAfterSpliceDynamicData` has been changed to match the argument order on `Store_SetRecord`, + where the `PackedCounter encodedLength` field comes before the `bytes dynamicData` field. + + ```diff + IStore { + event Store_SpliceDynamicData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + + PackedCounter encodedLengths, + bytes data, + - PackedCounter encodedLengths + ); + } + + IStoreHook { + function onBeforeSpliceDynamicData( + ResourceId tableId, + bytes32[] memory keyTuple, + uint8 dynamicFieldIndex, + uint40 startWithinField, + uint40 deleteCount, + + PackedCounter encodedLengths, + bytes memory data, + - PackedCounter encodedLengths + ) external; + + function onAfterSpliceDynamicData( + ResourceId tableId, + bytes32[] memory keyTuple, + uint8 dynamicFieldIndex, + uint40 startWithinField, + uint40 deleteCount, + + PackedCounter encodedLengths, + bytes memory data, + - PackedCounter encodedLengths + ) external; + } + ``` + +- [#1527](https://github.com/latticexyz/mud/pull/1527) [`759514d8`](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8) Thanks [@holic](https://github.com/holic)! - 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 + ); + + ``` + +- [#1531](https://github.com/latticexyz/mud/pull/1531) [`d5094a24`](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4) Thanks [@alvrs](https://github.com/alvrs)! - - The `IStoreHook` interface was changed to replace `onBeforeSetField` and `onAfterSetField` with `onBeforeSpliceStaticData`, `onAfterSpliceStaticData`, `onBeforeSpliceDynamicData` and `onAfterSpliceDynamicData`. + + This new interface matches the new `StoreSpliceStaticData` and `StoreSpliceDynamicData` events, and avoids having to read the entire field from storage when only a subset of the field was updated + (e.g. when pushing elements to a field). + + ```diff + interface IStoreHook { + - function onBeforeSetField( + - bytes32 tableId, + - bytes32[] memory keyTuple, + - uint8 fieldIndex, + - bytes memory data, + - FieldLayout fieldLayout + - ) external; + + - function onAfterSetField( + - bytes32 tableId, + - bytes32[] memory keyTuple, + - uint8 fieldIndex, + - bytes memory data, + - FieldLayout fieldLayout + - ) external; + + + function onBeforeSpliceStaticData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint48 start, + + uint40 deleteCount, + + bytes memory data + + ) external; + + + function onAfterSpliceStaticData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint48 start, + + uint40 deleteCount, + + bytes memory data + + ) external; + + + function onBeforeSpliceDynamicData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex, + + uint40 startWithinField, + + uint40 deleteCount, + + bytes memory data, + + PackedCounter encodedLengths + + ) external; + + + function onAfterSpliceDynamicData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex, + + uint40 startWithinField, + + uint40 deleteCount, + + bytes memory data, + + PackedCounter encodedLengths + + ) external; + } + ``` + + - All `calldata` parameters on the `IStoreHook` interface were changed to `memory`, since the functions are called with `memory` from the `World`. + + - `IStore` exposes two new functions: `spliceStaticData` and `spliceDynamicData`. + + These functions provide lower level access to the operations happening under the hood in `setField`, `pushToField`, `popFromField` and `updateInField` and simplify handling + the new splice hooks. + + `StoreCore`'s internal logic was simplified to use the `spliceStaticData` and `spliceDynamicData` functions instead of duplicating similar logic in different functions. + + ```solidity + interface IStore { + // Splice data in the static part of the record + function spliceStaticData( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint48 start, + uint40 deleteCount, + bytes calldata data + ) external; + + // Splice data in the dynamic part of the record + function spliceDynamicData( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint8 dynamicFieldIndex, + uint40 startWithinField, + uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + +- [#1336](https://github.com/latticexyz/mud/pull/1336) [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e) Thanks [@dk1a](https://github.com/dk1a)! - - Add `FieldLayout`, which is a `bytes32` user-type similar to `Schema`. + + Both `FieldLayout` and `Schema` have the same kind of data in the first 4 bytes. + + - 2 bytes for total length of all static fields + - 1 byte for number of static size fields + - 1 byte for number of dynamic size fields + + But whereas `Schema` has `SchemaType` enum in each of the other 28 bytes, `FieldLayout` has static byte lengths in each of the other 28 bytes. + + - Replace `Schema valueSchema` with `FieldLayout fieldLayout` in Store and World contracts. + + `FieldLayout` is more gas-efficient because it already has lengths, and `Schema` has types which need to be converted to lengths. + + - Add `getFieldLayout` to `IStore` interface. + + There is no `FieldLayout` for keys, only for values, because key byte lengths aren't usually relevant on-chain. You can still use `getKeySchema` if you need key types. + + - Add `fieldLayoutToHex` utility to `protocol-parser` package. + + - Add `constants.sol` for constants shared between `FieldLayout`, `Schema` and `PackedCounter`. + +- [#1532](https://github.com/latticexyz/mud/pull/1532) [`ae340b2b`](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623) Thanks [@dk1a](https://github.com/dk1a)! - Store's `getRecord` has been updated to return `staticData`, `encodedLengths`, and `dynamicData` instead of a single `data` blob, to match the new behaviour of Store setter methods. + + If you use codegenerated libraries, you will only need to update `encode` calls. + + ```diff + - bytes memory data = Position.encode(x, y); + + (bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData) = Position.encode(x, y); + ``` + +- [#1483](https://github.com/latticexyz/mud/pull/1483) [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab) Thanks [@holic](https://github.com/holic)! - Store and World contract ABIs are now exported from the `out` directory. You'll need to update your imports like: + + ```diff + - import IBaseWorldAbi from "@latticexyz/world/abi/IBaseWorld.sol/IBaseWorldAbi.json"; + + import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorldAbi.json"; + ``` + + `MudTest.sol` was also moved to the World package. You can update your import like: + + ```diff + - import { MudTest } from "@latticexyz/store/src/MudTest.sol"; + + import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; + ``` + +- [#1566](https://github.com/latticexyz/mud/pull/1566) [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9) Thanks [@dk1a](https://github.com/dk1a)! - These breaking changes only affect store utilities, you aren't affected if you use `@latticexyz/cli` codegen scripts. + + - Add `remappings` argument to the `tablegen` codegen function, so that it can read user-provided files. + - In `RenderTableOptions` change the type of `imports` from `RelativeImportDatum` to `ImportDatum`, to allow passing absolute imports to the table renderer. + - Add `solidityUserTypes` argument to several functions that need to resolve user or abi types: `resolveAbiOrUserType`, `importForAbiOrUserType`, `getUserTypeInfo`. + - Add `userTypes` config option to MUD config, which takes user types mapped to file paths from which to import them. + +- [#1550](https://github.com/latticexyz/mud/pull/1550) [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e) Thanks [@dk1a](https://github.com/dk1a)! - - Always render field methods with a suffix in tablegen (they used to not be rendered if field methods without a suffix were rendered). + + - Add `withSuffixlessFieldMethods` to `RenderTableOptions`, which indicates that field methods without a suffix should be rendered. + +- [#1473](https://github.com/latticexyz/mud/pull/1473) [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a) Thanks [@holic](https://github.com/holic)! - Bump Solidity version to 0.8.21 + +- [#1318](https://github.com/latticexyz/mud/pull/1318) [`ac508bf1`](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130) Thanks [@holic](https://github.com/holic)! - 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"; + ``` + +- [#1558](https://github.com/latticexyz/mud/pull/1558) [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f) Thanks [@alvrs](https://github.com/alvrs)! - What used to be known as `ephemeral` table is now called `offchain` table. + The previous `ephemeral` tables only supported an `emitEphemeral` method, which emitted a `StoreSetEphemeralRecord` event. + + Now `offchain` tables support all regular table methods, except partial operations on dynamic fields (`push`, `pop`, `update`). + Unlike regular tables they don't store data on-chain but emit the same events as regular tables (`StoreSetRecord`, `StoreSpliceStaticData`, `StoreDeleteRecord`), so their data can be indexed by offchain indexers/clients. + + ```diff + - EphemeralTable.emitEphemeral(value); + + OffchainTable.set(value); + ``` + +- [#1577](https://github.com/latticexyz/mud/pull/1577) [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c) Thanks [@alvrs](https://github.com/alvrs)! - `Store` events have been renamed for consistency and readability. + If you're parsing `Store` events manually, you need to update your ABI. + If you're using the MUD sync stack, the new events are already integrated and no further changes are necessary. + + ```diff + - event StoreSetRecord( + + event Store_SetRecord( + ResourceId indexed tableId, + bytes32[] keyTuple, + bytes staticData, + bytes32 encodedLengths, + bytes dynamicData + ); + - event StoreSpliceStaticData( + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data + ); + - event StoreSpliceDynamicData( + + event Store_SpliceDynamicData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + uint40 deleteCount, + bytes data, + bytes32 encodedLengths + ); + - event StoreDeleteRecord( + + event Store_DeleteRecord( + ResourceId indexed tableId, + bytes32[] keyTuple + ); + ``` + +- [#1544](https://github.com/latticexyz/mud/pull/1544) [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae) Thanks [@alvrs](https://github.com/alvrs)! - - `ResourceSelector` is replaced with `ResourceId`, `ResourceIdLib`, `ResourceIdInstance`, `WorldResourceIdLib` and `WorldResourceIdInstance`. + + Previously a "resource selector" was a `bytes32` value with the first 16 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + Now a "resource ID" is a `bytes32` value with the first 2 bytes reserved for the resource type, the next 14 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name. + + Previously `ResouceSelector` was a library and the resource selector type was a plain `bytes32`. + Now `ResourceId` is a user type, and the functionality is implemented in the `ResourceIdInstance` (for type) and `WorldResourceIdInstance` (for namespace and name) libraries. + We split the logic into two libraries, because `Store` now also uses `ResourceId` and needs to be aware of resource types, but not of namespaces/names. + + ```diff + - import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol"; + + import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; + + import { WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol"; + + import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol"; + + - bytes32 systemId = ResourceSelector.from("namespace", "name"); + + ResourceId systemId = WorldResourceIdLib.encode(RESOURCE_SYSTEM, "namespace", "name"); + + - using ResourceSelector for bytes32; + + using WorldResourceIdInstance for ResourceId; + + using ResourceIdInstance for ResourceId; + + systemId.getName(); + systemId.getNamespace(); + + systemId.getType(); + + ``` + + - All `Store` and `World` methods now use the `ResourceId` type for `tableId`, `systemId`, `moduleId` and `namespaceId`. + All mentions of `resourceSelector` were renamed to `resourceId` or the more specific type (e.g. `tableId`, `systemId`) + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IStore { + function setRecord( + - bytes32 tableId, + + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + FieldLayout fieldLayout + ) external; + + // Same for all other methods + } + ``` + + ```diff + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IBaseWorld { + function callFrom( + address delegator, + - bytes32 resourceSelector, + + ResourceId systemId, + bytes memory callData + ) external payable returns (bytes memory); + + // Same for all other methods + } + ``` + +- [#1520](https://github.com/latticexyz/mud/pull/1520) [`99ab9cd6`](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380) Thanks [@holic](https://github.com/holic)! - Store events now use an `indexed` `tableId`. This adds ~100 gas per write, but means we our sync stack can filter events by table. + +- [#1472](https://github.com/latticexyz/mud/pull/1472) [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf) Thanks [@alvrs](https://github.com/alvrs)! - - `StoreCore`'s `initialize` function is split into `initialize` (to set the `StoreSwitch`'s `storeAddress`) and `registerCoreTables` (to register the `Tables` and `StoreHooks` tables). + The purpose of this is to give consumers more granular control over the setup flow. + + - The `StoreRead` contract no longer calls `StoreCore.initialize` in its constructor. + `StoreCore` consumers are expected to call `StoreCore.initialize` and `StoreCore.registerCoreTable` in their own setup logic. + +- [#1587](https://github.com/latticexyz/mud/pull/1587) [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d) Thanks [@alvrs](https://github.com/alvrs)! - Changed the `userTypes` property to accept `{ filePath: string, internalType: SchemaAbiType }` to enable strong type inference from the config. + +- [#1581](https://github.com/latticexyz/mud/pull/1581) [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b) Thanks [@alvrs](https://github.com/alvrs)! - - The external `setRecord` and `deleteRecord` methods of `IStore` no longer accept a `FieldLayout` as input, but load it from storage instead. + This is to prevent invalid `FieldLayout` values being passed, which could cause the onchain state to diverge from the indexer state. + However, the internal `StoreCore` library still exposes a `setRecord` and `deleteRecord` method that allows a `FieldLayout` to be passed. + This is because `StoreCore` can only be used internally, so the `FieldLayout` value can be trusted and we can save the gas for accessing storage. + + ```diff + interface IStore { + function setRecord( + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + - FieldLayout fieldLayout + ) external; + + function deleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + - FieldLayout fieldLayout + ) external; + } + ``` + + - The `spliceStaticData` method and `Store_SpliceStaticData` event of `IStore` and `StoreCore` no longer include `deleteCount` in their signature. + This is because when splicing static data, the data after `start` is always overwritten with `data` instead of being shifted, so `deleteCount` is always the length of the data to be written. + + ```diff + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + - uint40 deleteCount, + bytes data + ); + + interface IStore { + function spliceStaticData( + ResourceId tableId, + bytes32[] calldata keyTuple, + uint48 start, + - uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + + - The `updateInField` method has been removed from `IStore`, as it's almost identical to the more general `spliceDynamicData`. + If you're manually calling `updateInField`, here is how to upgrade to `spliceDynamicData`: + + ```diff + - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); + + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields(); + + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet); + ``` + + - All other methods that are only valid for dynamic fields (`pushToField`, `popFromField`, `getFieldSlice`) + have been renamed to make this more explicit (`pushToDynamicField`, `popFromDynamicField`, `getDynamicFieldSlice`). + + Their `fieldIndex` parameter has been replaced by a `dynamicFieldIndex` parameter, which is the index relative to the first dynamic field (i.e. `dynamicFieldIndex` = `fieldIndex` - `numStaticFields`). + The `FieldLayout` parameter has been removed, as it was only used to calculate the `dynamicFieldIndex` in the method. + + ```diff + interface IStore { + - function pushToField( + + function pushToDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + bytes calldata dataToPush, + - FieldLayout fieldLayout + ) external; + + - function popFromField( + + function popFromDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + uint256 byteLengthToPop, + - FieldLayout fieldLayout + ) external; + + - function getFieldSlice( + + function getDynamicFieldSlice( + ResourceId tableId, + bytes32[] memory keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + - FieldLayout fieldLayout, + uint256 start, + uint256 end + ) external view returns (bytes memory data); + } + ``` + + - `IStore` has a new `getDynamicFieldLength` length method, which returns the byte length of the given dynamic field and doesn't require the `FieldLayout`. + + ```diff + IStore { + + function getDynamicFieldLength( + + ResourceId tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex + + ) external view returns (uint256); + } + + ``` + + - `IStore` now has additional overloads for `getRecord`, `getField`, `getFieldLength` and `setField` that don't require a `FieldLength` to be passed, but instead load it from storage. + + - `IStore` now exposes `setStaticField` and `setDynamicField` to save gas by avoiding the dynamic inference of whether the field is static or dynamic. + + - The `getDynamicFieldSlice` method no longer accepts reading outside the bounds of the dynamic field. + This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero. + +### Minor Changes + +- [#1511](https://github.com/latticexyz/mud/pull/1511) [`9b43029c`](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7) Thanks [@holic](https://github.com/holic)! - 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); + ``` + +- [#1521](https://github.com/latticexyz/mud/pull/1521) [`55ab88a6`](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314) Thanks [@alvrs](https://github.com/alvrs)! - `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); + } + ``` + +- [#1542](https://github.com/latticexyz/mud/pull/1542) [`80dd6992`](https://github.com/latticexyz/mud/commit/80dd6992e98c90a91d417fc785d0d53260df6ce2) Thanks [@dk1a](https://github.com/dk1a)! - Add an optional `namePrefix` argument to `renderRecordData`, to support inlined logic in codegenned `set` method which uses a struct. + +- [#1513](https://github.com/latticexyz/mud/pull/1513) [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280) Thanks [@Boffee](https://github.com/Boffee)! - 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 + } + ``` + +### Patch Changes + +- [#1490](https://github.com/latticexyz/mud/pull/1490) [`aea67c58`](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84) Thanks [@alvrs](https://github.com/alvrs)! - Include bytecode for `World` and `Store` in npm packages. + +- [#1508](https://github.com/latticexyz/mud/pull/1508) [`211be2a1`](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9) Thanks [@Boffee](https://github.com/Boffee)! - 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. + +- [#1512](https://github.com/latticexyz/mud/pull/1512) [`0f3e2e02`](https://github.com/latticexyz/mud/commit/0f3e2e02b5114e08fe700c18326db76816ffad3c) Thanks [@Boffee](https://github.com/Boffee)! - Added `Storage.loadField` to optimize loading 32 bytes or less from storage (which is always the case when loading data for static fields). + +- [#1568](https://github.com/latticexyz/mud/pull/1568) [`d0878928`](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c) Thanks [@alvrs](https://github.com/alvrs)! - Prefixed all errors with their respective library/contract for improved debugging. + +- [#1544](https://github.com/latticexyz/mud/pull/1544) [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae) Thanks [@alvrs](https://github.com/alvrs)! - The `ResourceType` table is removed. + It was previously used to store the resource type for each resource ID in a `World`. This is no longer necessary as the [resource type is now encoded in the resource ID](https://github.com/latticexyz/mud/pull/1544). + + To still be able to determine whether a given resource ID exists, a `ResourceIds` table has been added. + The previous `ResourceType` table was part of `World` and missed tables that were registered directly via `StoreCore.registerTable` instead of via `World.registerTable` (e.g. when a table was registered as part of a root module). + This problem is solved by the new table `ResourceIds` being part of `Store`. + + `StoreCore`'s `hasTable` function was removed in favor of using `ResourceIds.getExists(tableId)` directly. + + ```diff + - import { ResourceType } from "@latticexyz/world/src/tables/ResourceType.sol"; + - import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; + + import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol"; + + - bool tableExists = StoreCore.hasTable(tableId); + + bool tableExists = ResourceIds.getExists(tableId); + + - bool systemExists = ResourceType.get(systemId) != Resource.NONE; + + bool systemExists = ResourceIds.getExists(systemId); + ``` + +- [#1484](https://github.com/latticexyz/mud/pull/1484) [`6573e38e`](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `table` where it is used as "table ID" to `tableId`. + This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + + ```diff + event StoreSetRecord( + - bytes32 table, + + bytes32 tableId, + bytes32[] key, + bytes data + ); + + event StoreSetField( + - bytes32 table, + + bytes32 tableId, + bytes32[] key, + uint8 fieldIndex, + bytes data + ); + + event StoreDeleteRecord( + - bytes32 table, + + bytes32 tableId, + bytes32[] key + ); + + event StoreEphemeralRecord( + - bytes32 table, + + bytes32 tableId, + bytes32[] key, + bytes data + ); + ``` + +- [#1492](https://github.com/latticexyz/mud/pull/1492) [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `key` where it is used as "key tuple" to `keyTuple`. + This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + + ```diff + event StoreSetRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + bytes data + ); + + event StoreSetField( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + uint8 fieldIndex, + bytes data + ); + + event StoreDeleteRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + ); + + event StoreEphemeralRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + bytes data + ); + ``` + +- [#1599](https://github.com/latticexyz/mud/pull/1599) [`63831a26`](https://github.com/latticexyz/mud/commit/63831a264b6b09501f380a4601f82ba7bf07a619) Thanks [@alvrs](https://github.com/alvrs)! - Minor `Store` cleanups: renamed `Utils.sol` to `leftMask.sol` since it only contains a single free function, and removed a leftover sanity check. + +- [#1586](https://github.com/latticexyz/mud/pull/1586) [`22ee4470`](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612) Thanks [@alvrs](https://github.com/alvrs)! - All `Store` and `World` tables now use the appropriate user-types for `ResourceId`, `FieldLayout` and `Schema` to avoid manual `wrap`/`unwrap`. + +- [#1509](https://github.com/latticexyz/mud/pull/1509) [`be313068`](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87) Thanks [@Boffee](https://github.com/Boffee)! - Optimized the `StoreCore` hash function determining the data location to use less gas. + +- [#1569](https://github.com/latticexyz/mud/pull/1569) [`22ba7b67`](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7) Thanks [@alvrs](https://github.com/alvrs)! - Simplified a couple internal constants used for bitshifting. + +- Updated dependencies [[`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b)]: + - @latticexyz/common@2.0.0-next.9 + - @latticexyz/schema-type@2.0.0-next.9 + - @latticexyz/config@2.0.0-next.9 + ## 2.0.0-next.8 ### Major Changes diff --git a/packages/store/package.json b/packages/store/package.json index d2fe260e43..a89da3e218 100644 --- a/packages/store/package.json +++ b/packages/store/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/store", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "Store", "repository": { "type": "git", diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index 5c02256dec..6c977d9df1 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 2.0.0-next.9 + ## 2.0.0-next.8 ## 2.0.0-next.7 diff --git a/packages/utils/package.json b/packages/utils/package.json index 7da0b51e49..9a6a28f922 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/utils", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/world-modules/CHANGELOG.md b/packages/world-modules/CHANGELOG.md index 420e6f23d0..1782b81d47 100644 --- a/packages/world-modules/CHANGELOG.md +++ b/packages/world-modules/CHANGELOG.md @@ -1 +1,27 @@ # Change Log + +## 2.0.0-next.9 + +### Major Changes + +- [#1591](https://github.com/latticexyz/mud/pull/1591) [`251170e1`](https://github.com/latticexyz/mud/commit/251170e1ef0b07466c597ea84df0cb49de7d6a23) Thanks [@alvrs](https://github.com/alvrs)! - All optional modules have been moved from `@latticexyz/world` to `@latticexyz/world-modules`. + If you're using the MUD CLI, the import is already updated and no changes are necessary. + +### Patch Changes + +- [#1592](https://github.com/latticexyz/mud/pull/1592) [`c07fa021`](https://github.com/latticexyz/mud/commit/c07fa021501ff92be35c0491dd89bbb8161e1c07) Thanks [@alvrs](https://github.com/alvrs)! - Tables and interfaces in the `world` package are now generated to the `codegen` folder. + This is only a breaking change if you imported tables or codegenerated interfaces from `@latticexyz/world` directly. + If you're using the MUD CLI, the changed import paths are already integrated and no further changes are necessary. + + ```diff + - import { IBaseWorld } from "@latticexyz/world/src/interfaces/IBaseWorld.sol"; + + import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol"; + + ``` + +- Updated dependencies [[`748f4588`](https://github.com/latticexyz/mud/commit/748f4588a218928bca041760448c26991c0d8033), [`aea67c58`](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84), [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9), [`c07fa021`](https://github.com/latticexyz/mud/commit/c07fa021501ff92be35c0491dd89bbb8161e1c07), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`f9f9609e`](https://github.com/latticexyz/mud/commit/f9f9609ef69d7fa58cad6a9af3fe6d2eed6d8aa2), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`759514d8`](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8), [`d5094a24`](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4), [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96), [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e), [`ae340b2b`](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623), [`e5d208e4`](https://github.com/latticexyz/mud/commit/e5d208e40b2b2fae223b48716ce3f62c530ea1ca), [`211be2a1`](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9), [`0f3e2e02`](https://github.com/latticexyz/mud/commit/0f3e2e02b5114e08fe700c18326db76816ffad3c), [`1f80a0b5`](https://github.com/latticexyz/mud/commit/1f80a0b52a5c2d051e3697d6e60aad7364b0a925), [`d0878928`](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c), [`4c7fd3eb`](https://github.com/latticexyz/mud/commit/4c7fd3eb29e3d3954f2f1f36ace474a436082651), [`a0341daf`](https://github.com/latticexyz/mud/commit/a0341daf9fd87e8072ffa292a33f508dd37b8ca6), [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`6573e38e`](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`f1cd43bf`](https://github.com/latticexyz/mud/commit/f1cd43bf9264d5a23a3edf2a1ea4212361a72203), [`31ffc9d5`](https://github.com/latticexyz/mud/commit/31ffc9d5d0a6d030cc61349f0f8fbcf6748ebc48), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`63831a26`](https://github.com/latticexyz/mud/commit/63831a264b6b09501f380a4601f82ba7bf07a619), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`5741d53d`](https://github.com/latticexyz/mud/commit/5741d53d0a39990a0d7b2842f1f012973655e060), [`22ee4470`](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612), [`be313068`](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87), [`ac508bf1`](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`9b43029c`](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7), [`55ab88a6`](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314), [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`99ab9cd6`](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`80dd6992`](https://github.com/latticexyz/mud/commit/80dd6992e98c90a91d417fc785d0d53260df6ce2), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`22ba7b67`](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`251170e1`](https://github.com/latticexyz/mud/commit/251170e1ef0b07466c597ea84df0cb49de7d6a23), [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b), [`95c59b20`](https://github.com/latticexyz/mud/commit/95c59b203259c20a6f944c5f9af008b44e2902b6)]: + - @latticexyz/world@2.0.0-next.9 + - @latticexyz/store@2.0.0-next.9 + - @latticexyz/common@2.0.0-next.9 + - @latticexyz/schema-type@2.0.0-next.9 + - @latticexyz/config@2.0.0-next.9 diff --git a/packages/world-modules/package.json b/packages/world-modules/package.json index 274e1f3536..92232e3be8 100644 --- a/packages/world-modules/package.json +++ b/packages/world-modules/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/world-modules", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "World modules", "repository": { "type": "git", diff --git a/packages/world/CHANGELOG.md b/packages/world/CHANGELOG.md index 6e78301e32..2257350b76 100644 --- a/packages/world/CHANGELOG.md +++ b/packages/world/CHANGELOG.md @@ -1,5 +1,631 @@ # Change Log +## 2.0.0-next.9 + +### Major Changes + +- [#1563](https://github.com/latticexyz/mud/pull/1563) [`748f4588`](https://github.com/latticexyz/mud/commit/748f4588a218928bca041760448c26991c0d8033) Thanks [@alvrs](https://github.com/alvrs)! - All `World` methods now revert if the `World` calls itself. + The `World` should never need to externally call itself, since all internal table operations happen via library calls, and all root system operations happen via delegate call. + + It should not be possible to make the `World` call itself as an external actor. + If it were possible to make the `World` call itself, it would be possible to write to internal tables that only the `World` should have access to. + As this is a very important invariance, we made it explicit in a requirement check in every `World` method, rather than just relying on making it impossible to trigger the `World` to call itself. + + This is a breaking change for modules that previously used external calls to the `World` in the `installRoot` method. + In the `installRoot` method, the `World` can only be called via `delegatecall`, and table operations should be performed via the internal table methods (e.g. `_set` instead of `set`). + + Example for how to replace external calls to `world` in root systems / root modules (`installRoot`) with `delegatecall`: + + ```diff + + import { revertWithBytes } from "@latticexyz/world/src/revertWithBytes.sol"; + + - world.grantAccess(tableId, address(hook)); + + (bool success, bytes memory returnData) = address(world).delegatecall( + + abi.encodeCall(world.grantAccess, (tableId, address(hook))) + + ); + + + if (!success) revertWithBytes(returnData); + ``` + +- [#1592](https://github.com/latticexyz/mud/pull/1592) [`c07fa021`](https://github.com/latticexyz/mud/commit/c07fa021501ff92be35c0491dd89bbb8161e1c07) Thanks [@alvrs](https://github.com/alvrs)! - Tables and interfaces in the `world` package are now generated to the `codegen` folder. + This is only a breaking change if you imported tables or codegenerated interfaces from `@latticexyz/world` directly. + If you're using the MUD CLI, the changed import paths are already integrated and no further changes are necessary. + + ```diff + - import { IBaseWorld } from "@latticexyz/world/src/interfaces/IBaseWorld.sol"; + + import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol"; + + ``` + +- [#1354](https://github.com/latticexyz/mud/pull/1354) [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853) Thanks [@dk1a](https://github.com/dk1a)! - 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. + +- [#1527](https://github.com/latticexyz/mud/pull/1527) [`759514d8`](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8) Thanks [@holic](https://github.com/holic)! - 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 + ); + + ``` + +- [#1531](https://github.com/latticexyz/mud/pull/1531) [`d5094a24`](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4) Thanks [@alvrs](https://github.com/alvrs)! - - The `IStoreHook` interface was changed to replace `onBeforeSetField` and `onAfterSetField` with `onBeforeSpliceStaticData`, `onAfterSpliceStaticData`, `onBeforeSpliceDynamicData` and `onAfterSpliceDynamicData`. + + This new interface matches the new `StoreSpliceStaticData` and `StoreSpliceDynamicData` events, and avoids having to read the entire field from storage when only a subset of the field was updated + (e.g. when pushing elements to a field). + + ```diff + interface IStoreHook { + - function onBeforeSetField( + - bytes32 tableId, + - bytes32[] memory keyTuple, + - uint8 fieldIndex, + - bytes memory data, + - FieldLayout fieldLayout + - ) external; + + - function onAfterSetField( + - bytes32 tableId, + - bytes32[] memory keyTuple, + - uint8 fieldIndex, + - bytes memory data, + - FieldLayout fieldLayout + - ) external; + + + function onBeforeSpliceStaticData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint48 start, + + uint40 deleteCount, + + bytes memory data + + ) external; + + + function onAfterSpliceStaticData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint48 start, + + uint40 deleteCount, + + bytes memory data + + ) external; + + + function onBeforeSpliceDynamicData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex, + + uint40 startWithinField, + + uint40 deleteCount, + + bytes memory data, + + PackedCounter encodedLengths + + ) external; + + + function onAfterSpliceDynamicData( + + bytes32 tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex, + + uint40 startWithinField, + + uint40 deleteCount, + + bytes memory data, + + PackedCounter encodedLengths + + ) external; + } + ``` + + - All `calldata` parameters on the `IStoreHook` interface were changed to `memory`, since the functions are called with `memory` from the `World`. + + - `IStore` exposes two new functions: `spliceStaticData` and `spliceDynamicData`. + + These functions provide lower level access to the operations happening under the hood in `setField`, `pushToField`, `popFromField` and `updateInField` and simplify handling + the new splice hooks. + + `StoreCore`'s internal logic was simplified to use the `spliceStaticData` and `spliceDynamicData` functions instead of duplicating similar logic in different functions. + + ```solidity + interface IStore { + // Splice data in the static part of the record + function spliceStaticData( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint48 start, + uint40 deleteCount, + bytes calldata data + ) external; + + // Splice data in the dynamic part of the record + function spliceDynamicData( + bytes32 tableId, + bytes32[] calldata keyTuple, + uint8 dynamicFieldIndex, + uint40 startWithinField, + uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + +- [#1336](https://github.com/latticexyz/mud/pull/1336) [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e) Thanks [@dk1a](https://github.com/dk1a)! - - Add `FieldLayout`, which is a `bytes32` user-type similar to `Schema`. + + Both `FieldLayout` and `Schema` have the same kind of data in the first 4 bytes. + + - 2 bytes for total length of all static fields + - 1 byte for number of static size fields + - 1 byte for number of dynamic size fields + + But whereas `Schema` has `SchemaType` enum in each of the other 28 bytes, `FieldLayout` has static byte lengths in each of the other 28 bytes. + + - Replace `Schema valueSchema` with `FieldLayout fieldLayout` in Store and World contracts. + + `FieldLayout` is more gas-efficient because it already has lengths, and `Schema` has types which need to be converted to lengths. + + - Add `getFieldLayout` to `IStore` interface. + + There is no `FieldLayout` for keys, only for values, because key byte lengths aren't usually relevant on-chain. You can still use `getKeySchema` if you need key types. + + - Add `fieldLayoutToHex` utility to `protocol-parser` package. + + - Add `constants.sol` for constants shared between `FieldLayout`, `Schema` and `PackedCounter`. + +- [#1532](https://github.com/latticexyz/mud/pull/1532) [`ae340b2b`](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623) Thanks [@dk1a](https://github.com/dk1a)! - Store's `getRecord` has been updated to return `staticData`, `encodedLengths`, and `dynamicData` instead of a single `data` blob, to match the new behaviour of Store setter methods. + + If you use codegenerated libraries, you will only need to update `encode` calls. + + ```diff + - bytes memory data = Position.encode(x, y); + + (bytes memory staticData, PackedCounter encodedLengths, bytes memory dynamicData) = Position.encode(x, y); + ``` + +- [#1575](https://github.com/latticexyz/mud/pull/1575) [`e5d208e4`](https://github.com/latticexyz/mud/commit/e5d208e40b2b2fae223b48716ce3f62c530ea1ca) Thanks [@alvrs](https://github.com/alvrs)! - The `registerRootFunctionSelector` function's signature was changed to accept a `string functionSignature` parameter instead of a `bytes4 functionSelector` parameter. + This change enables the `World` to store the function signatures of all registered functions in a `FunctionSignatures` offchain table, which will allow for the automatic generation of interfaces for a given `World` address in the future. + + ```diff + IBaseWorld { + function registerRootFunctionSelector( + ResourceId systemId, + - bytes4 worldFunctionSelector, + + string memory worldFunctionSignature, + bytes4 systemFunctionSelector + ) external returns (bytes4 worldFunctionSelector); + } + ``` + +- [#1483](https://github.com/latticexyz/mud/pull/1483) [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab) Thanks [@holic](https://github.com/holic)! - Store and World contract ABIs are now exported from the `out` directory. You'll need to update your imports like: + + ```diff + - import IBaseWorldAbi from "@latticexyz/world/abi/IBaseWorld.sol/IBaseWorldAbi.json"; + + import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorldAbi.json"; + ``` + + `MudTest.sol` was also moved to the World package. You can update your import like: + + ```diff + - import { MudTest } from "@latticexyz/store/src/MudTest.sol"; + + import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; + ``` + +- [#1574](https://github.com/latticexyz/mud/pull/1574) [`31ffc9d5`](https://github.com/latticexyz/mud/commit/31ffc9d5d0a6d030cc61349f0f8fbcf6748ebc48) Thanks [@alvrs](https://github.com/alvrs)! - The `registerFunctionSelector` function now accepts a single `functionSignature` string paramemer instead of separating function name and function arguments into separate parameters. + + ```diff + IBaseWorld { + function registerFunctionSelector( + ResourceId systemId, + - string memory systemFunctionName, + - string memory systemFunctionArguments + + string memory systemFunctionSignature + ) external returns (bytes4 worldFunctionSelector); + } + ``` + + This is a breaking change if you were manually registering function selectors, e.g. in a `PostDeploy.s.sol` script or a module. + To upgrade, simply replace the separate `systemFunctionName` and `systemFunctionArguments` parameters with a single `systemFunctionSignature` parameter. + + ```diff + world.registerFunctionSelector( + systemId, + - systemFunctionName, + - systemFunctionArguments, + + string(abi.encodePacked(systemFunctionName, systemFunctionArguments)) + ); + ``` + +- [#1544](https://github.com/latticexyz/mud/pull/1544) [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae) Thanks [@alvrs](https://github.com/alvrs)! - All `World` methods acting on namespaces as resources have been updated to use `ResourceId namespaceId` as parameter instead of `bytes14 namespace`. + The reason for this change is to make it clearer when a namespace is used as resource, as opposed to being part of another resource's ID. + + ```diff + + import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + + IBaseWorld { + - function registerNamespace(bytes14 namespace) external; + + function registerNamespace(ResourceId namespaceId) external; + + - function transferOwnership(bytes14 namespace, address newOwner) external; + + function transferOwnership(ResourceId namespaceId, address newOwner) external; + + - function transferBalanceToNamespace(bytes14 fromNamespace, bytes14 toNamespace, uint256 amount) external; + + function transferBalanceToNamespace(ResourceId fromNamespaceId, ResourceId toNamespaceId, uint256 amount) external; + + - function transferBalanceToAddress(bytes14 fromNamespace, address toAddress, uint256 amount) external; + + function transferBalanceToAddress(ResourceId fromNamespaceId, address toAddress, uint256 amount) external; + } + + ``` + +- [#1473](https://github.com/latticexyz/mud/pull/1473) [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a) Thanks [@holic](https://github.com/holic)! - Bump Solidity version to 0.8.21 + +- [#1594](https://github.com/latticexyz/mud/pull/1594) [`5741d53d`](https://github.com/latticexyz/mud/commit/5741d53d0a39990a0d7b2842f1f012973655e060) Thanks [@alvrs](https://github.com/alvrs)! - - `IBaseWorld` now has a `batchCallFrom` method, which allows system calls via `callFrom` to be executed in batch. + + ```solidity + import { SystemCallFromData } from "@latticexyz/world/modules/core/types.sol"; + + interface IBaseWorld { + function batchCallFrom(SystemCallFromData[] calldata systemCalls) external returns (bytes[] memory returnDatas); + } + ``` + + - The `callBatch` method of `IBaseWorld` has been renamed to `batchCall` to align better with the `batchCallFrom` method. + + ```diff + interface IBaseWorld { + - function callBatch(SystemCallData[] calldata systemCalls) external returns (bytes[] memory returnDatas); + + function batchCall(SystemCallData[] calldata systemCalls) external returns (bytes[] memory returnDatas); + } + ``` + +- [#1591](https://github.com/latticexyz/mud/pull/1591) [`251170e1`](https://github.com/latticexyz/mud/commit/251170e1ef0b07466c597ea84df0cb49de7d6a23) Thanks [@alvrs](https://github.com/alvrs)! - All optional modules have been moved from `@latticexyz/world` to `@latticexyz/world-modules`. + If you're using the MUD CLI, the import is already updated and no changes are necessary. + +- [#1581](https://github.com/latticexyz/mud/pull/1581) [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b) Thanks [@alvrs](https://github.com/alvrs)! - - The external `setRecord` and `deleteRecord` methods of `IStore` no longer accept a `FieldLayout` as input, but load it from storage instead. + This is to prevent invalid `FieldLayout` values being passed, which could cause the onchain state to diverge from the indexer state. + However, the internal `StoreCore` library still exposes a `setRecord` and `deleteRecord` method that allows a `FieldLayout` to be passed. + This is because `StoreCore` can only be used internally, so the `FieldLayout` value can be trusted and we can save the gas for accessing storage. + + ```diff + interface IStore { + function setRecord( + ResourceId tableId, + bytes32[] calldata keyTuple, + bytes calldata staticData, + PackedCounter encodedLengths, + bytes calldata dynamicData, + - FieldLayout fieldLayout + ) external; + + function deleteRecord( + ResourceId tableId, + bytes32[] memory keyTuple, + - FieldLayout fieldLayout + ) external; + } + ``` + + - The `spliceStaticData` method and `Store_SpliceStaticData` event of `IStore` and `StoreCore` no longer include `deleteCount` in their signature. + This is because when splicing static data, the data after `start` is always overwritten with `data` instead of being shifted, so `deleteCount` is always the length of the data to be written. + + ```diff + + event Store_SpliceStaticData( + ResourceId indexed tableId, + bytes32[] keyTuple, + uint48 start, + - uint40 deleteCount, + bytes data + ); + + interface IStore { + function spliceStaticData( + ResourceId tableId, + bytes32[] calldata keyTuple, + uint48 start, + - uint40 deleteCount, + bytes calldata data + ) external; + } + ``` + + - The `updateInField` method has been removed from `IStore`, as it's almost identical to the more general `spliceDynamicData`. + If you're manually calling `updateInField`, here is how to upgrade to `spliceDynamicData`: + + ```diff + - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout); + + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields(); + + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet); + ``` + + - All other methods that are only valid for dynamic fields (`pushToField`, `popFromField`, `getFieldSlice`) + have been renamed to make this more explicit (`pushToDynamicField`, `popFromDynamicField`, `getDynamicFieldSlice`). + + Their `fieldIndex` parameter has been replaced by a `dynamicFieldIndex` parameter, which is the index relative to the first dynamic field (i.e. `dynamicFieldIndex` = `fieldIndex` - `numStaticFields`). + The `FieldLayout` parameter has been removed, as it was only used to calculate the `dynamicFieldIndex` in the method. + + ```diff + interface IStore { + - function pushToField( + + function pushToDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + bytes calldata dataToPush, + - FieldLayout fieldLayout + ) external; + + - function popFromField( + + function popFromDynamicField( + ResourceId tableId, + bytes32[] calldata keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + uint256 byteLengthToPop, + - FieldLayout fieldLayout + ) external; + + - function getFieldSlice( + + function getDynamicFieldSlice( + ResourceId tableId, + bytes32[] memory keyTuple, + - uint8 fieldIndex, + + uint8 dynamicFieldIndex, + - FieldLayout fieldLayout, + uint256 start, + uint256 end + ) external view returns (bytes memory data); + } + ``` + + - `IStore` has a new `getDynamicFieldLength` length method, which returns the byte length of the given dynamic field and doesn't require the `FieldLayout`. + + ```diff + IStore { + + function getDynamicFieldLength( + + ResourceId tableId, + + bytes32[] memory keyTuple, + + uint8 dynamicFieldIndex + + ) external view returns (uint256); + } + + ``` + + - `IStore` now has additional overloads for `getRecord`, `getField`, `getFieldLength` and `setField` that don't require a `FieldLength` to be passed, but instead load it from storage. + + - `IStore` now exposes `setStaticField` and `setDynamicField` to save gas by avoiding the dynamic inference of whether the field is static or dynamic. + + - The `getDynamicFieldSlice` method no longer accepts reading outside the bounds of the dynamic field. + This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero. + +### Minor Changes + +- [#1590](https://github.com/latticexyz/mud/pull/1590) [`1f80a0b5`](https://github.com/latticexyz/mud/commit/1f80a0b52a5c2d051e3697d6e60aad7364b0a925) Thanks [@alvrs](https://github.com/alvrs)! - It is now possible for namespace owners to register a fallback delegation control system for the namespace. + This fallback delegation control system is used to verify a delegation in `IBaseWorld.callFrom`, after the user's individual and fallback delegations have been checked. + + ```solidity + IBaseWorld { + function registerNamespaceDelegation( + ResourceId namespaceId, + ResourceId delegationControlId, + bytes memory initCallData + ) external; + } + ``` + +- [#1511](https://github.com/latticexyz/mud/pull/1511) [`9b43029c`](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7) Thanks [@holic](https://github.com/holic)! - 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); + ``` + +- [#1472](https://github.com/latticexyz/mud/pull/1472) [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf) Thanks [@alvrs](https://github.com/alvrs)! - - The `World` contract now has an `initialize` function, which can be called once by the creator of the World to install the core module. + This change allows the registration of all core tables to happen in the `CoreModule`, so no table metadata has to be included in the `World`'s bytecode. + + ```solidity + interface IBaseWorld { + function initialize(IModule coreModule) public; + } + ``` + + - The `World` contract now stores the original creator of the `World` in an immutable state variable. + It is used internally to only allow the original creator to initialize the `World` in a separate transaction. + + ```solidity + interface IBaseWorld { + function creator() external view returns (address); + } + ``` + + - The deploy script is updated to use the `World`'s `initialize` function to install the `CoreModule` instead of `registerRootModule` as before. + +- [#1500](https://github.com/latticexyz/mud/pull/1500) [`95c59b20`](https://github.com/latticexyz/mud/commit/95c59b203259c20a6f944c5f9af008b44e2902b6) Thanks [@yonadaaa](https://github.com/yonadaaa)! - The `World` now has a `callBatch` method which allows multiple system calls to be batched into a single transaction. + + ```solidity + import { SystemCallData } from "@latticexyz/world/modules/core/types.sol"; + + interface IBaseWorld { + function callBatch(SystemCallData[] calldata systemCalls) external returns (bytes[] memory returnDatas); + } + ``` + +### Patch Changes + +- [#1490](https://github.com/latticexyz/mud/pull/1490) [`aea67c58`](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84) Thanks [@alvrs](https://github.com/alvrs)! - Include bytecode for `World` and `Store` in npm packages. + +- [#1508](https://github.com/latticexyz/mud/pull/1508) [`211be2a1`](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9) Thanks [@Boffee](https://github.com/Boffee)! - 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. + +- [#1568](https://github.com/latticexyz/mud/pull/1568) [`d0878928`](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c) Thanks [@alvrs](https://github.com/alvrs)! - Prefixed all errors with their respective library/contract for improved debugging. + +- [#1501](https://github.com/latticexyz/mud/pull/1501) [`4c7fd3eb`](https://github.com/latticexyz/mud/commit/4c7fd3eb29e3d3954f2f1f36ace474a436082651) Thanks [@alvrs](https://github.com/alvrs)! - Remove a workaround for the internal `InstalledModules` table that is not needed anymore. + +- [#1524](https://github.com/latticexyz/mud/pull/1524) [`a0341daf`](https://github.com/latticexyz/mud/commit/a0341daf9fd87e8072ffa292a33f508dd37b8ca6) Thanks [@holic](https://github.com/holic)! - Renamed all `funcSelectorAndArgs` arguments to `callData` for clarity. + +- [#1544](https://github.com/latticexyz/mud/pull/1544) [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae) Thanks [@alvrs](https://github.com/alvrs)! - The `ResourceType` table is removed. + It was previously used to store the resource type for each resource ID in a `World`. This is no longer necessary as the [resource type is now encoded in the resource ID](https://github.com/latticexyz/mud/pull/1544). + + To still be able to determine whether a given resource ID exists, a `ResourceIds` table has been added. + The previous `ResourceType` table was part of `World` and missed tables that were registered directly via `StoreCore.registerTable` instead of via `World.registerTable` (e.g. when a table was registered as part of a root module). + This problem is solved by the new table `ResourceIds` being part of `Store`. + + `StoreCore`'s `hasTable` function was removed in favor of using `ResourceIds.getExists(tableId)` directly. + + ```diff + - import { ResourceType } from "@latticexyz/world/src/tables/ResourceType.sol"; + - import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; + + import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol"; + + - bool tableExists = StoreCore.hasTable(tableId); + + bool tableExists = ResourceIds.getExists(tableId); + + - bool systemExists = ResourceType.get(systemId) != Resource.NONE; + + bool systemExists = ResourceIds.getExists(systemId); + ``` + +- [#1492](https://github.com/latticexyz/mud/pull/1492) [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96) Thanks [@alvrs](https://github.com/alvrs)! - Renamed all occurrences of `key` where it is used as "key tuple" to `keyTuple`. + This is only a breaking change for consumers who manually decode `Store` events, but not for consumers who use the MUD libraries. + + ```diff + event StoreSetRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + bytes data + ); + + event StoreSetField( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + uint8 fieldIndex, + bytes data + ); + + event StoreDeleteRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + ); + + event StoreEphemeralRecord( + bytes32 tableId, + - bytes32[] key, + + bytes32[] keyTuple, + bytes data + ); + ``` + +- [#1452](https://github.com/latticexyz/mud/pull/1452) [`f1cd43bf`](https://github.com/latticexyz/mud/commit/f1cd43bf9264d5a23a3edf2a1ea4212361a72203) Thanks [@alvrs](https://github.com/alvrs)! - Register `Delegations` table in the `CoreModule` + +- [#1586](https://github.com/latticexyz/mud/pull/1586) [`22ee4470`](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612) Thanks [@alvrs](https://github.com/alvrs)! - All `Store` and `World` tables now use the appropriate user-types for `ResourceId`, `FieldLayout` and `Schema` to avoid manual `wrap`/`unwrap`. + +- [#1509](https://github.com/latticexyz/mud/pull/1509) [`be313068`](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87) Thanks [@Boffee](https://github.com/Boffee)! - Optimized the `StoreCore` hash function determining the data location to use less gas. + +- [#1521](https://github.com/latticexyz/mud/pull/1521) [`55ab88a6`](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314) Thanks [@alvrs](https://github.com/alvrs)! - `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); + } + ``` + +- [#1513](https://github.com/latticexyz/mud/pull/1513) [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280) Thanks [@Boffee](https://github.com/Boffee)! - 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 + } + ``` + +- [#1569](https://github.com/latticexyz/mud/pull/1569) [`22ba7b67`](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7) Thanks [@alvrs](https://github.com/alvrs)! - Simplified a couple internal constants used for bitshifting. + +- Updated dependencies [[`aea67c58`](https://github.com/latticexyz/mud/commit/aea67c5804efb2a8b919f5aa3a053d9b04184e84), [`07dd6f32`](https://github.com/latticexyz/mud/commit/07dd6f32c9bb9f0e807bac3586c5cc9833f14ab9), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`f9f9609e`](https://github.com/latticexyz/mud/commit/f9f9609ef69d7fa58cad6a9af3fe6d2eed6d8aa2), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`759514d8`](https://github.com/latticexyz/mud/commit/759514d8b980fa5fe49a4ef919d8008b215f2af8), [`d5094a24`](https://github.com/latticexyz/mud/commit/d5094a2421cf2882a317e3ad9600c8de004b20d4), [`0b8ce3f2`](https://github.com/latticexyz/mud/commit/0b8ce3f2c9b540dbd1c9ba21354f8bf850e72a96), [`de151fec`](https://github.com/latticexyz/mud/commit/de151fec07b63a6022483c1ad133c556dd44992e), [`ae340b2b`](https://github.com/latticexyz/mud/commit/ae340b2bfd98f4812ed3a94c746af3611645a623), [`211be2a1`](https://github.com/latticexyz/mud/commit/211be2a1eba8600ad53be6f8c70c64a8523113b9), [`0f3e2e02`](https://github.com/latticexyz/mud/commit/0f3e2e02b5114e08fe700c18326db76816ffad3c), [`d0878928`](https://github.com/latticexyz/mud/commit/d08789282c8b8d4c12897e2ff5a688af9115fb1c), [`83583a50`](https://github.com/latticexyz/mud/commit/83583a5053de4e5e643572e3b1c0f49467e8e2ab), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`6573e38e`](https://github.com/latticexyz/mud/commit/6573e38e9064121540aa46ce204d8ca5d61ed847), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`6e66c5b7`](https://github.com/latticexyz/mud/commit/6e66c5b745a036c5bc5422819de9c518a6f6cc96), [`65c9546c`](https://github.com/latticexyz/mud/commit/65c9546c4ee8a410b21d032f02b0050442152e7e), [`44a5432a`](https://github.com/latticexyz/mud/commit/44a5432acb9c5af3dca1447c50219a00894c45a9), [`63831a26`](https://github.com/latticexyz/mud/commit/63831a264b6b09501f380a4601f82ba7bf07a619), [`331dbfdc`](https://github.com/latticexyz/mud/commit/331dbfdcbbda404de4b0fd4d439d636ae2033853), [`92de5998`](https://github.com/latticexyz/mud/commit/92de59982fb9fc4e00e50c4a5232ed541f3ce71a), [`22ee4470`](https://github.com/latticexyz/mud/commit/22ee4470047e4611a3cae62e9d0af4713aa1e612), [`be313068`](https://github.com/latticexyz/mud/commit/be313068b158265c2deada55eebfd6ba753abb87), [`ac508bf1`](https://github.com/latticexyz/mud/commit/ac508bf189b098e66b59a725f58a2008537be130), [`bfcb293d`](https://github.com/latticexyz/mud/commit/bfcb293d1931edde7f8a3e077f6f555a26fd1d2f), [`9b43029c`](https://github.com/latticexyz/mud/commit/9b43029c3c888f8e82b146312f5c2e92321c28a7), [`55ab88a6`](https://github.com/latticexyz/mud/commit/55ab88a60adb3ad72ebafef4d50513eb71e3c314), [`af639a26`](https://github.com/latticexyz/mud/commit/af639a26446ca4b689029855767f8a723557f62c), [`5e723b90`](https://github.com/latticexyz/mud/commit/5e723b90e6b18bc70d357ff4b0a1b217611236ae), [`99ab9cd6`](https://github.com/latticexyz/mud/commit/99ab9cd6fff1a732b47d63ead894292661682380), [`c049c23f`](https://github.com/latticexyz/mud/commit/c049c23f48b93ac7881fb1a5a8417831611d5cbf), [`80dd6992`](https://github.com/latticexyz/mud/commit/80dd6992e98c90a91d417fc785d0d53260df6ce2), [`24a6cd53`](https://github.com/latticexyz/mud/commit/24a6cd536f0c31cab93fb7644751cb9376be383d), [`708b49c5`](https://github.com/latticexyz/mud/commit/708b49c50e05f7b67b596e72ebfcbd76e1ff6280), [`22ba7b67`](https://github.com/latticexyz/mud/commit/22ba7b675bd50d1bb18b8a71c0de17c6d70d78c7), [`c4f49240`](https://github.com/latticexyz/mud/commit/c4f49240d7767c3fa7a25926f74b4b62ad67ca04), [`cea754dd`](https://github.com/latticexyz/mud/commit/cea754dde0d8abf7392e93faa319b260956ae92b)]: + - @latticexyz/store@2.0.0-next.9 + - @latticexyz/common@2.0.0-next.9 + - @latticexyz/schema-type@2.0.0-next.9 + - @latticexyz/config@2.0.0-next.9 + ## 2.0.0-next.8 ### Major Changes diff --git a/packages/world/package.json b/packages/world/package.json index 2a725cd877..205f00ba78 100644 --- a/packages/world/package.json +++ b/packages/world/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/world", - "version": "2.0.0-next.8", + "version": "2.0.0-next.9", "description": "World framework", "repository": { "type": "git",