Skip to content

Commit

Permalink
feat(store,world): emit Store/World versions (#1511)
Browse files Browse the repository at this point in the history
Co-authored-by: alvrs <[email protected]>
  • Loading branch information
holic and alvrs authored Sep 16, 2023
1 parent 2b585af commit 9b43029
Show file tree
Hide file tree
Showing 14 changed files with 105 additions and 35 deletions.
16 changes: 16 additions & 0 deletions .changeset/soft-fans-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"@latticexyz/store": minor
"@latticexyz/world": minor
---

Add protocol version with corresponding getter and event on deploy

```solidity
world.worldVersion();
world.storeVersion(); // a World is also a Store
```

```solidity
event HelloWorld(bytes32 indexed worldVersion);
event HelloStore(bytes32 indexed storeVersion);
```
4 changes: 2 additions & 2 deletions packages/store/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testHooks",
"name": "delete record on table with subscriber",
"gasUsed": 16415
"gasUsed": 16438
},
{
"file": "test/StoreCoreGas.t.sol",
Expand All @@ -723,7 +723,7 @@
"file": "test/StoreCoreGas.t.sol",
"test": "testHooksDynamicData",
"name": "delete (dynamic) record on table with subscriber",
"gasUsed": 17400
"gasUsed": 17423
},
{
"file": "test/StoreCoreGas.t.sol",
Expand Down
4 changes: 4 additions & 0 deletions packages/store/src/IStore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import { Schema } from "./Schema.sol";
import { IStoreHook } from "./IStoreHook.sol";

interface IStoreRead {
event HelloStore(bytes32 indexed storeVersion);

function storeVersion() external view returns (bytes32);

function getFieldLayout(bytes32 tableId) external view returns (FieldLayout fieldLayout);

function getValueSchema(bytes32 tableId) external view returns (Schema valueSchema);
Expand Down
5 changes: 4 additions & 1 deletion packages/store/src/StoreCore.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import { STORE_VERSION } from "./version.sol";
import { Bytes } from "./Bytes.sol";
import { Storage } from "./Storage.sol";
import { Memory } from "./Memory.sol";
Expand All @@ -16,7 +17,7 @@ import { Hook, HookLib } from "./Hook.sol";
import { StoreHookLib, StoreHookType } from "./StoreHook.sol";

library StoreCore {
// note: the preimage of the tuple of keys used to index is part of the event, so it can be used by indexers
event HelloStore(bytes32 indexed version);
event StoreSetRecord(
bytes32 indexed tableId,
bytes32[] keyTuple,
Expand Down Expand Up @@ -53,6 +54,8 @@ library StoreCore {
* Consumers must call this function in their constructor.
*/
function initialize() internal {
emit HelloStore(STORE_VERSION);

// StoreSwitch uses the storeAddress to decide where to write data to.
// If StoreSwitch is called in the context of a Store contract (storeAddress == address(this)),
// StoreSwitch uses internal methods to write data instead of external calls.
Expand Down
5 changes: 5 additions & 0 deletions packages/store/src/StoreRead.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import { STORE_VERSION } from "./version.sol";
import { IStoreRead } from "./IStore.sol";
import { StoreCore } from "./StoreCore.sol";
import { FieldLayout } from "./FieldLayout.sol";
import { Schema } from "./Schema.sol";

contract StoreRead is IStoreRead {
function storeVersion() public pure returns (bytes32) {
return STORE_VERSION;
}

function getFieldLayout(bytes32 tableId) public view virtual returns (FieldLayout fieldLayout) {
fieldLayout = StoreCore.getFieldLayout(tableId);
}
Expand Down
4 changes: 4 additions & 0 deletions packages/store/src/version.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

bytes32 constant STORE_VERSION = "0.0.0";
19 changes: 19 additions & 0 deletions packages/store/test/StoreMock.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import { Test } from "forge-std/Test.sol";
import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol";
import { STORE_VERSION } from "../src/version.sol";
import { StoreCore } from "../src/StoreCore.sol";
import { StoreMock } from "../test/StoreMock.sol";
import { StoreSwitch } from "../src/StoreSwitch.sol";

contract StoreMockTest is Test {
event HelloStore(bytes32 indexed storeVersion);

function testStoreMockConstrctor() public {
vm.expectEmit(true, true, true, true);
emit HelloStore(STORE_VERSION);
new StoreMock();
}
}
5 changes: 4 additions & 1 deletion packages/store/ts/storeEventsAbi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import { AbiEvent } from "abitype";

describe("storeEventsAbi", () => {
it("should match the store ABI", () => {
const expectedEvents = IStoreAbi.filter((item) => item.type === "event") as readonly AbiEvent[];
const expectedEvents = IStoreAbi.filter((item) => item.type === "event").filter(
(item) => item.name !== "HelloStore"
) as readonly AbiEvent[];

const expectedAbi = expectedEvents
.map((item) => ({
// return data in a shape that matches abitype's parseAbi
Expand Down
48 changes: 24 additions & 24 deletions packages/world/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,67 +39,67 @@
"file": "test/KeysInTableModule.t.sol",
"test": "testInstallComposite",
"name": "install keys in table module",
"gasUsed": 1415306
"gasUsed": 1415308
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testInstallGas",
"name": "install keys in table module",
"gasUsed": 1415306
"gasUsed": 1415308
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testInstallGas",
"name": "set a record on a table with keysInTableModule installed",
"gasUsed": 158959
"gasUsed": 158915
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testInstallSingleton",
"name": "install keys in table module",
"gasUsed": 1415306
"gasUsed": 1415308
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testSetAndDeleteRecordHookCompositeGas",
"name": "install keys in table module",
"gasUsed": 1415306
"gasUsed": 1415308
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testSetAndDeleteRecordHookCompositeGas",
"name": "change a composite record on a table with keysInTableModule installed",
"gasUsed": 22016
"gasUsed": 21994
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testSetAndDeleteRecordHookCompositeGas",
"name": "delete a composite record on a table with keysInTableModule installed",
"gasUsed": 171520
"gasUsed": 171498
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testSetAndDeleteRecordHookGas",
"name": "install keys in table module",
"gasUsed": 1415306
"gasUsed": 1415308
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testSetAndDeleteRecordHookGas",
"name": "change a record on a table with keysInTableModule installed",
"gasUsed": 20738
"gasUsed": 20716
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testSetAndDeleteRecordHookGas",
"name": "delete a record on a table with keysInTableModule installed",
"gasUsed": 88171
"gasUsed": 88149
},
{
"file": "test/KeysWithValueModule.t.sol",
"test": "testGetKeysWithValueGas",
"name": "install keys with value module",
"gasUsed": 654597
"gasUsed": 654598
},
{
"file": "test/KeysWithValueModule.t.sol",
Expand All @@ -117,49 +117,49 @@
"file": "test/KeysWithValueModule.t.sol",
"test": "testInstall",
"name": "install keys with value module",
"gasUsed": 654597
"gasUsed": 654598
},
{
"file": "test/KeysWithValueModule.t.sol",
"test": "testInstall",
"name": "set a record on a table with KeysWithValueModule installed",
"gasUsed": 134495
"gasUsed": 134451
},
{
"file": "test/KeysWithValueModule.t.sol",
"test": "testSetAndDeleteRecordHook",
"name": "install keys with value module",
"gasUsed": 654597
"gasUsed": 654598
},
{
"file": "test/KeysWithValueModule.t.sol",
"test": "testSetAndDeleteRecordHook",
"name": "change a record on a table with KeysWithValueModule installed",
"gasUsed": 104070
"gasUsed": 104026
},
{
"file": "test/KeysWithValueModule.t.sol",
"test": "testSetAndDeleteRecordHook",
"name": "delete a record on a table with KeysWithValueModule installed",
"gasUsed": 32927
"gasUsed": 32905
},
{
"file": "test/KeysWithValueModule.t.sol",
"test": "testSetField",
"name": "install keys with value module",
"gasUsed": 654597
"gasUsed": 654598
},
{
"file": "test/KeysWithValueModule.t.sol",
"test": "testSetField",
"name": "set a field on a table with KeysWithValueModule installed",
"gasUsed": 139109
"gasUsed": 139065
},
{
"file": "test/KeysWithValueModule.t.sol",
"test": "testSetField",
"name": "change a field on a table with KeysWithValueModule installed",
"gasUsed": 103868
"gasUsed": 103824
},
{
"file": "test/query.t.sol",
Expand Down Expand Up @@ -255,7 +255,7 @@
"file": "test/UniqueEntityModule.t.sol",
"test": "testInstall",
"name": "install unique entity module",
"gasUsed": 678986
"gasUsed": 678987
},
{
"file": "test/UniqueEntityModule.t.sol",
Expand All @@ -267,7 +267,7 @@
"file": "test/UniqueEntityModule.t.sol",
"test": "testInstallRoot",
"name": "installRoot unique entity module",
"gasUsed": 669045
"gasUsed": 669046
},
{
"file": "test/UniqueEntityModule.t.sol",
Expand All @@ -279,7 +279,7 @@
"file": "test/World.t.sol",
"test": "testCall",
"name": "call a system via the World",
"gasUsed": 12288
"gasUsed": 12333
},
{
"file": "test/World.t.sol",
Expand Down Expand Up @@ -309,7 +309,7 @@
"file": "test/World.t.sol",
"test": "testRegisterFallbackSystem",
"name": "Register a fallback system",
"gasUsed": 58887
"gasUsed": 58888
},
{
"file": "test/World.t.sol",
Expand All @@ -321,7 +321,7 @@
"file": "test/World.t.sol",
"test": "testRegisterFunctionSelector",
"name": "Register a function selector",
"gasUsed": 79481
"gasUsed": 79482
},
{
"file": "test/World.t.sol",
Expand Down
7 changes: 6 additions & 1 deletion packages/world/src/World.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Schema } from "@latticexyz/store/src/Schema.sol";
import { PackedCounter } from "@latticexyz/store/src/PackedCounter.sol";
import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol";

import { WORLD_VERSION } from "./version.sol";
import { System } from "./System.sol";
import { ResourceSelector } from "./ResourceSelector.sol";
import { ROOT_NAMESPACE, ROOT_NAME } from "./constants.sol";
Expand Down Expand Up @@ -38,10 +39,14 @@ contract World is StoreRead, IStoreData, IWorldKernel {
using ResourceSelector for bytes32;
address public immutable creator;

function worldVersion() public pure returns (bytes32) {
return WORLD_VERSION;
}

constructor() {
creator = msg.sender;
StoreCore.initialize();
emit HelloWorld();
emit HelloWorld(WORLD_VERSION);
}

/**
Expand Down
7 changes: 6 additions & 1 deletion packages/world/src/interfaces/IWorldKernel.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ interface IWorldCall {
* registered functions selectors from the `CoreModule`.
*/
interface IWorldKernel is IWorldModuleInstallation, IWorldCall, IWorldErrors {
event HelloWorld();
event HelloWorld(bytes32 indexed worldVersion);

/**
* The version of the World.
*/
function worldVersion() external view returns (bytes32);

/**
* The immutable original deployer of the World.
Expand Down
4 changes: 4 additions & 0 deletions packages/world/src/version.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

bytes32 constant WORLD_VERSION = "0.0.0";
7 changes: 4 additions & 3 deletions packages/world/test/Factories.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity >=0.8.0;
import { Test, console } from "forge-std/Test.sol";

import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol";
import { WORLD_VERSION } from "../src/version.sol";
import { World } from "../src/World.sol";
import { CoreModule } from "../src/modules/core/CoreModule.sol";
import { Create2Factory } from "../src/factories/Create2Factory.sol";
Expand All @@ -16,7 +17,7 @@ import { ROOT_NAMESPACE } from "../src/constants.sol";
contract FactoriesTest is Test {
event ContractDeployed(address addr, uint256 salt);
event WorldDeployed(address indexed newContract);
event HelloWorld();
event HelloWorld(bytes32 indexed version);

function calculateAddress(
address deployingAddress,
Expand Down Expand Up @@ -58,8 +59,8 @@ contract FactoriesTest is Test {
address calculatedAddress = calculateAddress(worldFactoryAddress, bytes32(0), type(World).creationCode);

// Check for HelloWorld event from World
vm.expectEmit(true, false, false, false);
emit HelloWorld();
vm.expectEmit(true, true, true, true);
emit HelloWorld(WORLD_VERSION);

// Check for WorldDeployed event from Factory
vm.expectEmit(true, false, false, false);
Expand Down
Loading

0 comments on commit 9b43029

Please sign in to comment.