From c991c71ae2eed8ec3c8a328962439710cffc135d Mon Sep 17 00:00:00 2001 From: yonada Date: Fri, 1 Mar 2024 11:22:09 +0000 Subject: [PATCH] refactor(store): event interfaces for Store libraries (#2348) --- .changeset/heavy-shirts-dance.md | 5 ++ docs/pages/store/reference/misc.mdx | 70 --------------------- docs/pages/store/reference/store.mdx | 9 ++- packages/store/src/FieldLayout.sol | 32 ++++------ packages/store/src/IFieldLayoutErrors.sol | 19 ++++++ packages/store/src/IPackedCounterErrors.sol | 13 ++++ packages/store/src/ISchemaErrors.sol | 17 +++++ packages/store/src/ISliceErrors.sol | 13 ++++ packages/store/src/IStore.sol | 15 ++++- packages/store/src/IStoreErrors.sol | 7 +++ packages/store/src/PackedCounter.sol | 5 +- packages/store/src/Schema.sol | 25 +++----- packages/store/src/Slice.sol | 5 +- packages/store/test/FieldLayout.t.sol | 11 ++-- packages/store/test/Schema.t.sol | 11 ++-- packages/store/test/StoreCore.t.sol | 3 +- 16 files changed, 137 insertions(+), 123 deletions(-) create mode 100644 .changeset/heavy-shirts-dance.md create mode 100644 packages/store/src/IFieldLayoutErrors.sol create mode 100644 packages/store/src/IPackedCounterErrors.sol create mode 100644 packages/store/src/ISchemaErrors.sol create mode 100644 packages/store/src/ISliceErrors.sol diff --git a/.changeset/heavy-shirts-dance.md b/.changeset/heavy-shirts-dance.md new file mode 100644 index 0000000000..6317deb7f4 --- /dev/null +++ b/.changeset/heavy-shirts-dance.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store": patch +--- + +Added interfaces for all errors that are used by `StoreCore`, which includes `FieldLayout`, `PackedCounter`, `Schema`, and `Slice`. This interfaces are inherited by `IStore`, ensuring that all possible errors are included in the `IStore` ABI for proper decoding in the frontend. diff --git a/docs/pages/store/reference/misc.mdx b/docs/pages/store/reference/misc.mdx index 1d26769632..301a4846d9 100644 --- a/docs/pages/store/reference/misc.mdx +++ b/docs/pages/store/reference/misc.mdx @@ -470,50 +470,6 @@ function encode(uint256[] memory _staticFieldLengths, uint256 numDynamicFields) | -------- | ------------- | ------------------------------------------------------------ | | `` | `FieldLayout` | A FieldLayout structure containing the encoded field layout. | -### Errors - -#### FieldLayoutLib_TooManyFields - -```solidity -error FieldLayoutLib_TooManyFields(uint256 numFields, uint256 maxFields); -``` - -#### FieldLayoutLib_TooManyDynamicFields - -```solidity -error FieldLayoutLib_TooManyDynamicFields(uint256 numFields, uint256 maxFields); -``` - -#### FieldLayoutLib_Empty - -```solidity -error FieldLayoutLib_Empty(); -``` - -#### FieldLayoutLib_InvalidStaticDataLength - -```solidity -error FieldLayoutLib_InvalidStaticDataLength(uint256 staticDataLength, uint256 computedStaticDataLength); -``` - -#### FieldLayoutLib_StaticLengthIsZero - -```solidity -error FieldLayoutLib_StaticLengthIsZero(uint256 index); -``` - -#### FieldLayoutLib_StaticLengthIsNotZero - -```solidity -error FieldLayoutLib_StaticLengthIsNotZero(uint256 index); -``` - -#### FieldLayoutLib_StaticLengthDoesNotFitInAWord - -```solidity -error FieldLayoutLib_StaticLengthDoesNotFitInAWord(uint256 index); -``` - ## FieldLayout [Git Source](https://github.com/latticexyz/mud/blob/main/packages/store/src/FieldLayout.sol) @@ -991,24 +947,6 @@ function encode(SchemaType[] memory schemas) internal pure returns (Schema); | -------- | -------- | ------------------- | | `` | `Schema` | The encoded Schema. | -### Errors - -#### SchemaLib_InvalidLength - -_Error raised when the provided schema has an invalid length._ - -```solidity -error SchemaLib_InvalidLength(uint256 length); -``` - -#### SchemaLib_StaticTypeAfterDynamicType - -_Error raised when a static type is placed after a dynamic type in a schema._ - -```solidity -error SchemaLib_StaticTypeAfterDynamicType(); -``` - ## Schema [Git Source](https://github.com/latticexyz/mud/blob/main/packages/store/src/Schema.sol) @@ -1192,14 +1130,6 @@ function getSubslice(bytes memory data, uint256 start, uint256 end) internal pur | -------- | ------- | ------------------------------------- | | `` | `Slice` | A new Slice representing the subslice | -### Errors - -#### Slice_OutOfBounds - -```solidity -error Slice_OutOfBounds(bytes data, uint256 start, uint256 end); -``` - ## Slice [Git Source](https://github.com/latticexyz/mud/blob/main/packages/store/src/Slice.sol) diff --git a/docs/pages/store/reference/store.mdx b/docs/pages/store/reference/store.mdx index 250240a5e9..5cb36a4cb7 100644 --- a/docs/pages/store/reference/store.mdx +++ b/docs/pages/store/reference/store.mdx @@ -5,7 +5,9 @@ [Git Source](https://github.com/latticexyz/mud/blob/main/packages/store/src/IStore.sol) **Inherits:** -[IStoreData](/store/reference/store#istoredata), [IStoreRegistration](/store/reference/store#istoreregistration), [IStoreErrors](/store/reference/store#istoreerrors) +[IStoreData](/store/reference/store#istoredata), [IStoreRegistration](/store/reference/store#istoreregistration), [IStoreErrors](/store/reference/store#istoreerrors), [IFieldLayoutErrors](/src/IFieldLayoutErrors.sol/interface.IFieldLayoutErrors.md), [IPackedCounterErrors](/src/IPackedCounterErrors.sol/interface.IPackedCounterErrors.md), [ISchemaErrors](/src/ISchemaErrors.sol/interface.ISchemaErrors.md), [ISliceErrors](/src/ISliceErrors.sol/interface.ISliceErrors.md) + +IStore implements the error interfaces for each library that it uses. ## IStoreEvents @@ -104,6 +106,11 @@ event Store_DeleteRecord(ResourceId indexed tableId, bytes32[] keyTuple); [Git Source](https://github.com/latticexyz/mud/blob/main/packages/store/src/IStoreErrors.sol) +This interface includes errors for Store. + +_We bundle these errors in an interface (instead of at the file-level or in their corresponding library) so they can be inherited by IStore. +This ensures that all possible errors are included in the IStore ABI for proper decoding in the frontend._ + ### Errors #### Store_TableAlreadyExists diff --git a/packages/store/src/FieldLayout.sol b/packages/store/src/FieldLayout.sol index 04cde8862e..1cc3bb5154 100644 --- a/packages/store/src/FieldLayout.sol +++ b/packages/store/src/FieldLayout.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.24; import { WORD_SIZE, WORD_LAST_INDEX, BYTE_TO_BITS, MAX_TOTAL_FIELDS, MAX_DYNAMIC_FIELDS, LayoutOffsets } from "./constants.sol"; +import { IFieldLayoutErrors } from "./IFieldLayoutErrors.sol"; /** * @title FieldLayout @@ -27,14 +28,6 @@ using FieldLayoutInstance for FieldLayout global; * various constraints regarding the length and size of the fields. */ library FieldLayoutLib { - error FieldLayoutLib_TooManyFields(uint256 numFields, uint256 maxFields); - error FieldLayoutLib_TooManyDynamicFields(uint256 numFields, uint256 maxFields); - error FieldLayoutLib_Empty(); - error FieldLayoutLib_InvalidStaticDataLength(uint256 staticDataLength, uint256 computedStaticDataLength); - error FieldLayoutLib_StaticLengthIsZero(uint256 index); - error FieldLayoutLib_StaticLengthIsNotZero(uint256 index); - error FieldLayoutLib_StaticLengthDoesNotFitInAWord(uint256 index); - /** * @notice Encodes the given field layout into a single bytes32. * @dev Ensures various constraints on the length and size of the fields. @@ -47,17 +40,18 @@ library FieldLayoutLib { uint256 fieldLayout; uint256 totalLength; uint256 totalFields = _staticFieldLengths.length + numDynamicFields; - if (totalFields > MAX_TOTAL_FIELDS) revert FieldLayoutLib_TooManyFields(totalFields, MAX_TOTAL_FIELDS); + if (totalFields > MAX_TOTAL_FIELDS) + revert IFieldLayoutErrors.FieldLayout_TooManyFields(totalFields, MAX_TOTAL_FIELDS); if (numDynamicFields > MAX_DYNAMIC_FIELDS) - revert FieldLayoutLib_TooManyDynamicFields(numDynamicFields, MAX_DYNAMIC_FIELDS); + revert IFieldLayoutErrors.FieldLayout_TooManyDynamicFields(numDynamicFields, MAX_DYNAMIC_FIELDS); // Compute the total static length and store the field lengths in the encoded fieldLayout for (uint256 i; i < _staticFieldLengths.length; ) { uint256 staticByteLength = _staticFieldLengths[i]; if (staticByteLength == 0) { - revert FieldLayoutLib_StaticLengthIsZero(i); + revert IFieldLayoutErrors.FieldLayout_StaticLengthIsZero(i); } else if (staticByteLength > WORD_SIZE) { - revert FieldLayoutLib_StaticLengthDoesNotFitInAWord(i); + revert IFieldLayoutErrors.FieldLayout_StaticLengthDoesNotFitInAWord(i); } unchecked { @@ -156,18 +150,18 @@ library FieldLayoutInstance { */ function validate(FieldLayout fieldLayout) internal pure { if (fieldLayout.isEmpty()) { - revert FieldLayoutLib.FieldLayoutLib_Empty(); + revert IFieldLayoutErrors.FieldLayout_Empty(); } uint256 _numDynamicFields = fieldLayout.numDynamicFields(); if (_numDynamicFields > MAX_DYNAMIC_FIELDS) { - revert FieldLayoutLib.FieldLayoutLib_TooManyDynamicFields(_numDynamicFields, MAX_DYNAMIC_FIELDS); + revert IFieldLayoutErrors.FieldLayout_TooManyDynamicFields(_numDynamicFields, MAX_DYNAMIC_FIELDS); } uint256 _numStaticFields = fieldLayout.numStaticFields(); uint256 _numTotalFields = _numStaticFields + _numDynamicFields; if (_numTotalFields > MAX_TOTAL_FIELDS) { - revert FieldLayoutLib.FieldLayoutLib_TooManyFields(_numTotalFields, MAX_TOTAL_FIELDS); + revert IFieldLayoutErrors.FieldLayout_TooManyFields(_numTotalFields, MAX_TOTAL_FIELDS); } // Static lengths must be valid @@ -175,9 +169,9 @@ library FieldLayoutInstance { for (uint256 i; i < _numStaticFields; ) { uint256 staticByteLength = fieldLayout.atIndex(i); if (staticByteLength == 0) { - revert FieldLayoutLib.FieldLayoutLib_StaticLengthIsZero(i); + revert IFieldLayoutErrors.FieldLayout_StaticLengthIsZero(i); } else if (staticByteLength > WORD_SIZE) { - revert FieldLayoutLib.FieldLayoutLib_StaticLengthDoesNotFitInAWord(i); + revert IFieldLayoutErrors.FieldLayout_StaticLengthDoesNotFitInAWord(i); } _staticDataLength += staticByteLength; unchecked { @@ -186,13 +180,13 @@ library FieldLayoutInstance { } // Static length sums must match if (_staticDataLength != fieldLayout.staticDataLength()) { - revert FieldLayoutLib.FieldLayoutLib_InvalidStaticDataLength(fieldLayout.staticDataLength(), _staticDataLength); + revert IFieldLayoutErrors.FieldLayout_InvalidStaticDataLength(fieldLayout.staticDataLength(), _staticDataLength); } // Unused fields must be zero for (uint256 i = _numStaticFields; i < MAX_TOTAL_FIELDS; i++) { uint256 staticByteLength = fieldLayout.atIndex(i); if (staticByteLength != 0) { - revert FieldLayoutLib.FieldLayoutLib_StaticLengthIsNotZero(i); + revert IFieldLayoutErrors.FieldLayout_StaticLengthIsNotZero(i); } } } diff --git a/packages/store/src/IFieldLayoutErrors.sol b/packages/store/src/IFieldLayoutErrors.sol new file mode 100644 index 0000000000..6d421e4b85 --- /dev/null +++ b/packages/store/src/IFieldLayoutErrors.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +/** + * @title IFieldLayoutErrors + * @author MUD (https://mud.dev) by Lattice (https://lattice.xyz) + * @notice This interface includes errors for the FieldLayout library. + * @dev We bundle these errors in an interface (instead of at the file-level or in their corresponding libraries) so they can be inherited by IStore. + * This ensures that all possible errors are included in the IStore ABI for proper decoding in the frontend. + */ +interface IFieldLayoutErrors { + error FieldLayout_TooManyFields(uint256 numFields, uint256 maxFields); + error FieldLayout_TooManyDynamicFields(uint256 numFields, uint256 maxFields); + error FieldLayout_Empty(); + error FieldLayout_InvalidStaticDataLength(uint256 staticDataLength, uint256 computedStaticDataLength); + error FieldLayout_StaticLengthIsZero(uint256 index); + error FieldLayout_StaticLengthIsNotZero(uint256 index); + error FieldLayout_StaticLengthDoesNotFitInAWord(uint256 index); +} diff --git a/packages/store/src/IPackedCounterErrors.sol b/packages/store/src/IPackedCounterErrors.sol new file mode 100644 index 0000000000..05eb8f50df --- /dev/null +++ b/packages/store/src/IPackedCounterErrors.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +/** + * @title IPackedCounterErrors + * @author MUD (https://mud.dev) by Lattice (https://lattice.xyz) + * @notice This interface includes errors for the PackedCounter library. + * @dev We bundle these errors in an interface (instead of at the file-level or in their corresponding libraries) so they can be inherited by IStore. + * This ensures that all possible errors are included in the IStore ABI for proper decoding in the frontend. + */ +interface IPackedCounterErrors { + error PackedCounter_InvalidLength(uint256 length); +} diff --git a/packages/store/src/ISchemaErrors.sol b/packages/store/src/ISchemaErrors.sol new file mode 100644 index 0000000000..103f630a19 --- /dev/null +++ b/packages/store/src/ISchemaErrors.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +/** + * @title ISchemaErrors + * @author MUD (https://mud.dev) by Lattice (https://lattice.xyz) + * @notice This interface includes errors for the Schema library. + * @dev We bundle these errors in an interface (instead of at the file-level or in their corresponding libraries) so they can be inherited by IStore. + * This ensures that all possible errors are included in the IStore ABI for proper decoding in the frontend. + */ +interface ISchemaErrors { + /// @dev Error raised when the provided schema has an invalid length. + error Schema_InvalidLength(uint256 length); + + /// @dev Error raised when a static type is placed after a dynamic type in a schema. + error Schema_StaticTypeAfterDynamicType(); +} diff --git a/packages/store/src/ISliceErrors.sol b/packages/store/src/ISliceErrors.sol new file mode 100644 index 0000000000..6660aa2718 --- /dev/null +++ b/packages/store/src/ISliceErrors.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +/** + * @title ISliceErrors + * @author MUD (https://mud.dev) by Lattice (https://lattice.xyz) + * @notice This interface includes errors for the Slice library. + * @dev We bundle these errors in an interface (instead of at the file-level or in their corresponding libraries) so they can be inherited by IStore. + * This ensures that all possible errors are included in the IStore ABI for proper decoding in the frontend. + */ +interface ISliceErrors { + error Slice_OutOfBounds(bytes data, uint256 start, uint256 end); +} diff --git a/packages/store/src/IStore.sol b/packages/store/src/IStore.sol index 6510e115dc..71f7cb673f 100644 --- a/packages/store/src/IStore.sol +++ b/packages/store/src/IStore.sol @@ -4,9 +4,22 @@ pragma solidity >=0.8.24; import { IStoreErrors } from "./IStoreErrors.sol"; import { IStoreData } from "./IStoreData.sol"; import { IStoreRegistration } from "./IStoreRegistration.sol"; +import { IFieldLayoutErrors } from "./IFieldLayoutErrors.sol"; +import { IPackedCounterErrors } from "./IPackedCounterErrors.sol"; +import { ISchemaErrors } from "./ISchemaErrors.sol"; +import { ISliceErrors } from "./ISliceErrors.sol"; /** * @title IStore * @author MUD (https://mud.dev) by Lattice (https://lattice.xyz) + * @notice IStore implements the error interfaces for each library that it uses. */ -interface IStore is IStoreData, IStoreRegistration, IStoreErrors {} +interface IStore is + IStoreData, + IStoreRegistration, + IStoreErrors, + IFieldLayoutErrors, + IPackedCounterErrors, + ISchemaErrors, + ISliceErrors +{} diff --git a/packages/store/src/IStoreErrors.sol b/packages/store/src/IStoreErrors.sol index 62d63f085d..8cef288f36 100644 --- a/packages/store/src/IStoreErrors.sol +++ b/packages/store/src/IStoreErrors.sol @@ -3,6 +3,13 @@ pragma solidity >=0.8.24; import { ResourceId } from "./ResourceId.sol"; +/** + * @title IStoreErrors + * @author MUD (https://mud.dev) by Lattice (https://lattice.xyz) + * @notice This interface includes errors for Store. + * @dev We bundle these errors in an interface (instead of at the file-level or in their corresponding library) so they can be inherited by IStore. + * This ensures that all possible errors are included in the IStore ABI for proper decoding in the frontend. + */ interface IStoreErrors { // Errors include a stringified version of the tableId for easier debugging if cleartext tableIds are used error Store_TableAlreadyExists(ResourceId tableId, string tableIdString); diff --git a/packages/store/src/PackedCounter.sol b/packages/store/src/PackedCounter.sol index 4ae34dddfa..fba2ac07fb 100644 --- a/packages/store/src/PackedCounter.sol +++ b/packages/store/src/PackedCounter.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.24; import { BYTE_TO_BITS } from "./constants.sol"; +import { IPackedCounterErrors } from "./IPackedCounterErrors.sol"; /** * @title PackedCounter Type Definition @@ -139,8 +140,6 @@ library PackedCounterLib { * @dev Offers decoding, extracting, and setting functionalities for a PackedCounter. */ library PackedCounterInstance { - error PackedCounter_InvalidLength(uint256 length); - /** * @notice Decode the accumulated counter from a PackedCounter. * @dev Extracts the right-most 7 bytes of a PackedCounter. @@ -178,7 +177,7 @@ library PackedCounterInstance { uint256 newValueAtIndex ) internal pure returns (PackedCounter) { if (newValueAtIndex > MAX_VAL) { - revert PackedCounter_InvalidLength(newValueAtIndex); + revert IPackedCounterErrors.PackedCounter_InvalidLength(newValueAtIndex); } uint256 rawPackedCounter = uint256(PackedCounter.unwrap(packedCounter)); diff --git a/packages/store/src/Schema.sol b/packages/store/src/Schema.sol index 761368313d..16d9fc674b 100644 --- a/packages/store/src/Schema.sol +++ b/packages/store/src/Schema.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.24; import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; import { WORD_LAST_INDEX, BYTE_TO_BITS, MAX_TOTAL_FIELDS, MAX_DYNAMIC_FIELDS, LayoutOffsets } from "./constants.sol"; +import { ISchemaErrors } from "./ISchemaErrors.sol"; /** * @title Schema handling in Lattice @@ -24,19 +25,13 @@ using SchemaInstance for Schema global; * @dev Static utility functions for handling Schemas. */ library SchemaLib { - /// @dev Error raised when the provided schema has an invalid length. - error SchemaLib_InvalidLength(uint256 length); - - /// @dev Error raised when a static type is placed after a dynamic type in a schema. - error SchemaLib_StaticTypeAfterDynamicType(); - /** * @notice Encodes a given schema into a single bytes32. * @param schemas The list of SchemaTypes that constitute the schema. * @return The encoded Schema. */ function encode(SchemaType[] memory schemas) internal pure returns (Schema) { - if (schemas.length > MAX_TOTAL_FIELDS) revert SchemaLib_InvalidLength(schemas.length); + if (schemas.length > MAX_TOTAL_FIELDS) revert ISchemaErrors.Schema_InvalidLength(schemas.length); uint256 schema; uint256 totalLength; uint256 dynamicFields; @@ -54,7 +49,7 @@ library SchemaLib { } } else if (dynamicFields > 0) { // Revert if we have seen a dynamic field before, but now we see a static field - revert SchemaLib_StaticTypeAfterDynamicType(); + revert ISchemaErrors.Schema_StaticTypeAfterDynamicType(); } unchecked { @@ -68,7 +63,7 @@ library SchemaLib { } // Require MAX_DYNAMIC_FIELDS - if (dynamicFields > MAX_DYNAMIC_FIELDS) revert SchemaLib_InvalidLength(dynamicFields); + if (dynamicFields > MAX_DYNAMIC_FIELDS) revert ISchemaErrors.Schema_InvalidLength(dynamicFields); // Get the static field count uint256 staticFields; @@ -162,23 +157,23 @@ library SchemaInstance { */ function validate(Schema schema, bool allowEmpty) internal pure { // Schema must not be empty - if (!allowEmpty && schema.isEmpty()) revert SchemaLib.SchemaLib_InvalidLength(0); + if (!allowEmpty && schema.isEmpty()) revert ISchemaErrors.Schema_InvalidLength(0); // Schema must have no more than MAX_DYNAMIC_FIELDS uint256 _numDynamicFields = schema.numDynamicFields(); - if (_numDynamicFields > MAX_DYNAMIC_FIELDS) revert SchemaLib.SchemaLib_InvalidLength(_numDynamicFields); + if (_numDynamicFields > MAX_DYNAMIC_FIELDS) revert ISchemaErrors.Schema_InvalidLength(_numDynamicFields); uint256 _numStaticFields = schema.numStaticFields(); // Schema must not have more than MAX_TOTAL_FIELDS in total uint256 _numTotalFields = _numStaticFields + _numDynamicFields; - if (_numTotalFields > MAX_TOTAL_FIELDS) revert SchemaLib.SchemaLib_InvalidLength(_numTotalFields); + if (_numTotalFields > MAX_TOTAL_FIELDS) revert ISchemaErrors.Schema_InvalidLength(_numTotalFields); // No dynamic field can be before a dynamic field uint256 _staticDataLength; for (uint256 i; i < _numStaticFields; ) { uint256 staticByteLength = schema.atIndex(i).getStaticByteLength(); if (staticByteLength == 0) { - revert SchemaLib.SchemaLib_StaticTypeAfterDynamicType(); + revert ISchemaErrors.Schema_StaticTypeAfterDynamicType(); } _staticDataLength += staticByteLength; unchecked { @@ -188,14 +183,14 @@ library SchemaInstance { // Static length sums must match if (_staticDataLength != schema.staticDataLength()) { - revert SchemaLib.SchemaLib_InvalidLength(schema.staticDataLength()); + revert ISchemaErrors.Schema_InvalidLength(schema.staticDataLength()); } // No static field can be after a dynamic field for (uint256 i = _numStaticFields; i < _numTotalFields; ) { uint256 staticByteLength = schema.atIndex(i).getStaticByteLength(); if (staticByteLength > 0) { - revert SchemaLib.SchemaLib_StaticTypeAfterDynamicType(); + revert ISchemaErrors.Schema_StaticTypeAfterDynamicType(); } unchecked { i++; diff --git a/packages/store/src/Slice.sol b/packages/store/src/Slice.sol index b6565f3757..6fcdc114d9 100644 --- a/packages/store/src/Slice.sol +++ b/packages/store/src/Slice.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.24; import { Memory } from "./Memory.sol"; import { DecodeSlice } from "./tightcoder/DecodeSlice.sol"; +import { ISliceErrors } from "./ISliceErrors.sol"; // Acknowledgements: // Based on @dk1a's Slice.sol library (https://github.com/dk1a/solidity-stringutils/blob/main/src/Slice.sol) @@ -18,8 +19,6 @@ using DecodeSlice for Slice global; * @author MUD (https://mud.dev) by Lattice (https://lattice.xyz) */ library SliceLib { - error Slice_OutOfBounds(bytes data, uint256 start, uint256 end); - uint256 constant MASK_LEN = uint256(type(uint128).max); /** @@ -57,7 +56,7 @@ library SliceLib { */ function getSubslice(bytes memory data, uint256 start, uint256 end) internal pure returns (Slice) { // TODO this check helps catch bugs and can eventually be removed - if (start > end || end > data.length) revert Slice_OutOfBounds(data, start, end); + if (start > end || end > data.length) revert ISliceErrors.Slice_OutOfBounds(data, start, end); uint256 pointer; assembly { diff --git a/packages/store/test/FieldLayout.t.sol b/packages/store/test/FieldLayout.t.sol index 915d96618f..bb835a882b 100644 --- a/packages/store/test/FieldLayout.t.sol +++ b/packages/store/test/FieldLayout.t.sol @@ -6,6 +6,7 @@ import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { FieldLayout, FieldLayoutLib } from "../src/FieldLayout.sol"; import { FieldLayoutEncodeHelper } from "./FieldLayoutEncodeHelper.sol"; import { MAX_TOTAL_FIELDS, MAX_DYNAMIC_FIELDS } from "../src/constants.sol"; +import { IFieldLayoutErrors } from "../src/IFieldLayoutErrors.sol"; // TODO add tests for all lengths contract FieldLayoutTest is Test, GasReporter { @@ -36,12 +37,12 @@ contract FieldLayoutTest is Test, GasReporter { } function testInvalidFieldLayoutStaticTypeIsZero() public { - vm.expectRevert(abi.encodeWithSelector(FieldLayoutLib.FieldLayoutLib_StaticLengthIsZero.selector, 1)); + vm.expectRevert(abi.encodeWithSelector(IFieldLayoutErrors.FieldLayout_StaticLengthIsZero.selector, 1)); FieldLayoutEncodeHelper.encode(1, 0, 1); } function testInvalidFieldLayoutStaticTypeDoesNotFitInAWord() public { - vm.expectRevert(abi.encodeWithSelector(FieldLayoutLib.FieldLayoutLib_StaticLengthDoesNotFitInAWord.selector, 1)); + vm.expectRevert(abi.encodeWithSelector(IFieldLayoutErrors.FieldLayout_StaticLengthDoesNotFitInAWord.selector, 1)); FieldLayoutEncodeHelper.encode(1, 33, 1); } @@ -97,7 +98,7 @@ contract FieldLayoutTest is Test, GasReporter { fieldLayout[16] = 32; vm.expectRevert( abi.encodeWithSelector( - FieldLayoutLib.FieldLayoutLib_TooManyFields.selector, + IFieldLayoutErrors.FieldLayout_TooManyFields.selector, fieldLayout.length + dynamicFields, MAX_TOTAL_FIELDS ) @@ -117,7 +118,7 @@ contract FieldLayoutTest is Test, GasReporter { uint256 dynamicFields = 6; vm.expectRevert( abi.encodeWithSelector( - FieldLayoutLib.FieldLayoutLib_TooManyDynamicFields.selector, + IFieldLayoutErrors.FieldLayout_TooManyDynamicFields.selector, fieldLayout.length + dynamicFields, MAX_DYNAMIC_FIELDS ) @@ -202,7 +203,7 @@ contract FieldLayoutTest is Test, GasReporter { vm.expectRevert( abi.encodeWithSelector( - FieldLayoutLib.FieldLayoutLib_TooManyDynamicFields.selector, + IFieldLayoutErrors.FieldLayout_TooManyDynamicFields.selector, encodedFieldLayout.numDynamicFields(), MAX_DYNAMIC_FIELDS ) diff --git a/packages/store/test/Schema.t.sol b/packages/store/test/Schema.t.sol index 3762448b0c..e648afb589 100644 --- a/packages/store/test/Schema.t.sol +++ b/packages/store/test/Schema.t.sol @@ -7,6 +7,7 @@ import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol" import { Schema, SchemaLib } from "../src/Schema.sol"; import { SchemaEncodeHelper } from "./SchemaEncodeHelper.sol"; import { WORD_LAST_INDEX, BYTE_TO_BITS, LayoutOffsets } from "../src/constants.sol"; +import { ISchemaErrors } from "../src/ISchemaErrors.sol"; /** * @notice Encodes a given schema into a single bytes32, without checks. @@ -89,7 +90,7 @@ contract SchemaTest is Test, GasReporter { } function testInvalidSchemaStaticAfterDynamic() public { - vm.expectRevert(abi.encodeWithSelector(SchemaLib.SchemaLib_StaticTypeAfterDynamicType.selector)); + vm.expectRevert(abi.encodeWithSelector(ISchemaErrors.Schema_StaticTypeAfterDynamicType.selector)); SchemaEncodeHelper.encode(SchemaType.UINT8, SchemaType.UINT32_ARRAY, SchemaType.UINT16); } @@ -159,7 +160,7 @@ contract SchemaTest is Test, GasReporter { schema[26] = SchemaType.UINT32_ARRAY; schema[27] = SchemaType.UINT32_ARRAY; schema[28] = SchemaType.UINT32_ARRAY; - vm.expectRevert(abi.encodeWithSelector(SchemaLib.SchemaLib_InvalidLength.selector, schema.length)); + vm.expectRevert(abi.encodeWithSelector(ISchemaErrors.Schema_InvalidLength.selector, schema.length)); SchemaLib.encode(schema); } @@ -183,7 +184,7 @@ contract SchemaTest is Test, GasReporter { schema[3] = SchemaType.UINT32_ARRAY; schema[4] = SchemaType.UINT32_ARRAY; schema[5] = SchemaType.UINT32_ARRAY; - vm.expectRevert(abi.encodeWithSelector(SchemaLib.SchemaLib_InvalidLength.selector, schema.length)); + vm.expectRevert(abi.encodeWithSelector(ISchemaErrors.Schema_InvalidLength.selector, schema.length)); SchemaLib.encode(schema); } @@ -296,7 +297,7 @@ contract SchemaTest is Test, GasReporter { Schema encodedSchema = Schema.wrap(keccak256("some invalid schema")); vm.expectRevert( - abi.encodeWithSelector(SchemaLib.SchemaLib_InvalidLength.selector, encodedSchema.numDynamicFields()) + abi.encodeWithSelector(ISchemaErrors.Schema_InvalidLength.selector, encodedSchema.numDynamicFields()) ); encodedSchema.validate({ allowEmpty: false }); @@ -334,7 +335,7 @@ contract SchemaTest is Test, GasReporter { schema[27] = SchemaType.UINT32_ARRAY; Schema encodedSchema = encodeUnsafe(schema); - vm.expectRevert(SchemaLib.SchemaLib_StaticTypeAfterDynamicType.selector); + vm.expectRevert(ISchemaErrors.Schema_StaticTypeAfterDynamicType.selector); encodedSchema.validate({ allowEmpty: false }); } diff --git a/packages/store/test/StoreCore.t.sol b/packages/store/test/StoreCore.t.sol index 2b88c5c6dd..cd416d88c9 100644 --- a/packages/store/test/StoreCore.t.sol +++ b/packages/store/test/StoreCore.t.sol @@ -26,6 +26,7 @@ import { MirrorSubscriber, indexerTableId } from "./MirrorSubscriber.sol"; import { RevertSubscriber } from "./RevertSubscriber.sol"; import { EchoSubscriber } from "./EchoSubscriber.sol"; import { setDynamicDataLengthAtIndex } from "./setDynamicDataLengthAtIndex.sol"; +import { IFieldLayoutErrors } from "../src/IFieldLayoutErrors.sol"; struct TestStruct { uint128 firstData; @@ -130,7 +131,7 @@ contract StoreCoreTest is Test, StoreMock { vm.expectRevert( abi.encodeWithSelector( - FieldLayoutLib.FieldLayoutLib_TooManyDynamicFields.selector, + IFieldLayoutErrors.FieldLayout_TooManyDynamicFields.selector, invalidFieldLayout.numDynamicFields(), 5 )