diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 696bb399f6..d39c54e7ff 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -994,7 +994,17 @@ library StoreCoreInternal { } uint256 previousFieldLength = previousEncodedLengths.atIndex(dynamicFieldIndex); - uint256 updatedFieldLength = previousFieldLength - deleteCount + data.length; + + // The field can't be reduced below its length + if (deleteCount > previousFieldLength) { + revert IStoreErrors.Store_InvalidSplice(startWithinField, deleteCount, uint40(previousFieldLength)); + } + + uint256 updatedFieldLength; + unchecked { + // (safe because deleteCount was just checked, and memory length additions can't overflow uint256 due to gas costs) + updatedFieldLength = previousFieldLength - deleteCount + data.length; + } // If the total length of the field is changed, the data has to be appended/removed at the end of the field. // Otherwise offchain indexers would shift the data after inserted data, while onchain the data is truncated at the end. diff --git a/packages/store/test/StoreCoreDynamic.t.sol b/packages/store/test/StoreCoreDynamic.t.sol index 9b5f0a8754..961319dc62 100644 --- a/packages/store/test/StoreCoreDynamic.t.sol +++ b/packages/store/test/StoreCoreDynamic.t.sol @@ -240,4 +240,26 @@ contract StoreCoreDynamicTest is Test, GasReporter, StoreMock { vm.expectRevert(abi.encodeWithSelector(IStoreErrors.Store_IndexOutOfBounds.selector, length, length)); StoreCore.getDynamicFieldSlice(tableId, keyTuple, 0, length, length); } + + /// forge-config: default.allow_internal_expect_revert = true + function testDynamicFieldInvalidDeleteCount() public { + ResourceId tableId = _tableId; + bytes32[] memory keyTuple = _keyTuple; + + // Expect a revert if deleteCount is greater than the current field length + uint256 length = secondDataBytes.length; + vm.expectRevert(abi.encodeWithSelector(IStoreErrors.Store_InvalidSplice.selector, 0, 9, length)); + StoreCore.spliceDynamicData(tableId, keyTuple, 0, 0, 9, hex"191a1b1c"); + } + + /// forge-config: default.allow_internal_expect_revert = true + function testDynamicFieldInvalidSplice() public { + ResourceId tableId = _tableId; + bytes32[] memory keyTuple = _keyTuple; + + // Expect a revert if the data to be removed is not at the end of the field + uint256 length = secondDataBytes.length; + vm.expectRevert(abi.encodeWithSelector(IStoreErrors.Store_InvalidSplice.selector, 0, 1, length)); + StoreCore.spliceDynamicData(tableId, keyTuple, 0, 0, 1, ""); + } } diff --git a/packages/store/ts/flattenStoreLogs.test.ts b/packages/store/ts/flattenStoreLogs.test.ts index 45093624f1..6dccaf2b7a 100644 --- a/packages/store/ts/flattenStoreLogs.test.ts +++ b/packages/store/ts/flattenStoreLogs.test.ts @@ -53,10 +53,10 @@ describe("flattenStoreLogs", async () => { "Store_SetRecord store__ResourceIds (0x6e73000000000000000000000000000000000000000000000000000000000000)", "Store_SetRecord store__ResourceIds (0x6e7373746f726500000000000000000000000000000000000000000000000000)", "Store_SetRecord world__NamespaceOwner (0x6e7373746f726500000000000000000000000000000000000000000000000000)", - "Store_SetRecord world__ResourceAccess (0x6e7373746f726500000000000000000000000000000000000000000000000000,0x0000000000000000000000008dc4168dc8e582f0ef5adbab3c0873856682639b)", + "Store_SetRecord world__ResourceAccess (0x6e7373746f726500000000000000000000000000000000000000000000000000,0x0000000000000000000000005435f08a037e0de78fc59e0c84116f258ee1be37)", "Store_SetRecord store__ResourceIds (0x6e73776f726c6400000000000000000000000000000000000000000000000000)", "Store_SetRecord world__NamespaceOwner (0x6e73776f726c6400000000000000000000000000000000000000000000000000)", - "Store_SetRecord world__ResourceAccess (0x6e73776f726c6400000000000000000000000000000000000000000000000000,0x0000000000000000000000008dc4168dc8e582f0ef5adbab3c0873856682639b)", + "Store_SetRecord world__ResourceAccess (0x6e73776f726c6400000000000000000000000000000000000000000000000000,0x0000000000000000000000005435f08a037e0de78fc59e0c84116f258ee1be37)", "Store_SetRecord store__ResourceIds (0x737900000000000000000000000000004163636573734d616e6167656d656e74)", "Store_SetRecord world__Systems (0x737900000000000000000000000000004163636573734d616e6167656d656e74)", "Store_SetRecord world__SystemRegistry (0x00000000000000000000000073e872dcf77241b6d2afe4169ac27f9d31767292)", @@ -71,8 +71,8 @@ describe("flattenStoreLogs", async () => { "Store_SetRecord world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000002aac36425e74ff6c0778da582c55176394a067b0)", "Store_SetRecord store__ResourceIds (0x73790000000000000000000000000000526567697374726174696f6e00000000)", "Store_SetRecord world__Systems (0x73790000000000000000000000000000526567697374726174696f6e00000000)", - "Store_SetRecord world__SystemRegistry (0x000000000000000000000000047f80b91559887ab304519858c0bce90f2a00a6)", - "Store_SetRecord world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000047f80b91559887ab304519858c0bce90f2a00a6)", + "Store_SetRecord world__SystemRegistry (0x000000000000000000000000c70bcf65ac03f7da2566b01704c7be5c6405e7b6)", + "Store_SetRecord world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000c70bcf65ac03f7da2566b01704c7be5c6405e7b6)", "Store_SetRecord world__FunctionSelector (0x40554c3a00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0x40554c3a00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSelector (0x8d53b20800000000000000000000000000000000000000000000000000000000)", @@ -117,7 +117,7 @@ describe("flattenStoreLogs", async () => { "Store_SetRecord world__FunctionSignatur (0xbfdfaff700000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSelector (0xaa66e9c800000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0xaa66e9c800000000000000000000000000000000000000000000000000000000)", - "Store_SetRecord world__InstalledModules (0x0000000000000000000000009fcc45958071325949b488a784268371f17cb2d7,0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470)", + "Store_SetRecord world__InstalledModules (0x0000000000000000000000009d25d736cfd1aa21afe87aef9db3fb5c1cdc4559,0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470)", "Store_SetRecord world__NamespaceOwner (0x6e73000000000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266)", "Store_SetRecord store__Tables (0x74620000000000000000000000000000506f736974696f6e0000000000000000)", @@ -134,8 +134,8 @@ describe("flattenStoreLogs", async () => { "Store_SetRecord store__ResourceIds (0x746200000000000000000000000000005465727261696e000000000000000000)", "Store_SetRecord store__ResourceIds (0x737900000000000000000000000000004d6f766553797374656d000000000000)", "Store_SetRecord world__Systems (0x737900000000000000000000000000004d6f766553797374656d000000000000)", - "Store_SetRecord world__SystemRegistry (0x000000000000000000000000cbcdc66f9301ccf30b6b46efba8a3015d332dc13)", - "Store_SetRecord world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000cbcdc66f9301ccf30b6b46efba8a3015d332dc13)", + "Store_SetRecord world__SystemRegistry (0x000000000000000000000000a449d01a57109b10304b85c3e5d9e50e9ad0e880)", + "Store_SetRecord world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000a449d01a57109b10304b85c3e5d9e50e9ad0e880)", "Store_SetRecord world__FunctionSelector (0xb591186e00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0xb591186e00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord store__Tables (0x7462000000000000000000000000000043616c6c576974685369676e61747572)", diff --git a/packages/store/ts/getStoreLogs.test.ts b/packages/store/ts/getStoreLogs.test.ts index bef32fa93f..10dce79ee1 100644 --- a/packages/store/ts/getStoreLogs.test.ts +++ b/packages/store/ts/getStoreLogs.test.ts @@ -50,13 +50,13 @@ describe("getStoreLogs", async () => { "Store_SpliceStaticData store__ResourceIds (0x7462776f726c64000000000000000000496e69744d6f64756c65416464726573)", "Store_SpliceStaticData store__ResourceIds (0x6e73000000000000000000000000000000000000000000000000000000000000)", "Store_SpliceStaticData world__NamespaceOwner (0x6e73000000000000000000000000000000000000000000000000000000000000)", - "Store_SpliceStaticData world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000008dc4168dc8e582f0ef5adbab3c0873856682639b)", + "Store_SpliceStaticData world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000005435f08a037e0de78fc59e0c84116f258ee1be37)", "Store_SpliceStaticData store__ResourceIds (0x6e7373746f726500000000000000000000000000000000000000000000000000)", "Store_SpliceStaticData world__NamespaceOwner (0x6e7373746f726500000000000000000000000000000000000000000000000000)", - "Store_SpliceStaticData world__ResourceAccess (0x6e7373746f726500000000000000000000000000000000000000000000000000,0x0000000000000000000000008dc4168dc8e582f0ef5adbab3c0873856682639b)", + "Store_SpliceStaticData world__ResourceAccess (0x6e7373746f726500000000000000000000000000000000000000000000000000,0x0000000000000000000000005435f08a037e0de78fc59e0c84116f258ee1be37)", "Store_SpliceStaticData store__ResourceIds (0x6e73776f726c6400000000000000000000000000000000000000000000000000)", "Store_SpliceStaticData world__NamespaceOwner (0x6e73776f726c6400000000000000000000000000000000000000000000000000)", - "Store_SpliceStaticData world__ResourceAccess (0x6e73776f726c6400000000000000000000000000000000000000000000000000,0x0000000000000000000000008dc4168dc8e582f0ef5adbab3c0873856682639b)", + "Store_SpliceStaticData world__ResourceAccess (0x6e73776f726c6400000000000000000000000000000000000000000000000000,0x0000000000000000000000005435f08a037e0de78fc59e0c84116f258ee1be37)", "Store_SpliceStaticData store__ResourceIds (0x737900000000000000000000000000004163636573734d616e6167656d656e74)", "Store_SetRecord world__Systems (0x737900000000000000000000000000004163636573734d616e6167656d656e74)", "Store_SpliceStaticData world__SystemRegistry (0x00000000000000000000000073e872dcf77241b6d2afe4169ac27f9d31767292)", @@ -71,8 +71,8 @@ describe("getStoreLogs", async () => { "Store_SpliceStaticData world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000002aac36425e74ff6c0778da582c55176394a067b0)", "Store_SpliceStaticData store__ResourceIds (0x73790000000000000000000000000000526567697374726174696f6e00000000)", "Store_SetRecord world__Systems (0x73790000000000000000000000000000526567697374726174696f6e00000000)", - "Store_SpliceStaticData world__SystemRegistry (0x000000000000000000000000047f80b91559887ab304519858c0bce90f2a00a6)", - "Store_SpliceStaticData world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000047f80b91559887ab304519858c0bce90f2a00a6)", + "Store_SpliceStaticData world__SystemRegistry (0x000000000000000000000000c70bcf65ac03f7da2566b01704c7be5c6405e7b6)", + "Store_SpliceStaticData world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000c70bcf65ac03f7da2566b01704c7be5c6405e7b6)", "Store_SetRecord world__FunctionSelector (0x40554c3a00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0x40554c3a00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0x40554c3a00000000000000000000000000000000000000000000000000000000)", @@ -139,9 +139,9 @@ describe("getStoreLogs", async () => { "Store_SetRecord world__FunctionSelector (0xaa66e9c800000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0xaa66e9c800000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0xaa66e9c800000000000000000000000000000000000000000000000000000000)", - "Store_SpliceStaticData world__InstalledModules (0x0000000000000000000000009fcc45958071325949b488a784268371f17cb2d7,0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470)", + "Store_SpliceStaticData world__InstalledModules (0x0000000000000000000000009d25d736cfd1aa21afe87aef9db3fb5c1cdc4559,0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470)", "Store_SpliceStaticData world__NamespaceOwner (0x6e73000000000000000000000000000000000000000000000000000000000000)", - "Store_DeleteRecord world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000008dc4168dc8e582f0ef5adbab3c0873856682639b)", + "Store_DeleteRecord world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000005435f08a037e0de78fc59e0c84116f258ee1be37)", "Store_SpliceStaticData world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266)", "Store_SetRecord store__Tables (0x74620000000000000000000000000000506f736974696f6e0000000000000000)", "Store_SpliceStaticData store__ResourceIds (0x74620000000000000000000000000000506f736974696f6e0000000000000000)", @@ -157,8 +157,8 @@ describe("getStoreLogs", async () => { "Store_SpliceStaticData store__ResourceIds (0x746200000000000000000000000000005465727261696e000000000000000000)", "Store_SpliceStaticData store__ResourceIds (0x737900000000000000000000000000004d6f766553797374656d000000000000)", "Store_SetRecord world__Systems (0x737900000000000000000000000000004d6f766553797374656d000000000000)", - "Store_SpliceStaticData world__SystemRegistry (0x000000000000000000000000cbcdc66f9301ccf30b6b46efba8a3015d332dc13)", - "Store_SpliceStaticData world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000cbcdc66f9301ccf30b6b46efba8a3015d332dc13)", + "Store_SpliceStaticData world__SystemRegistry (0x000000000000000000000000a449d01a57109b10304b85c3e5d9e50e9ad0e880)", + "Store_SpliceStaticData world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000a449d01a57109b10304b85c3e5d9e50e9ad0e880)", "Store_SetRecord world__FunctionSelector (0xb591186e00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0xb591186e00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0xb591186e00000000000000000000000000000000000000000000000000000000)",