From 43254a29f22b84b6f7a17cdb5e7d39da2265901f Mon Sep 17 00:00:00 2001 From: alvrs Date: Sun, 14 May 2023 11:32:33 +0200 Subject: [PATCH] test(store): fix tests after foundry update, move gas report to separate tests --- packages/store/gas-report.json | 338 ++++++------- packages/store/test/StoreCore.t.sol | 280 ++++------- packages/store/test/StoreCoreGas.t.sol | 626 +++++++++++++++++++++++++ packages/store/test/StoreMock.sol | 66 +++ 4 files changed, 962 insertions(+), 348 deletions(-) create mode 100644 packages/store/test/StoreCoreGas.t.sol create mode 100644 packages/store/test/StoreMock.sol diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 9c164034b0..4bd1c1e38c 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -276,334 +276,334 @@ "gasUsed": 1108 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreDynamic.t.sol", + "name": "get field slice (cold, 1 slot)", + "functionCall": "bytes memory secondFieldSlice = StoreCore.getFieldSlice(_table, _key, 1, schema, 0, 4)", + "gasUsed": 8161 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "get field slice (warm, 1 slot)", + "functionCall": "secondFieldSlice = StoreCore.getFieldSlice(_table, _key, 1, schema, 4, 8)", + "gasUsed": 2188 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "get field slice (semi-cold, 1 slot)", + "functionCall": "bytes memory thirdFieldSlice = StoreCore.getFieldSlice(_table, _key, 2, schema, 4, 32)", + "gasUsed": 4193 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "get field slice (warm, 2 slots)", + "functionCall": "thirdFieldSlice = StoreCore.getFieldSlice(_table, _key, 2, schema, 8, 40)", + "gasUsed": 4475 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "get field length (cold, 1 slot)", + "functionCall": "uint256 length = StoreCore.getFieldLength(_table, _key, 1, schema)", + "gasUsed": 7968 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "get field length (warm, 1 slot)", + "functionCall": "length = StoreCore.getFieldLength(_table, _key, 1, schema)", + "gasUsed": 1964 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "get field length (warm due to , 2 slots)", + "functionCall": "uint256 length = StoreCore.getFieldLength(_table, _key, 2, schema)", + "gasUsed": 7968 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "get field length (warm, 2 slots)", + "functionCall": "length = StoreCore.getFieldLength(_table, _key, 2, schema)", + "gasUsed": 1964 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "pop from field (cold, 1 slot, 1 uint32 item)", + "functionCall": "StoreCore.popFromField(_table, _key, 1, byteLengthToPop)", + "gasUsed": 29270 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "pop from field (warm, 1 slot, 1 uint32 item)", + "functionCall": "StoreCore.popFromField(_table, _key, 1, byteLengthToPop)", + "gasUsed": 19348 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "pop from field (cold, 2 slots, 10 uint32 items)", + "functionCall": "StoreCore.popFromField(_table, _key, 2, byteLengthToPop)", + "gasUsed": 31149 + }, + { + "source": "test/StoreCoreDynamic.t.sol", + "name": "pop from field (warm, 2 slots, 10 uint32 items)", + "functionCall": "StoreCore.popFromField(_table, _key, 2, byteLengthToPop)", + "gasUsed": 19231 + }, + { + "source": "test/StoreCoreGas.t.sol", "name": "access non-existing record", - "functionCall": "bytes memory data1 = StoreCore.getRecord(table, key)", - "gasUsed": 7316 + "functionCall": "StoreCore.getRecord(table, key)", + "gasUsed": 7310 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "access static field of non-existing record", - "functionCall": "bytes memory data2 = StoreCore.getField(table, key, 0)", - "gasUsed": 2988 + "functionCall": "StoreCore.getField(table, key, 0)", + "gasUsed": 2982 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "access dynamic field of non-existing record", - "functionCall": "bytes memory data3 = StoreCore.getField(table, key, 1)", - "gasUsed": 3599 + "functionCall": "StoreCore.getField(table, key, 1)", + "gasUsed": 3593 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "access length of dynamic field of non-existing record", - "functionCall": "uint256 data3Length = StoreCore.getFieldLength(table, key, 1, schema)", - "gasUsed": 1342 + "functionCall": "StoreCore.getFieldLength(table, key, 1, schema)", + "gasUsed": 1331 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "access slice of dynamic field of non-existing record", - "functionCall": "bytes memory data3Slice = StoreCore.getFieldSlice(table, key, 1, schema, 0, 0)", - "gasUsed": 1338 + "functionCall": "StoreCore.getFieldSlice(table, key, 1, schema, 0, 0)", + "gasUsed": 1331 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "delete record (complex data, 3 slots)", "functionCall": "StoreCore.deleteRecord(table, key)", - "gasUsed": 10952 + "gasUsed": 11001 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "Check for existence of table (existent)", "functionCall": "StoreCore.hasTable(table)", "gasUsed": 1111 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "check for existence of table (non-existent)", "functionCall": "StoreCore.hasTable(table2)", "gasUsed": 3138 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "register subscriber", "functionCall": "StoreCore.registerStoreHook(table, subscriber)", - "gasUsed": 65478 + "gasUsed": 65566 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set record on table with subscriber", "functionCall": "StoreCore.setRecord(table, key, data)", - "gasUsed": 73889 + "gasUsed": 73972 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set static field on table with subscriber", "functionCall": "StoreCore.setField(table, key, 0, data)", - "gasUsed": 31889 + "gasUsed": 31960 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "delete record on table with subscriber", "functionCall": "StoreCore.deleteRecord(table, key)", - "gasUsed": 24405 + "gasUsed": 24545 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "register subscriber", "functionCall": "StoreCore.registerStoreHook(table, subscriber)", - "gasUsed": 65478 + "gasUsed": 65566 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set (dynamic) record on table with subscriber", "functionCall": "StoreCore.setRecord(table, key, data)", - "gasUsed": 167326 + "gasUsed": 167409 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set (dynamic) field on table with subscriber", "functionCall": "StoreCore.setField(table, key, 1, arrayDataBytes)", - "gasUsed": 34983 + "gasUsed": 34919 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "delete (dynamic) record on table with subscriber", "functionCall": "StoreCore.deleteRecord(table, key)", - "gasUsed": 25884 + "gasUsed": 26059 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "push to field (1 slot, 1 uint32 item)", "functionCall": "StoreCore.pushToField(table, key, 1, secondDataToPush)", - "gasUsed": 16996 + "gasUsed": 17072 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "push to field (2 slots, 10 uint32 items)", "functionCall": "StoreCore.pushToField(table, key, 2, thirdDataToPush)", - "gasUsed": 39718 + "gasUsed": 39780 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "StoreCore: register schema", "functionCall": "StoreCore.registerSchema(table, schema, keySchema)", - "gasUsed": 54854 + "gasUsed": 54877 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "StoreCore: get schema (warm)", - "functionCall": "Schema loadedSchema = StoreCore.getSchema(table)", - "gasUsed": 1143 + "functionCall": "StoreCore.getSchema(table)", + "gasUsed": 1136 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "StoreCore: get key schema (warm)", - "functionCall": "Schema loadedKeySchema = StoreCore.getKeySchema(table)", - "gasUsed": 1211 + "functionCall": "StoreCore.getKeySchema(table)", + "gasUsed": 1204 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set complex record with dynamic data (4 slots)", "functionCall": "StoreCore.setRecord(table, key, data)", - "gasUsed": 107641 + "gasUsed": 107714 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "get complex record with dynamic data (4 slots)", - "functionCall": "bytes memory loadedData = StoreCore.getRecord(table, key)", - "gasUsed": 6449 + "functionCall": "StoreCore.getRecord(table, key)", + "gasUsed": 6443 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "compare: Set complex record with dynamic data using native solidity", "functionCall": "testStruct = _testStruct", - "gasUsed": 116842 + "gasUsed": 116839 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "compare: Set complex record with dynamic data using abi.encode", "functionCall": "testMapping[1234] = abi.encode(_testStruct)", "gasUsed": 267377 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set dynamic length of dynamic index 0", "functionCall": "StoreCoreInternal._setDynamicDataLengthAtIndex(table, key, 0, 10)", "gasUsed": 23600 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set dynamic length of dynamic index 1", "functionCall": "StoreCoreInternal._setDynamicDataLengthAtIndex(table, key, 1, 99)", - "gasUsed": 1720 + "gasUsed": 1719 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "reduce dynamic length of dynamic index 0", "functionCall": "StoreCoreInternal._setDynamicDataLengthAtIndex(table, key, 0, 5)", "gasUsed": 1707 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set static field (1 slot)", - "functionCall": "StoreCore.setField(table, key, 0, abi.encodePacked(firstDataBytes))", - "gasUsed": 38011 + "functionCall": "StoreCore.setField(table, key, 0, firstDataPacked)", + "gasUsed": 37980 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "get static field (1 slot)", - "functionCall": "bytes memory loadedData = StoreCore.getField(table, key, 0)", - "gasUsed": 2990 + "functionCall": "StoreCore.getField(table, key, 0)", + "gasUsed": 2980 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set static field (overlap 2 slot)", - "functionCall": "StoreCore.setField(table, key, 1, abi.encodePacked(secondDataBytes))", - "gasUsed": 33026 + "functionCall": "StoreCore.setField(table, key, 1, secondDataPacked)", + "gasUsed": 35009 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "get static field (overlap 2 slot)", - "functionCall": "loadedData = StoreCore.getField(table, key, 1)", - "gasUsed": 3882 + "functionCall": "StoreCore.getField(table, key, 1)", + "gasUsed": 3877 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set dynamic field (1 slot, first dynamic field)", "functionCall": "StoreCore.setField(table, key, 2, thirdDataBytes)", - "gasUsed": 55329 + "gasUsed": 57377 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "get dynamic field (1 slot, first dynamic field)", - "functionCall": "loadedData = StoreCore.getField(table, key, 2)", - "gasUsed": 3831 + "functionCall": "StoreCore.getField(table, key, 2)", + "gasUsed": 3812 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set dynamic field (1 slot, second dynamic field)", "functionCall": "StoreCore.setField(table, key, 3, fourthDataBytes)", - "gasUsed": 35469 + "gasUsed": 35503 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "get dynamic field (1 slot, second dynamic field)", - "functionCall": "loadedData = StoreCore.getField(table, key, 3)", - "gasUsed": 3850 + "functionCall": "StoreCore.getField(table, key, 3)", + "gasUsed": 3825 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set static record (1 slot)", "functionCall": "StoreCore.setRecord(table, key, data)", - "gasUsed": 37316 + "gasUsed": 37369 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "get static record (1 slot)", - "functionCall": "bytes memory loadedData = StoreCore.getRecord(table, key, schema)", - "gasUsed": 1335 + "functionCall": "StoreCore.getRecord(table, key, schema)", + "gasUsed": 1329 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "set static record (2 slots)", "functionCall": "StoreCore.setRecord(table, key, data)", - "gasUsed": 59881 + "gasUsed": 59940 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "get static record (2 slots)", - "functionCall": "bytes memory loadedData = StoreCore.getRecord(table, key, schema)", - "gasUsed": 1584 + "functionCall": "StoreCore.getRecord(table, key, schema)", + "gasUsed": 1578 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "StoreCore: set table metadata", "functionCall": "StoreCore.setMetadata(table, tableName, fieldNames)", - "gasUsed": 251762 + "gasUsed": 251850 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "update in field (1 slot, 1 uint32 item)", "functionCall": "StoreCore.updateInField(table, key, 1, 4 * 1, secondDataForUpdate)", - "gasUsed": 16533 + "gasUsed": 16604 }, { - "source": "test/StoreCore.t.sol", + "source": "test/StoreCoreGas.t.sol", "name": "push to field (2 slots, 6 uint64 items)", "functionCall": "StoreCore.updateInField(table, key, 2, 8 * 1, thirdDataForUpdate)", - "gasUsed": 17636 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "get field slice (cold, 1 slot)", - "functionCall": "bytes memory secondFieldSlice = StoreCore.getFieldSlice(_table, _key, 1, schema, 0, 4)", - "gasUsed": 8161 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "get field slice (warm, 1 slot)", - "functionCall": "secondFieldSlice = StoreCore.getFieldSlice(_table, _key, 1, schema, 4, 8)", - "gasUsed": 2188 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "get field slice (semi-cold, 1 slot)", - "functionCall": "bytes memory thirdFieldSlice = StoreCore.getFieldSlice(_table, _key, 2, schema, 4, 32)", - "gasUsed": 4193 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "get field slice (warm, 2 slots)", - "functionCall": "thirdFieldSlice = StoreCore.getFieldSlice(_table, _key, 2, schema, 8, 40)", - "gasUsed": 4475 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "get field length (cold, 1 slot)", - "functionCall": "uint256 length = StoreCore.getFieldLength(_table, _key, 1, schema)", - "gasUsed": 7968 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "get field length (warm, 1 slot)", - "functionCall": "length = StoreCore.getFieldLength(_table, _key, 1, schema)", - "gasUsed": 1964 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "get field length (warm due to , 2 slots)", - "functionCall": "uint256 length = StoreCore.getFieldLength(_table, _key, 2, schema)", - "gasUsed": 7968 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "get field length (warm, 2 slots)", - "functionCall": "length = StoreCore.getFieldLength(_table, _key, 2, schema)", - "gasUsed": 1964 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "functionCall": "StoreCore.popFromField(_table, _key, 1, byteLengthToPop)", - "gasUsed": 29270 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "functionCall": "StoreCore.popFromField(_table, _key, 1, byteLengthToPop)", - "gasUsed": 19348 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "functionCall": "StoreCore.popFromField(_table, _key, 2, byteLengthToPop)", - "gasUsed": 31149 - }, - { - "source": "test/StoreCoreDynamic.t.sol", - "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "functionCall": "StoreCore.popFromField(_table, _key, 2, byteLengthToPop)", - "gasUsed": 19231 + "gasUsed": 17699 }, { "source": "test/StoreMetadata.t.sol", diff --git a/packages/store/test/StoreCore.t.sol b/packages/store/test/StoreCore.t.sol index 0f67a3f14f..98529b6ffc 100644 --- a/packages/store/test/StoreCore.t.sol +++ b/packages/store/test/StoreCore.t.sol @@ -15,6 +15,7 @@ import { IStoreErrors } from "../src/IStoreErrors.sol"; import { IStore, IStoreHook } from "../src/IStore.sol"; import { StoreSwitch } from "../src/StoreSwitch.sol"; import { StoreMetadataData, StoreMetadata } from "../src/codegen/Tables.sol"; +import { StoreMock } from "./StoreMock.sol"; struct TestStruct { uint128 firstData; @@ -22,52 +23,12 @@ struct TestStruct { uint32[] thirdData; } -contract StoreCoreTest is Test, StoreReadWithStubs { +contract StoreCoreTest is Test, StoreMock { TestStruct private testStruct; + mapping(uint256 => bytes) private testMapping; Schema defaultKeySchema = SchemaLib.encode(SchemaType.BYTES32); - // Expose an external setRecord function for testing purposes of indexers (see testHooks) - function setRecord(bytes32 table, bytes32[] calldata key, bytes calldata data) public override { - StoreCore.setRecord(table, key, data); - } - - // Expose an external setField function for testing purposes of indexers (see testHooks) - function setField(bytes32 table, bytes32[] calldata key, uint8 schemaIndex, bytes calldata data) public override { - StoreCore.setField(table, key, schemaIndex, data); - } - - // Expose an external pushToField function for testing purposes of indexers (see testHooks) - function pushToField( - bytes32 table, - bytes32[] calldata key, - uint8 schemaIndex, - bytes calldata dataToPush - ) public override { - StoreCore.pushToField(table, key, schemaIndex, dataToPush); - } - - // Expose an external updateInField function for testing purposes of indexers (see testHooks) - function updateInField( - bytes32 table, - bytes32[] calldata key, - uint8 schemaIndex, - uint256 startByteIndex, - bytes calldata dataToSet - ) public override { - StoreCore.updateInField(table, key, schemaIndex, startByteIndex, dataToSet); - } - - // Expose an external deleteRecord function for testing purposes of indexers (see testHooks) - function deleteRecord(bytes32 table, bytes32[] calldata key) public override { - StoreCore.deleteRecord(table, key); - } - - // Expose an external registerSchema function for testing purposes of indexers (see testHooks) - function registerSchema(bytes32 table, Schema schema, Schema keySchema) public override { - StoreCore.registerSchema(table, schema, keySchema); - } - function testRegisterAndGetSchema() public { Schema schema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16, SchemaType.UINT8, SchemaType.UINT16); Schema keySchema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16); @@ -80,21 +41,18 @@ contract StoreCoreTest is Test, StoreReadWithStubs { vm.expectEmit(true, true, true, true); emit StoreSetRecord(StoreCoreInternal.SCHEMA_TABLE, key, abi.encodePacked(schema.unwrap(), keySchema.unwrap())); - // !gasreport StoreCore: register schema - StoreCore.registerSchema(table, schema, keySchema); + IStore(this).registerSchema(table, schema, keySchema); - // !gasreport StoreCore: get schema (warm) - Schema loadedSchema = StoreCore.getSchema(table); + Schema loadedSchema = IStore(this).getSchema(table); assertEq(loadedSchema.unwrap(), schema.unwrap()); - // !gasreport StoreCore: get key schema (warm) - Schema loadedKeySchema = StoreCore.getKeySchema(table); + Schema loadedKeySchema = IStore(this).getKeySchema(table); assertEq(loadedKeySchema.unwrap(), keySchema.unwrap()); } function testFailRegisterInvalidSchema() public { - StoreCore.registerSchema( + IStore(this).registerSchema( keccak256("table"), Schema.wrap(keccak256("random bytes as schema")), Schema.wrap(keccak256("random bytes as key schema")) @@ -105,12 +63,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { Schema schema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16, SchemaType.UINT8, SchemaType.UINT16); bytes32 table = keccak256("some.table"); bytes32 table2 = keccak256("other.table"); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); - // !gasreport Check for existence of table (existent) StoreCore.hasTable(table); - // !gasreport check for existence of table (non-existent) StoreCore.hasTable(table2); assertTrue(StoreCore.hasTable(table)); @@ -127,10 +83,9 @@ contract StoreCoreTest is Test, StoreReadWithStubs { fieldNames[1] = "field2"; // Register table - StoreCore.registerSchema(table, schema, keySchema); + IStore(this).registerSchema(table, schema, keySchema); - // !gasreport StoreCore: set table metadata - StoreCore.setMetadata(table, tableName, fieldNames); + IStore(this).setMetadata(table, tableName, fieldNames); // Get metadata for table StoreMetadataData memory metadata = StoreMetadata.get(table); @@ -149,10 +104,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { fieldNames[1] = "field2"; // Register table - StoreCore.registerSchema(table, schema, keySchema); + IStore(this).registerSchema(table, schema, keySchema); vm.expectRevert(abi.encodeWithSelector(IStoreErrors.StoreCore_InvalidFieldNamesLength.selector, 1, 2)); - StoreCore.setMetadata(table, tableName, fieldNames); + IStore(this).setMetadata(table, tableName, fieldNames); } function testSetAndGetDynamicDataLength() public { @@ -167,14 +122,13 @@ contract StoreCoreTest is Test, StoreReadWithStubs { ); // Register schema - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); // Create some key bytes32[] memory key = new bytes32[](1); key[0] = bytes32("some key"); // Set dynamic data length of dynamic index 0 - // !gasreport set dynamic length of dynamic index 0 StoreCoreInternal._setDynamicDataLengthAtIndex(table, key, 0, 10); PackedCounter encodedLength = StoreCoreInternal._loadEncodedDynamicDataLength(table, key); @@ -183,7 +137,6 @@ contract StoreCoreTest is Test, StoreReadWithStubs { assertEq(encodedLength.total(), 10); // Set dynamic data length of dynamic index 1 - // !gasreport set dynamic length of dynamic index 1 StoreCoreInternal._setDynamicDataLengthAtIndex(table, key, 1, 99); encodedLength = StoreCoreInternal._loadEncodedDynamicDataLength(table, key); @@ -192,7 +145,6 @@ contract StoreCoreTest is Test, StoreReadWithStubs { assertEq(encodedLength.total(), 109); // Reduce dynamic data length of dynamic index 0 again - // !gasreport reduce dynamic length of dynamic index 0 StoreCoreInternal._setDynamicDataLengthAtIndex(table, key, 0, 5); encodedLength = StoreCoreInternal._loadEncodedDynamicDataLength(table, key); @@ -206,7 +158,7 @@ contract StoreCoreTest is Test, StoreReadWithStubs { Schema schema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16, SchemaType.UINT8, SchemaType.UINT16); bytes32 table = keccak256("some.table"); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); // Set data bytes memory data = abi.encodePacked(bytes1(0x01), bytes2(0x0203), bytes1(0x04), bytes2(0x0506)); @@ -218,12 +170,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { vm.expectEmit(true, true, true, true); emit StoreSetRecord(table, key, data); - // !gasreport set static record (1 slot) - StoreCore.setRecord(table, key, data); + IStore(this).setRecord(table, key, data); // Get data - // !gasreport get static record (1 slot) - bytes memory loadedData = StoreCore.getRecord(table, key, schema); + bytes memory loadedData = IStore(this).getRecord(table, key, schema); assertTrue(Bytes.equals(data, loadedData)); } @@ -232,7 +182,7 @@ contract StoreCoreTest is Test, StoreReadWithStubs { // Register table's schema Schema schema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16, SchemaType.UINT8, SchemaType.UINT16); bytes32 table = keccak256("some.table"); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); // Set data bytes memory data = abi.encodePacked(bytes1(0x01), bytes2(0x0203), bytes1(0x04)); @@ -241,14 +191,14 @@ contract StoreCoreTest is Test, StoreReadWithStubs { key[0] = keccak256("some.key"); // This should fail because the data is not 6 bytes long - StoreCore.setRecord(table, key, data); + IStore(this).setRecord(table, key, data); } function testSetAndGetStaticDataSpanningWords() public { // Register table's schema Schema schema = SchemaLib.encode(SchemaType.UINT128, SchemaType.UINT256); bytes32 table = keccak256("some.table"); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); // Set data bytes memory data = abi.encodePacked( @@ -263,12 +213,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { vm.expectEmit(true, true, true, true); emit StoreSetRecord(table, key, data); - // !gasreport set static record (2 slots) - StoreCore.setRecord(table, key, data); + IStore(this).setRecord(table, key, data); // Get data - // !gasreport get static record (2 slots) - bytes memory loadedData = StoreCore.getRecord(table, key, schema); + bytes memory loadedData = IStore(this).getRecord(table, key, schema); assertTrue(Bytes.equals(data, loadedData)); } @@ -279,7 +227,7 @@ contract StoreCoreTest is Test, StoreReadWithStubs { { // Register table's schema Schema schema = SchemaLib.encode(SchemaType.UINT128, SchemaType.UINT32_ARRAY, SchemaType.UINT32_ARRAY); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); } bytes16 firstDataBytes = bytes16(0x0102030405060708090a0b0c0d0e0f10); @@ -326,12 +274,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { emit StoreSetRecord(table, key, data); // Set data - // !gasreport set complex record with dynamic data (4 slots) - StoreCore.setRecord(table, key, data); + IStore(this).setRecord(table, key, data); // Get data - // !gasreport get complex record with dynamic data (4 slots) - bytes memory loadedData = StoreCore.getRecord(table, key); + bytes memory loadedData = IStore(this).getRecord(table, key); assertEq(loadedData.length, data.length); assertEq(keccak256(loadedData), keccak256(data)); @@ -345,10 +291,8 @@ contract StoreCoreTest is Test, StoreReadWithStubs { _testStruct.thirdData[1] = 0x1d1e1f20; _testStruct.thirdData[2] = 0x21222324; - // !gasreport compare: Set complex record with dynamic data using native solidity testStruct = _testStruct; - // !gasreport compare: Set complex record with dynamic data using abi.encode testMapping[1234] = abi.encode(_testStruct); } @@ -363,7 +307,7 @@ contract StoreCoreTest is Test, StoreReadWithStubs { SchemaType.UINT32_ARRAY, SchemaType.UINT32_ARRAY ); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); } bytes16 firstDataBytes = bytes16(0x0102030405060708090a0b0c0d0e0f10); @@ -372,56 +316,56 @@ contract StoreCoreTest is Test, StoreReadWithStubs { bytes32[] memory key = new bytes32[](1); key[0] = bytes32("some.key"); + bytes memory firstDataPacked = abi.encodePacked(firstDataBytes); + // Expect a StoreSetField event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(table, key, 0, abi.encodePacked(firstDataBytes)); + emit StoreSetField(table, key, 0, firstDataPacked); // Set first field - // !gasreport set static field (1 slot) - StoreCore.setField(table, key, 0, abi.encodePacked(firstDataBytes)); + IStore(this).setField(table, key, 0, firstDataPacked); //////////////// // Static data //////////////// // Get first field - // !gasreport get static field (1 slot) - bytes memory loadedData = StoreCore.getField(table, key, 0); + bytes memory loadedData = IStore(this).getField(table, key, 0); // Verify loaded data is correct assertEq(loadedData.length, 16); assertEq(bytes16(loadedData), bytes16(firstDataBytes)); // Verify the second index is not set yet - assertEq(uint256(bytes32(StoreCore.getField(table, key, 1))), 0); + assertEq(uint256(bytes32(IStore(this).getField(table, key, 1))), 0); // Set second field bytes32 secondDataBytes = keccak256("some data"); + bytes memory secondDataPacked = abi.encodePacked(secondDataBytes); + // Expect a StoreSetField event to be emitted vm.expectEmit(true, true, true, true); - emit StoreSetField(table, key, 1, abi.encodePacked(secondDataBytes)); + emit StoreSetField(table, key, 1, secondDataPacked); - // !gasreport set static field (overlap 2 slot) - StoreCore.setField(table, key, 1, abi.encodePacked(secondDataBytes)); + IStore(this).setField(table, key, 1, secondDataPacked); // Get second field - // !gasreport get static field (overlap 2 slot) - loadedData = StoreCore.getField(table, key, 1); + loadedData = IStore(this).getField(table, key, 1); // Verify loaded data is correct assertEq(loadedData.length, 32); assertEq(bytes32(loadedData), secondDataBytes); // Verify the first field didn't change - assertEq(bytes16(StoreCore.getField(table, key, 0)), bytes16(firstDataBytes)); + assertEq(bytes16(IStore(this).getField(table, key, 0)), bytes16(firstDataBytes)); // Verify the full static data is correct - assertEq(StoreCore.getSchema(table).staticDataLength(), 48); - assertEq(Bytes.slice16(StoreCore.getRecord(table, key), 0), firstDataBytes); - assertEq(Bytes.slice32(StoreCore.getRecord(table, key), 16), secondDataBytes); + assertEq(IStore(this).getSchema(table).staticDataLength(), 48); + assertEq(Bytes.slice16(IStore(this).getRecord(table, key), 0), firstDataBytes); + assertEq(Bytes.slice32(IStore(this).getRecord(table, key), 16), secondDataBytes); assertEq( - keccak256(SliceLib.getSubslice(StoreCore.getRecord(table, key), 0, 48).toBytes()), + keccak256(SliceLib.getSubslice(IStore(this).getRecord(table, key), 0, 48).toBytes()), keccak256(abi.encodePacked(firstDataBytes, secondDataBytes)) ); @@ -451,12 +395,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { emit StoreSetField(table, key, 2, thirdDataBytes); // Set third field - // !gasreport set dynamic field (1 slot, first dynamic field) - StoreCore.setField(table, key, 2, thirdDataBytes); + IStore(this).setField(table, key, 2, thirdDataBytes); // Get third field - // !gasreport get dynamic field (1 slot, first dynamic field) - loadedData = StoreCore.getField(table, key, 2); + loadedData = IStore(this).getField(table, key, 2); // Verify loaded data is correct assertEq(SliceLib.fromBytes(loadedData).decodeArray_uint32().length, 2); @@ -464,23 +406,21 @@ contract StoreCoreTest is Test, StoreReadWithStubs { assertEq(keccak256(loadedData), keccak256(thirdDataBytes)); // Verify the fourth field is not set yet - assertEq(StoreCore.getField(table, key, 3).length, 0); + assertEq(IStore(this).getField(table, key, 3).length, 0); // Verify none of the previous fields were impacted - assertEq(bytes16(StoreCore.getField(table, key, 0)), bytes16(firstDataBytes)); - assertEq(bytes32(StoreCore.getField(table, key, 1)), bytes32(secondDataBytes)); + assertEq(bytes16(IStore(this).getField(table, key, 0)), bytes16(firstDataBytes)); + assertEq(bytes32(IStore(this).getField(table, key, 1)), bytes32(secondDataBytes)); // Expect a StoreSetField event to be emitted vm.expectEmit(true, true, true, true); emit StoreSetField(table, key, 3, fourthDataBytes); // Set fourth field - // !gasreport set dynamic field (1 slot, second dynamic field) - StoreCore.setField(table, key, 3, fourthDataBytes); + IStore(this).setField(table, key, 3, fourthDataBytes); // Get fourth field - // !gasreport get dynamic field (1 slot, second dynamic field) - loadedData = StoreCore.getField(table, key, 3); + loadedData = IStore(this).getField(table, key, 3); // Verify loaded data is correct assertEq(loadedData.length, fourthDataBytes.length); @@ -489,7 +429,7 @@ contract StoreCoreTest is Test, StoreReadWithStubs { // Verify all fields are correct PackedCounter encodedLengths = PackedCounterLib.pack(uint16(thirdDataBytes.length), uint16(fourthDataBytes.length)); assertEq( - keccak256(StoreCore.getRecord(table, key)), + keccak256(IStore(this).getRecord(table, key)), keccak256( abi.encodePacked(firstDataBytes, secondDataBytes, encodedLengths.unwrap(), thirdDataBytes, fourthDataBytes) ) @@ -501,7 +441,7 @@ contract StoreCoreTest is Test, StoreReadWithStubs { // Register table's schema Schema schema = SchemaLib.encode(SchemaType.UINT128, SchemaType.UINT32_ARRAY, SchemaType.UINT32_ARRAY); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); bytes16 firstDataBytes = bytes16(0x0102030405060708090a0b0c0d0e0f10); @@ -543,10 +483,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { key[0] = bytes32("some.key"); // Set data - StoreCore.setRecord(table, key, data); + IStore(this).setRecord(table, key, data); // Get data - bytes memory loadedData = StoreCore.getRecord(table, key); + bytes memory loadedData = IStore(this).getRecord(table, key); assertEq(loadedData.length, data.length); assertEq(keccak256(loadedData), keccak256(data)); @@ -556,11 +496,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { emit StoreDeleteRecord(table, key); // Delete data - // !gasreport delete record (complex data, 3 slots) - StoreCore.deleteRecord(table, key); + IStore(this).deleteRecord(table, key); // Verify data is deleted - loadedData = StoreCore.getRecord(table, key); + loadedData = IStore(this).getRecord(table, key); assertEq(keccak256(loadedData), keccak256(new bytes(schema.staticDataLength()))); } @@ -570,7 +509,7 @@ contract StoreCoreTest is Test, StoreReadWithStubs { { // Register table's schema Schema schema = SchemaLib.encode(SchemaType.UINT256, SchemaType.UINT32_ARRAY, SchemaType.UINT32_ARRAY); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); } // Create key @@ -596,10 +535,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { } // Set fields - StoreCore.setField(table, key, 0, abi.encodePacked(firstDataBytes)); - StoreCore.setField(table, key, 1, secondDataBytes); + IStore(this).setField(table, key, 0, abi.encodePacked(firstDataBytes)); + IStore(this).setField(table, key, 1, secondDataBytes); // Initialize a field with push - StoreCore.pushToField(table, key, 2, thirdDataBytes); + IStore(this).pushToField(table, key, 2, thirdDataBytes); // Create data to push bytes memory secondDataToPush; @@ -615,11 +554,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { emit StoreSetField(table, key, 1, newSecondDataBytes); // Push to second field - // !gasreport push to field (1 slot, 1 uint32 item) - StoreCore.pushToField(table, key, 1, secondDataToPush); + IStore(this).pushToField(table, key, 1, secondDataToPush); // Get second field - bytes memory loadedData = StoreCore.getField(table, key, 1); + bytes memory loadedData = IStore(this).getField(table, key, 1); // Verify loaded data is correct assertEq(SliceLib.fromBytes(loadedData).decodeArray_uint32().length, 2 + 1); @@ -627,8 +565,8 @@ contract StoreCoreTest is Test, StoreReadWithStubs { assertEq(loadedData, newSecondDataBytes); // Verify none of the other fields were impacted - assertEq(bytes32(StoreCore.getField(table, key, 0)), firstDataBytes); - assertEq(StoreCore.getField(table, key, 2), thirdDataBytes); + assertEq(bytes32(IStore(this).getField(table, key, 0)), firstDataBytes); + assertEq(IStore(this).getField(table, key, 2), thirdDataBytes); // Create data to push bytes memory thirdDataToPush; @@ -653,11 +591,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { emit StoreSetField(table, key, 2, newThirdDataBytes); // Push to third field - // !gasreport push to field (2 slots, 10 uint32 items) - StoreCore.pushToField(table, key, 2, thirdDataToPush); + IStore(this).pushToField(table, key, 2, thirdDataToPush); // Get third field - loadedData = StoreCore.getField(table, key, 2); + loadedData = IStore(this).getField(table, key, 2); // Verify loaded data is correct assertEq(SliceLib.fromBytes(loadedData).decodeArray_uint32().length, 3 + 10); @@ -665,8 +602,8 @@ contract StoreCoreTest is Test, StoreReadWithStubs { assertEq(loadedData, newThirdDataBytes); // Verify none of the other fields were impacted - assertEq(bytes32(StoreCore.getField(table, key, 0)), firstDataBytes); - assertEq(StoreCore.getField(table, key, 1), newSecondDataBytes); + assertEq(bytes32(IStore(this).getField(table, key, 0)), firstDataBytes); + assertEq(IStore(this).getField(table, key, 1), newSecondDataBytes); } function testUpdateInField() public { @@ -675,7 +612,7 @@ contract StoreCoreTest is Test, StoreReadWithStubs { { // Register table's schema Schema schema = SchemaLib.encode(SchemaType.UINT256, SchemaType.UINT32_ARRAY, SchemaType.UINT64_ARRAY); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); } // Create key @@ -699,9 +636,9 @@ contract StoreCoreTest is Test, StoreReadWithStubs { bytes memory thirdDataBytes = EncodeArray.encode(thirdData); // Set fields - StoreCore.setField(table, key, 0, abi.encodePacked(firstDataBytes)); - StoreCore.setField(table, key, 1, secondDataBytes); - StoreCore.setField(table, key, 2, thirdDataBytes); + IStore(this).setField(table, key, 0, abi.encodePacked(firstDataBytes)); + IStore(this).setField(table, key, 1, secondDataBytes); + IStore(this).setField(table, key, 2, thirdDataBytes); // Create data to use for the update bytes memory secondDataForUpdate; @@ -719,11 +656,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { emit StoreSetField(table, key, 1, newSecondDataBytes); // Update index 1 in second field (4 = byte length of uint32) - // !gasreport update in field (1 slot, 1 uint32 item) - StoreCore.updateInField(table, key, 1, 4 * 1, secondDataForUpdate); + IStore(this).updateInField(table, key, 1, 4 * 1, secondDataForUpdate); // Get second field - bytes memory loadedData = StoreCore.getField(table, key, 1); + bytes memory loadedData = IStore(this).getField(table, key, 1); // Verify loaded data is correct assertEq(SliceLib.fromBytes(loadedData).decodeArray_uint32().length, secondData.length); @@ -731,8 +667,8 @@ contract StoreCoreTest is Test, StoreReadWithStubs { assertEq(loadedData, newSecondDataBytes); // Verify none of the other fields were impacted - assertEq(bytes32(StoreCore.getField(table, key, 0)), firstDataBytes); - assertEq(StoreCore.getField(table, key, 2), thirdDataBytes); + assertEq(bytes32(IStore(this).getField(table, key, 0)), firstDataBytes); + assertEq(IStore(this).getField(table, key, 2), thirdDataBytes); // Create data for update bytes memory thirdDataForUpdate; @@ -760,11 +696,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { emit StoreSetField(table, key, 2, newThirdDataBytes); // Update indexes 1,2,3,4 in third field (8 = byte length of uint64) - // !gasreport push to field (2 slots, 6 uint64 items) - StoreCore.updateInField(table, key, 2, 8 * 1, thirdDataForUpdate); + IStore(this).updateInField(table, key, 2, 8 * 1, thirdDataForUpdate); // Get third field - loadedData = StoreCore.getField(table, key, 2); + loadedData = IStore(this).getField(table, key, 2); // Verify loaded data is correct assertEq(SliceLib.fromBytes(loadedData).decodeArray_uint64().length, thirdData.length); @@ -772,44 +707,39 @@ contract StoreCoreTest is Test, StoreReadWithStubs { assertEq(loadedData, newThirdDataBytes); // Verify none of the other fields were impacted - assertEq(bytes32(StoreCore.getField(table, key, 0)), firstDataBytes); - assertEq(StoreCore.getField(table, key, 1), newSecondDataBytes); + assertEq(bytes32(IStore(this).getField(table, key, 0)), firstDataBytes); + assertEq(IStore(this).getField(table, key, 1), newSecondDataBytes); // startByteIndex must not overflow vm.expectRevert( abi.encodeWithSelector(IStoreErrors.StoreCore_DataIndexOverflow.selector, type(uint16).max, type(uint32).max) ); - StoreCore.updateInField(table, key, 2, type(uint32).max, thirdDataForUpdate); + IStore(this).updateInField(table, key, 2, type(uint32).max, thirdDataForUpdate); } function testAccessEmptyData() public { bytes32 table = keccak256("some.table"); Schema schema = SchemaLib.encode(SchemaType.UINT32, SchemaType.UINT32_ARRAY); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); // Create key bytes32[] memory key = new bytes32[](1); key[0] = bytes32("some.key"); - // !gasreport access non-existing record - bytes memory data1 = StoreCore.getRecord(table, key); + bytes memory data1 = IStore(this).getRecord(table, key); assertEq(data1.length, schema.staticDataLength()); - // !gasreport access static field of non-existing record - bytes memory data2 = StoreCore.getField(table, key, 0); + bytes memory data2 = IStore(this).getField(table, key, 0); assertEq(data2.length, schema.staticDataLength()); - // !gasreport access dynamic field of non-existing record - bytes memory data3 = StoreCore.getField(table, key, 1); + bytes memory data3 = IStore(this).getField(table, key, 1); assertEq(data3.length, 0); - // !gasreport access length of dynamic field of non-existing record - uint256 data3Length = StoreCore.getFieldLength(table, key, 1, schema); + uint256 data3Length = IStore(this).getFieldLength(table, key, 1, schema); assertEq(data3Length, 0); - // !gasreport access slice of dynamic field of non-existing record - bytes memory data3Slice = StoreCore.getFieldSlice(table, key, 1, schema, 0, 0); + bytes memory data3Slice = IStore(this).getFieldSlice(table, key, 1, schema, 0, 0); assertEq(data3Slice.length, 0); } @@ -820,37 +750,33 @@ contract StoreCoreTest is Test, StoreReadWithStubs { // Register table's schema Schema schema = SchemaLib.encode(SchemaType.UINT128); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); // Create subscriber MirrorSubscriber subscriber = new MirrorSubscriber(table, schema, defaultKeySchema); - // !gasreport register subscriber - StoreCore.registerStoreHook(table, subscriber); + IStore(this).registerStoreHook(table, subscriber); bytes memory data = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); - // !gasreport set record on table with subscriber - StoreCore.setRecord(table, key, data); + IStore(this).setRecord(table, key, data); // Get data from indexed table - the indexer should have mirrored the data there - bytes memory indexedData = StoreCore.getRecord(indexerTableId, key); + bytes memory indexedData = IStore(this).getRecord(indexerTableId, key); assertEq(keccak256(data), keccak256(indexedData)); data = abi.encodePacked(bytes16(0x1112131415161718191a1b1c1d1e1f20)); - // !gasreport set static field on table with subscriber - StoreCore.setField(table, key, 0, data); + IStore(this).setField(table, key, 0, data); // Get data from indexed table - the indexer should have mirrored the data there - indexedData = StoreCore.getRecord(indexerTableId, key); + indexedData = IStore(this).getRecord(indexerTableId, key); assertEq(keccak256(data), keccak256(indexedData)); - // !gasreport delete record on table with subscriber - StoreCore.deleteRecord(table, key); + IStore(this).deleteRecord(table, key); // Get data from indexed table - the indexer should have mirrored the data there - indexedData = StoreCore.getRecord(indexerTableId, key); + indexedData = IStore(this).getRecord(indexerTableId, key); assertEq(keccak256(indexedData), keccak256(abi.encodePacked(bytes16(0)))); } @@ -861,13 +787,12 @@ contract StoreCoreTest is Test, StoreReadWithStubs { // Register table's schema Schema schema = SchemaLib.encode(SchemaType.UINT128, SchemaType.UINT32_ARRAY); - StoreCore.registerSchema(table, schema, defaultKeySchema); + IStore(this).registerSchema(table, schema, defaultKeySchema); // Create subscriber MirrorSubscriber subscriber = new MirrorSubscriber(table, schema, defaultKeySchema); - // !gasreport register subscriber - StoreCore.registerStoreHook(table, subscriber); + IStore(this).registerStoreHook(table, subscriber); uint32[] memory arrayData = new uint32[](1); arrayData[0] = 0x01020304; @@ -877,11 +802,10 @@ contract StoreCoreTest is Test, StoreReadWithStubs { bytes memory staticData = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); bytes memory data = abi.encodePacked(staticData, dynamicData); - // !gasreport set (dynamic) record on table with subscriber - StoreCore.setRecord(table, key, data); + IStore(this).setRecord(table, key, data); // Get data from indexed table - the indexer should have mirrored the data there - bytes memory indexedData = StoreCore.getRecord(indexerTableId, key); + bytes memory indexedData = IStore(this).getRecord(indexerTableId, key); assertEq(keccak256(data), keccak256(indexedData)); // Update dynamic data @@ -890,18 +814,16 @@ contract StoreCoreTest is Test, StoreReadWithStubs { dynamicData = abi.encodePacked(encodedArrayDataLength.unwrap(), arrayDataBytes); data = abi.encodePacked(staticData, dynamicData); - // !gasreport set (dynamic) field on table with subscriber - StoreCore.setField(table, key, 1, arrayDataBytes); + IStore(this).setField(table, key, 1, arrayDataBytes); // Get data from indexed table - the indexer should have mirrored the data there - indexedData = StoreCore.getRecord(indexerTableId, key); + indexedData = IStore(this).getRecord(indexerTableId, key); assertEq(keccak256(data), keccak256(indexedData)); - // !gasreport delete (dynamic) record on table with subscriber - StoreCore.deleteRecord(table, key); + IStore(this).deleteRecord(table, key); // Get data from indexed table - the indexer should have mirrored the data there - indexedData = StoreCore.getRecord(indexerTableId, key); + indexedData = IStore(this).getRecord(indexerTableId, key); assertEq(keccak256(indexedData), keccak256(abi.encodePacked(bytes16(0)))); } } diff --git a/packages/store/test/StoreCoreGas.t.sol b/packages/store/test/StoreCoreGas.t.sol new file mode 100644 index 0000000000..a15a4ba262 --- /dev/null +++ b/packages/store/test/StoreCoreGas.t.sol @@ -0,0 +1,626 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import "forge-std/Test.sol"; +import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; +import { StoreCore, StoreCoreInternal } from "../src/StoreCore.sol"; +import { Utils } from "../src/Utils.sol"; +import { Bytes } from "../src/Bytes.sol"; +import { SliceLib } from "../src/Slice.sol"; +import { EncodeArray } from "../src/tightcoder/EncodeArray.sol"; +import { Schema, SchemaLib } from "../src/Schema.sol"; +import { PackedCounter, PackedCounterLib } from "../src/PackedCounter.sol"; +import { StoreReadWithStubs } from "../src/StoreReadWithStubs.sol"; +import { IStoreErrors } from "../src/IStoreErrors.sol"; +import { IStore, IStoreHook } from "../src/IStore.sol"; +import { StoreSwitch } from "../src/StoreSwitch.sol"; +import { StoreMetadataData, StoreMetadata } from "../src/codegen/Tables.sol"; +import { StoreMock } from "./StoreMock.sol"; + +struct TestStruct { + uint128 firstData; + uint32[] secondData; + uint32[] thirdData; +} + +contract StoreCoreGasTest is Test, StoreMock { + TestStruct private testStruct; + + mapping(uint256 => bytes) private testMapping; + Schema defaultKeySchema = SchemaLib.encode(SchemaType.BYTES32); + + function testRegisterAndGetSchema() public { + Schema schema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16, SchemaType.UINT8, SchemaType.UINT16); + Schema keySchema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16); + bytes32 table = keccak256("some.table"); + + // !gasreport StoreCore: register schema + StoreCore.registerSchema(table, schema, keySchema); + + // !gasreport StoreCore: get schema (warm) + StoreCore.getSchema(table); + + // !gasreport StoreCore: get key schema (warm) + StoreCore.getKeySchema(table); + } + + function testHasSchema() public { + Schema schema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16, SchemaType.UINT8, SchemaType.UINT16); + bytes32 table = keccak256("some.table"); + bytes32 table2 = keccak256("other.table"); + StoreCore.registerSchema(table, schema, defaultKeySchema); + + // !gasreport Check for existence of table (existent) + StoreCore.hasTable(table); + + // !gasreport check for existence of table (non-existent) + StoreCore.hasTable(table2); + } + + function testSetMetadata() public { + bytes32 table = keccak256("some.table"); + Schema schema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16); + Schema keySchema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16, SchemaType.UINT8, SchemaType.UINT16); + string memory tableName = "someTable"; + string[] memory fieldNames = new string[](2); + fieldNames[0] = "field1"; + fieldNames[1] = "field2"; + + // Register table + StoreCore.registerSchema(table, schema, keySchema); + + // !gasreport StoreCore: set table metadata + StoreCore.setMetadata(table, tableName, fieldNames); + } + + function testSetAndGetDynamicDataLength() public { + bytes32 table = keccak256("some.table"); + + Schema schema = SchemaLib.encode( + SchemaType.UINT8, + SchemaType.UINT16, + SchemaType.UINT32, + SchemaType.UINT32_ARRAY, + SchemaType.UINT32_ARRAY + ); + + // Register schema + StoreCore.registerSchema(table, schema, defaultKeySchema); + + // Create some key + bytes32[] memory key = new bytes32[](1); + key[0] = bytes32("some key"); + + // Set dynamic data length of dynamic index 0 + // !gasreport set dynamic length of dynamic index 0 + StoreCoreInternal._setDynamicDataLengthAtIndex(table, key, 0, 10); + + // Set dynamic data length of dynamic index 1 + // !gasreport set dynamic length of dynamic index 1 + StoreCoreInternal._setDynamicDataLengthAtIndex(table, key, 1, 99); + + // Reduce dynamic data length of dynamic index 0 again + // !gasreport reduce dynamic length of dynamic index 0 + StoreCoreInternal._setDynamicDataLengthAtIndex(table, key, 0, 5); + } + + function testSetAndGetStaticData() public { + // Register table's schema + Schema schema = SchemaLib.encode(SchemaType.UINT8, SchemaType.UINT16, SchemaType.UINT8, SchemaType.UINT16); + bytes32 table = keccak256("some.table"); + StoreCore.registerSchema(table, schema, defaultKeySchema); + + // Set data + bytes memory data = abi.encodePacked(bytes1(0x01), bytes2(0x0203), bytes1(0x04), bytes2(0x0506)); + bytes32[] memory key = new bytes32[](1); + key[0] = keccak256("some.key"); + + // !gasreport set static record (1 slot) + StoreCore.setRecord(table, key, data); + + // Get data + // !gasreport get static record (1 slot) + StoreCore.getRecord(table, key, schema); + } + + function testSetAndGetStaticDataSpanningWords() public { + // Register table's schema + Schema schema = SchemaLib.encode(SchemaType.UINT128, SchemaType.UINT256); + bytes32 table = keccak256("some.table"); + StoreCore.registerSchema(table, schema, defaultKeySchema); + + // Set data + bytes memory data = abi.encodePacked( + bytes16(0x0102030405060708090a0b0c0d0e0f10), + bytes32(0x1112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30) + ); + + bytes32[] memory key = new bytes32[](1); + key[0] = keccak256("some.key"); + + // !gasreport set static record (2 slots) + StoreCore.setRecord(table, key, data); + + // Get data + // !gasreport get static record (2 slots) + StoreCore.getRecord(table, key, schema); + } + + function testSetAndGetDynamicData() public { + bytes32 table = keccak256("some.table"); + + { + // Register table's schema + Schema schema = SchemaLib.encode(SchemaType.UINT128, SchemaType.UINT32_ARRAY, SchemaType.UINT32_ARRAY); + StoreCore.registerSchema(table, schema, defaultKeySchema); + } + + bytes16 firstDataBytes = bytes16(0x0102030405060708090a0b0c0d0e0f10); + + bytes memory secondDataBytes; + { + uint32[] memory secondData = new uint32[](2); + secondData[0] = 0x11121314; + secondData[1] = 0x15161718; + secondDataBytes = EncodeArray.encode(secondData); + } + + bytes memory thirdDataBytes; + { + uint32[] memory thirdData = new uint32[](3); + thirdData[0] = 0x191a1b1c; + thirdData[1] = 0x1d1e1f20; + thirdData[2] = 0x21222324; + thirdDataBytes = EncodeArray.encode(thirdData); + } + + PackedCounter encodedDynamicLength; + { + uint16[] memory dynamicLengths = new uint16[](2); + dynamicLengths[0] = uint16(secondDataBytes.length); + dynamicLengths[1] = uint16(thirdDataBytes.length); + encodedDynamicLength = PackedCounterLib.pack(dynamicLengths); + } + + // Concat data + bytes memory data = abi.encodePacked( + firstDataBytes, + encodedDynamicLength.unwrap(), + secondDataBytes, + thirdDataBytes + ); + + // Create key + bytes32[] memory key = new bytes32[](1); + key[0] = bytes32("some.key"); + + // Set data + // !gasreport set complex record with dynamic data (4 slots) + StoreCore.setRecord(table, key, data); + + // Get data + // !gasreport get complex record with dynamic data (4 slots) + StoreCore.getRecord(table, key); + + // Compare gas - setting the data as raw struct + TestStruct memory _testStruct = TestStruct(0, new uint32[](2), new uint32[](3)); + _testStruct.firstData = 0x0102030405060708090a0b0c0d0e0f10; + _testStruct.secondData[0] = 0x11121314; + _testStruct.secondData[1] = 0x15161718; + _testStruct.thirdData[0] = 0x191a1b1c; + _testStruct.thirdData[1] = 0x1d1e1f20; + _testStruct.thirdData[2] = 0x21222324; + + // !gasreport compare: Set complex record with dynamic data using native solidity + testStruct = _testStruct; + + // !gasreport compare: Set complex record with dynamic data using abi.encode + testMapping[1234] = abi.encode(_testStruct); + } + + function testSetAndGetField() public { + bytes32 table = keccak256("some.table"); + + { + // Register table's schema + Schema schema = SchemaLib.encode( + SchemaType.UINT128, + SchemaType.UINT256, + SchemaType.UINT32_ARRAY, + SchemaType.UINT32_ARRAY + ); + StoreCore.registerSchema(table, schema, defaultKeySchema); + } + + bytes16 firstDataBytes = bytes16(0x0102030405060708090a0b0c0d0e0f10); + + // Create key + bytes32[] memory key = new bytes32[](1); + key[0] = bytes32("some.key"); + + bytes memory firstDataPacked = abi.encodePacked(firstDataBytes); + + // Set first field + // !gasreport set static field (1 slot) + StoreCore.setField(table, key, 0, firstDataPacked); + + //////////////// + // Static data + //////////////// + + // Get first field + // !gasreport get static field (1 slot) + StoreCore.getField(table, key, 0); + + // Set second field + bytes32 secondDataBytes = keccak256("some data"); + bytes memory secondDataPacked = abi.encodePacked(secondDataBytes); + + // !gasreport set static field (overlap 2 slot) + StoreCore.setField(table, key, 1, secondDataPacked); + + // Get second field + // !gasreport get static field (overlap 2 slot) + StoreCore.getField(table, key, 1); + + //////////////// + // Dynamic data + //////////////// + + bytes memory thirdDataBytes; + { + uint32[] memory thirdData = new uint32[](2); + thirdData[0] = 0x11121314; + thirdData[1] = 0x15161718; + thirdDataBytes = EncodeArray.encode(thirdData); + } + + bytes memory fourthDataBytes; + { + uint32[] memory fourthData = new uint32[](3); + fourthData[0] = 0x191a1b1c; + fourthData[1] = 0x1d1e1f20; + fourthData[2] = 0x21222324; + fourthDataBytes = EncodeArray.encode(fourthData); + } + + // Set third field + // !gasreport set dynamic field (1 slot, first dynamic field) + StoreCore.setField(table, key, 2, thirdDataBytes); + + // Get third field + // !gasreport get dynamic field (1 slot, first dynamic field) + StoreCore.getField(table, key, 2); + + // Set fourth field + // !gasreport set dynamic field (1 slot, second dynamic field) + StoreCore.setField(table, key, 3, fourthDataBytes); + + // Get fourth field + // !gasreport get dynamic field (1 slot, second dynamic field) + StoreCore.getField(table, key, 3); + } + + function testDeleteData() public { + bytes32 table = keccak256("some.table"); + + // Register table's schema + Schema schema = SchemaLib.encode(SchemaType.UINT128, SchemaType.UINT32_ARRAY, SchemaType.UINT32_ARRAY); + StoreCore.registerSchema(table, schema, defaultKeySchema); + + bytes16 firstDataBytes = bytes16(0x0102030405060708090a0b0c0d0e0f10); + + bytes memory secondDataBytes; + { + uint32[] memory secondData = new uint32[](2); + secondData[0] = 0x11121314; + secondData[1] = 0x15161718; + secondDataBytes = EncodeArray.encode(secondData); + } + + bytes memory thirdDataBytes; + { + uint32[] memory thirdData = new uint32[](3); + thirdData[0] = 0x191a1b1c; + thirdData[1] = 0x1d1e1f20; + thirdData[2] = 0x21222324; + thirdDataBytes = EncodeArray.encode(thirdData); + } + + PackedCounter encodedDynamicLength; + { + uint16[] memory dynamicLengths = new uint16[](2); + dynamicLengths[0] = uint16(secondDataBytes.length); + dynamicLengths[1] = uint16(thirdDataBytes.length); + encodedDynamicLength = PackedCounterLib.pack(dynamicLengths); + } + + // Concat data + bytes memory data = abi.encodePacked( + firstDataBytes, + encodedDynamicLength.unwrap(), + secondDataBytes, + thirdDataBytes + ); + + // Create key + bytes32[] memory key = new bytes32[](1); + key[0] = bytes32("some.key"); + + // Set data + StoreCore.setRecord(table, key, data); + + // Delete data + // !gasreport delete record (complex data, 3 slots) + StoreCore.deleteRecord(table, key); + } + + function testPushToField() public { + bytes32 table = keccak256("some.table"); + + { + // Register table's schema + Schema schema = SchemaLib.encode(SchemaType.UINT256, SchemaType.UINT32_ARRAY, SchemaType.UINT32_ARRAY); + StoreCore.registerSchema(table, schema, defaultKeySchema); + } + + // Create key + bytes32[] memory key = new bytes32[](1); + key[0] = bytes32("some.key"); + + // Create data + bytes32 firstDataBytes = keccak256("some data"); + bytes memory secondDataBytes; + { + uint32[] memory secondData = new uint32[](2); + secondData[0] = 0x11121314; + secondData[1] = 0x15161718; + secondDataBytes = EncodeArray.encode(secondData); + } + bytes memory thirdDataBytes; + { + uint32[] memory thirdData = new uint32[](3); + thirdData[0] = 0x191a1b1c; + thirdData[1] = 0x1d1e1f20; + thirdData[2] = 0x21222324; + thirdDataBytes = EncodeArray.encode(thirdData); + } + + // Set fields + StoreCore.setField(table, key, 0, abi.encodePacked(firstDataBytes)); + StoreCore.setField(table, key, 1, secondDataBytes); + // Initialize a field with push + StoreCore.pushToField(table, key, 2, thirdDataBytes); + + // Create data to push + bytes memory secondDataToPush; + { + uint32[] memory secondData = new uint32[](1); + secondData[0] = 0x25262728; + secondDataToPush = EncodeArray.encode(secondData); + } + bytes memory newSecondDataBytes = abi.encodePacked(secondDataBytes, secondDataToPush); + + // Push to second field + // !gasreport push to field (1 slot, 1 uint32 item) + StoreCore.pushToField(table, key, 1, secondDataToPush); + + // Create data to push + bytes memory thirdDataToPush; + { + uint32[] memory thirdData = new uint32[](10); + thirdData[0] = 0x12345678; + thirdData[1] = 0x9abcdef0; + thirdData[2] = 0x12345678; + thirdData[3] = 0x9abcdef0; + thirdData[4] = 0x12345678; + thirdData[5] = 0x9abcdef0; + thirdData[6] = 0x12345678; + thirdData[7] = 0x9abcdef0; + thirdData[8] = 0x12345678; + thirdData[9] = 0x9abcdef0; + thirdDataToPush = EncodeArray.encode(thirdData); + } + + // Push to third field + // !gasreport push to field (2 slots, 10 uint32 items) + StoreCore.pushToField(table, key, 2, thirdDataToPush); + } + + function testUpdateInField() public { + bytes32 table = keccak256("some.table"); + + { + // Register table's schema + Schema schema = SchemaLib.encode(SchemaType.UINT256, SchemaType.UINT32_ARRAY, SchemaType.UINT64_ARRAY); + StoreCore.registerSchema(table, schema, defaultKeySchema); + } + + // Create key + bytes32[] memory key = new bytes32[](1); + key[0] = bytes32("some.key"); + + // Create data + bytes32 firstDataBytes = keccak256("some data"); + uint32[] memory secondData = new uint32[](2); + secondData[0] = 0x11121314; + secondData[1] = 0x15161718; + bytes memory secondDataBytes = EncodeArray.encode(secondData); + + uint64[] memory thirdData = new uint64[](6); + thirdData[0] = 0x1111111111111111; + thirdData[1] = 0x2222222222222222; + thirdData[2] = 0x3333333333333333; + thirdData[3] = 0x4444444444444444; + thirdData[4] = 0x5555555555555555; + thirdData[5] = 0x6666666666666666; + bytes memory thirdDataBytes = EncodeArray.encode(thirdData); + + // Set fields + StoreCore.setField(table, key, 0, abi.encodePacked(firstDataBytes)); + StoreCore.setField(table, key, 1, secondDataBytes); + StoreCore.setField(table, key, 2, thirdDataBytes); + + // Create data to use for the update + bytes memory secondDataForUpdate; + bytes memory newSecondDataBytes; + { + uint32[] memory _secondDataForUpdate = new uint32[](1); + _secondDataForUpdate[0] = 0x25262728; + secondDataForUpdate = EncodeArray.encode(_secondDataForUpdate); + + newSecondDataBytes = abi.encodePacked(secondData[0], _secondDataForUpdate[0]); + } + + // Update index 1 in second field (4 = byte length of uint32) + // !gasreport update in field (1 slot, 1 uint32 item) + StoreCore.updateInField(table, key, 1, 4 * 1, secondDataForUpdate); + + // Create data for update + bytes memory thirdDataForUpdate; + bytes memory newThirdDataBytes; + { + uint64[] memory _thirdDataForUpdate = new uint64[](4); + _thirdDataForUpdate[0] = 0x7777777777777777; + _thirdDataForUpdate[1] = 0x8888888888888888; + _thirdDataForUpdate[2] = 0x9999999999999999; + _thirdDataForUpdate[3] = 0x0; + thirdDataForUpdate = EncodeArray.encode(_thirdDataForUpdate); + + newThirdDataBytes = abi.encodePacked( + thirdData[0], + _thirdDataForUpdate[0], + _thirdDataForUpdate[1], + _thirdDataForUpdate[2], + _thirdDataForUpdate[3], + thirdData[5] + ); + } + + // Update indexes 1,2,3,4 in third field (8 = byte length of uint64) + // !gasreport push to field (2 slots, 6 uint64 items) + StoreCore.updateInField(table, key, 2, 8 * 1, thirdDataForUpdate); + } + + function testAccessEmptyData() public { + bytes32 table = keccak256("some.table"); + Schema schema = SchemaLib.encode(SchemaType.UINT32, SchemaType.UINT32_ARRAY); + + StoreCore.registerSchema(table, schema, defaultKeySchema); + + // Create key + bytes32[] memory key = new bytes32[](1); + key[0] = bytes32("some.key"); + + // !gasreport access non-existing record + StoreCore.getRecord(table, key); + + // !gasreport access static field of non-existing record + StoreCore.getField(table, key, 0); + + // !gasreport access dynamic field of non-existing record + StoreCore.getField(table, key, 1); + + // !gasreport access length of dynamic field of non-existing record + StoreCore.getFieldLength(table, key, 1, schema); + + // !gasreport access slice of dynamic field of non-existing record + StoreCore.getFieldSlice(table, key, 1, schema, 0, 0); + } + + function testHooks() public { + bytes32 table = keccak256("some.table"); + bytes32[] memory key = new bytes32[](1); + key[0] = keccak256("some key"); + + // Register table's schema + Schema schema = SchemaLib.encode(SchemaType.UINT128); + StoreCore.registerSchema(table, schema, defaultKeySchema); + + // Create subscriber + MirrorSubscriber subscriber = new MirrorSubscriber(table, schema, defaultKeySchema); + + // !gasreport register subscriber + StoreCore.registerStoreHook(table, subscriber); + + bytes memory data = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); + + // !gasreport set record on table with subscriber + StoreCore.setRecord(table, key, data); + + data = abi.encodePacked(bytes16(0x1112131415161718191a1b1c1d1e1f20)); + + // !gasreport set static field on table with subscriber + StoreCore.setField(table, key, 0, data); + + // !gasreport delete record on table with subscriber + StoreCore.deleteRecord(table, key); + } + + function testHooksDynamicData() public { + bytes32 table = keccak256("some.table"); + bytes32[] memory key = new bytes32[](1); + key[0] = keccak256("some key"); + + // Register table's schema + Schema schema = SchemaLib.encode(SchemaType.UINT128, SchemaType.UINT32_ARRAY); + StoreCore.registerSchema(table, schema, defaultKeySchema); + + // Create subscriber + MirrorSubscriber subscriber = new MirrorSubscriber(table, schema, defaultKeySchema); + + // !gasreport register subscriber + StoreCore.registerStoreHook(table, subscriber); + + uint32[] memory arrayData = new uint32[](1); + arrayData[0] = 0x01020304; + bytes memory arrayDataBytes = EncodeArray.encode(arrayData); + PackedCounter encodedArrayDataLength = PackedCounterLib.pack(uint16(arrayDataBytes.length)); + bytes memory dynamicData = abi.encodePacked(encodedArrayDataLength.unwrap(), arrayDataBytes); + bytes memory staticData = abi.encodePacked(bytes16(0x0102030405060708090a0b0c0d0e0f10)); + bytes memory data = abi.encodePacked(staticData, dynamicData); + + // !gasreport set (dynamic) record on table with subscriber + StoreCore.setRecord(table, key, data); + + // Update dynamic data + arrayData[0] = 0x11121314; + arrayDataBytes = EncodeArray.encode(arrayData); + dynamicData = abi.encodePacked(encodedArrayDataLength.unwrap(), arrayDataBytes); + data = abi.encodePacked(staticData, dynamicData); + + // !gasreport set (dynamic) field on table with subscriber + StoreCore.setField(table, key, 1, arrayDataBytes); + + // !gasreport delete (dynamic) record on table with subscriber + StoreCore.deleteRecord(table, key); + } +} + +bytes32 constant indexerTableId = keccak256("indexer.table"); + +contract MirrorSubscriber is IStoreHook { + bytes32 _table; + + constructor(bytes32 table, Schema schema, Schema keySchema) { + IStore(msg.sender).registerSchema(indexerTableId, schema, keySchema); + _table = table; + } + + function onSetRecord(bytes32 table, bytes32[] memory key, bytes memory data) public { + if (table != table) revert("invalid table"); + StoreSwitch.setRecord(indexerTableId, key, data); + } + + function onBeforeSetField(bytes32 table, bytes32[] memory key, uint8 schemaIndex, bytes memory data) public { + if (table != table) revert("invalid table"); + StoreSwitch.setField(indexerTableId, key, schemaIndex, data); + } + + function onAfterSetField(bytes32, bytes32[] memory, uint8, bytes memory) public {} + + function onDeleteRecord(bytes32 table, bytes32[] memory key) public { + if (table != table) revert("invalid table"); + StoreSwitch.deleteRecord(indexerTableId, key); + } +} diff --git a/packages/store/test/StoreMock.sol b/packages/store/test/StoreMock.sol new file mode 100644 index 0000000000..f95f0b6c6e --- /dev/null +++ b/packages/store/test/StoreMock.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import { IStore, IStoreHook } from "../src/IStore.sol"; +import { StoreCore } from "../src/StoreCore.sol"; +import { Schema } from "../src/Schema.sol"; +import { StoreRead } from "../src/StoreRead.sol"; + +/** + * StoreMock is a contract wrapper around the StoreCore library for testing purposes. + */ +contract StoreMock is IStore, StoreRead { + // Set full record (including full dynamic data) + function setRecord(bytes32 table, bytes32[] calldata key, bytes calldata data) public { + StoreCore.setRecord(table, key, data); + } + + // Set partial data at schema index + function setField(bytes32 table, bytes32[] calldata key, uint8 schemaIndex, bytes calldata data) public { + StoreCore.setField(table, key, schemaIndex, data); + } + + // Push encoded items to the dynamic field at schema index + function pushToField(bytes32 table, bytes32[] calldata key, uint8 schemaIndex, bytes calldata dataToPush) public { + StoreCore.pushToField(table, key, schemaIndex, dataToPush); + } + + // Pop byte length from the dynamic field at schema index + function popFromField(bytes32 table, bytes32[] calldata key, uint8 schemaIndex, uint256 byteLengthToPop) public { + StoreCore.popFromField(table, key, schemaIndex, byteLengthToPop); + } + + // Change encoded items within the dynamic field at schema index + function updateInField( + bytes32 table, + bytes32[] calldata key, + uint8 schemaIndex, + uint256 startByteIndex, + bytes calldata dataToSet + ) public { + StoreCore.updateInField(table, key, schemaIndex, startByteIndex, dataToSet); + } + + // Set full record (including full dynamic data) + function deleteRecord(bytes32 table, bytes32[] memory key) public { + StoreCore.deleteRecord(table, key); + } + + // Emit the ephemeral event without modifying storage + function emitEphemeralRecord(bytes32 table, bytes32[] calldata key, bytes calldata data) public { + StoreCore.emitEphemeralRecord(table, key, data); + } + + function registerSchema(bytes32 table, Schema schema, Schema keySchema) public { + StoreCore.registerSchema(table, schema, keySchema); + } + + function setMetadata(bytes32 table, string calldata tableName, string[] calldata fieldNames) public { + StoreCore.setMetadata(table, tableName, fieldNames); + } + + // Register hook to be called when a record or field is set or deleted + function registerStoreHook(bytes32 table, IStoreHook hook) public { + StoreCore.registerStoreHook(table, hook); + } +}