Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(store,world): replace isStore with storeAddress #1061

Merged
merged 27 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
28fdf8d
refactor(store): replace isStore with storeAddress
dk1a Jun 20, 2023
4cf590b
refactor(world): replace isStore with storeAddress
dk1a Jun 20, 2023
9a57fdc
rename WorldContext to WorldConsumer
dk1a Jun 20, 2023
64ec40f
gas-report
dk1a Jun 20, 2023
3995181
ignore storeAddress in deploy
dk1a Jun 20, 2023
caffe53
add storeAddress to MudV2Test
dk1a Jun 20, 2023
cfa0a60
fix StoreSwitch
dk1a Jun 21, 2023
37bb3d7
rebuild and simplify examples
dk1a Jun 21, 2023
f8b06ba
rebuild e2e
dk1a Jun 21, 2023
f47079d
refactor MudV2Test to avoid circular dependencies
dk1a Jun 21, 2023
be3c3ac
update templates
dk1a Jun 21, 2023
6e5be56
move comment about systems from StoreConsumer to WorldConsumer
dk1a Jun 27, 2023
b752ca1
use storeAddress in KeysWithValueHook for consistency
dk1a Jun 29, 2023
37789af
Merge branch 'main' into dk1a/refactor-is-store
dk1a Jul 13, 2023
c304eb7
some gas optimizations
dk1a Jul 14, 2023
9db1e34
more optimizations
dk1a Jul 17, 2023
c59d0ec
refactor StoreSwitch to use storage for storeAddress, exclude MudTest…
dk1a Jul 17, 2023
ac6c2d8
rebuild
dk1a Jul 17, 2023
58e5e98
cleanup
dk1a Jul 17, 2023
072d164
rebuild
dk1a Jul 17, 2023
5001ca5
Update packages/store/src/StoreSwitch.sol
dk1a Jul 17, 2023
4cf107c
Update packages/store/src/StoreCore.sol
dk1a Jul 17, 2023
65ddf91
Create selfish-cycles-retire.md
dk1a Jul 17, 2023
80706ac
prettier
dk1a Jul 17, 2023
12659f4
Update .changeset/selfish-cycles-retire.md
dk1a Jul 18, 2023
b6068a1
Update .changeset/selfish-cycles-retire.md
dk1a Jul 18, 2023
fe49822
Merge branch 'main' into dk1a/refactor-is-store
alvrs Jul 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .changeset/selfish-cycles-retire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
"@latticexyz/std-contracts": minor
"@latticexyz/store": minor
"@latticexyz/world": minor
---

Rename `MudV2Test` to `MudTest` and move from `@latticexyz/std-contracts` to `@latticexyz/store`.

```solidity
// old import
import { MudV2Test } from "@latticexyz/std-contracts/src/test/MudV2Test.t.sol";
// new import
import { MudTest } from "@latticexyz/store/src/MudTest.sol";
```

Refactor `StoreSwitch` to use a storage slot instead of `function isStore()` to determine which contract is Store:

- Previously `StoreSwitch` called `isStore()` on `msg.sender` to determine if `msg.sender` is a `Store` contract. If the call succeeded, the `Store` methods were called on `msg.sender`, otherwise the data was written to the own storage.
- With this change `StoreSwitch` instead checks for an `address` in a known storage slot. If the address equals the own address, data is written to the own storage. If it is an external address, `Store` methods are called on this address. If it is unset (`address(0)`), store methods are called on `msg.sender`.
- In practice this has the same effect as before: By default the `World` contracts sets its own address in `StoreSwitch`, while `System` contracts keep the Store address undefined, so `Systems` write to their caller (`World`) if they are executed via `call` or directly to the `World` storage if they are executed via `delegatecall`.
- Besides gas savings, this change has two additional benefits:
1. it is now possible for `Systems` to explicitly set a `Store` address to make them exclusive to that `Store` and
2. table libraries can now be used in tests without having to provide an explicit `Store` argument, because the `MudTest` base contract redirects reads and writes to the internal `World` contract.
8 changes: 4 additions & 4 deletions docs/pages/world/world-101.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,11 @@ Create a new file named `MySystemTest.t.sol` in the `test` folder.
pragma solidity >=0.8.0;

import "forge-std/Test.sol";
import { MudV2Test } from "@latticexyz/std-contracts/src/test/MudV2Test.t.sol";
import { MudTest } from "@latticexyz/store/src/MudTest.sol";
import { IWorld } from "../src/codegen/world/IWorld.sol";
import { Dog } from "../src/codegen/Tables.sol";

contract MySystemTest is MudV2Test {
contract MySystemTest is MudTest {
IWorld world;

function setUp() public override {
Expand All @@ -273,8 +273,8 @@ contract MySystemTest is MudV2Test {
// this will call the addEntry function on MySystem
bytes32 key = world.addEntry("bob", "blue");
// Expect the value retrieved from the Dog at the corresponding key to match "bob" and "blue"
string memory name = Dog.getName(world, key);
string memory color = Dog.getColor(world, key);
string memory name = Dog.getName(key);
string memory color = Dog.getColor(key);
assertEq(name, "bob");
assertEq(color, "blue");
}
Expand Down
1 change: 0 additions & 1 deletion e2e/packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"@latticexyz/cli": "link:../../../packages/cli",
"@latticexyz/config": "link:../../../packages/config",
"@latticexyz/schema-type": "link:../../../packages/schema-type",
"@latticexyz/std-contracts": "link:../../../packages/std-contracts",
"@latticexyz/store": "link:../../../packages/store",
"@latticexyz/world": "link:../../../packages/world",
"@typechain/ethers-v5": "^10.2.0",
Expand Down
4 changes: 2 additions & 2 deletions e2e/packages/contracts/test/Worldgen.t.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import { MudV2Test } from "@latticexyz/std-contracts/src/test/MudV2Test.t.sol";
import { MudTest } from "@latticexyz/store/src/MudTest.sol";

import { ICustomErrorsSystem } from "../src/codegen/world/ICustomErrorsSystem.sol";
import { Position } from "../src/CustomTypes.sol";

contract WorldgenTest is MudV2Test {
contract WorldgenTest is MudTest {
function testError1WasGenerated() public {
vm.expectRevert();
revert ICustomErrorsSystem.TestError1();
Expand Down
14 changes: 0 additions & 14 deletions e2e/packages/contracts/types/ethers-contracts/IWorld.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export interface IWorldInterface extends utils.Interface {
"grantAccess(bytes16,bytes16,address)": FunctionFragment;
"installModule(address,bytes)": FunctionFragment;
"installRootModule(address,bytes)": FunctionFragment;
"isStore()": FunctionFragment;
"pop()": FunctionFragment;
"popFromField(bytes16,bytes16,bytes32[],uint8,uint256)": FunctionFragment;
"popFromField(bytes32,bytes32[],uint8,uint256)": FunctionFragment;
Expand Down Expand Up @@ -93,7 +92,6 @@ export interface IWorldInterface extends utils.Interface {
| "grantAccess"
| "installModule"
| "installRootModule"
| "isStore"
| "pop"
| "popFromField(bytes16,bytes16,bytes32[],uint8,uint256)"
| "popFromField(bytes32,bytes32[],uint8,uint256)"
Expand Down Expand Up @@ -225,7 +223,6 @@ export interface IWorldInterface extends utils.Interface {
functionFragment: "installRootModule",
values: [PromiseOrValue<string>, PromiseOrValue<BytesLike>]
): string;
encodeFunctionData(functionFragment: "isStore", values?: undefined): string;
encodeFunctionData(functionFragment: "pop", values?: undefined): string;
encodeFunctionData(
functionFragment: "popFromField(bytes16,bytes16,bytes32[],uint8,uint256)",
Expand Down Expand Up @@ -491,7 +488,6 @@ export interface IWorldInterface extends utils.Interface {
functionFragment: "installRootModule",
data: BytesLike
): Result;
decodeFunctionResult(functionFragment: "isStore", data: BytesLike): Result;
decodeFunctionResult(functionFragment: "pop", data: BytesLike): Result;
decodeFunctionResult(
functionFragment: "popFromField(bytes16,bytes16,bytes32[],uint8,uint256)",
Expand Down Expand Up @@ -789,8 +785,6 @@ export interface IWorld extends BaseContract {
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;

isStore(overrides?: CallOverrides): Promise<[void]>;

pop(
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;
Expand Down Expand Up @@ -1097,8 +1091,6 @@ export interface IWorld extends BaseContract {
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;

isStore(overrides?: CallOverrides): Promise<void>;

pop(
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;
Expand Down Expand Up @@ -1405,8 +1397,6 @@ export interface IWorld extends BaseContract {
overrides?: CallOverrides
): Promise<void>;

isStore(overrides?: CallOverrides): Promise<void>;

pop(overrides?: CallOverrides): Promise<void>;

"popFromField(bytes16,bytes16,bytes32[],uint8,uint256)"(
Expand Down Expand Up @@ -1758,8 +1748,6 @@ export interface IWorld extends BaseContract {
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<BigNumber>;

isStore(overrides?: CallOverrides): Promise<BigNumber>;

pop(
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<BigNumber>;
Expand Down Expand Up @@ -2067,8 +2055,6 @@ export interface IWorld extends BaseContract {
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<PopulatedTransaction>;

isStore(overrides?: CallOverrides): Promise<PopulatedTransaction>;

pop(
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<PopulatedTransaction>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -717,13 +717,6 @@ const _abi = [
stateMutability: "nonpayable",
type: "function",
},
{
inputs: [],
name: "isStore",
outputs: [],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "pop",
Expand Down
3 changes: 0 additions & 3 deletions e2e/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion examples/minimal/packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"@latticexyz/config": "link:../../../../packages/config",
"@latticexyz/schema-type": "link:../../../../packages/schema-type",
"@latticexyz/solecs": "link:../../../../packages/solecs",
"@latticexyz/std-contracts": "link:../../../../packages/std-contracts",
"@latticexyz/store": "link:../../../../packages/store",
"@latticexyz/world": "link:../../../../packages/world",
"@solidstate/contracts": "^0.0.52",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
pragma solidity >=0.8.0;

import "forge-std/Test.sol";
import { MudV2Test } from "@latticexyz/std-contracts/src/test/MudV2Test.t.sol";
import { MudTest } from "@latticexyz/store/src/MudTest.sol";
import { getKeysWithValue } from "@latticexyz/world/src/modules/keyswithvalue/getKeysWithValue.sol";
import { StoreCore } from "@latticexyz/store/src/StoreCore.sol";

import { IWorld } from "../src/codegen/world/IWorld.sol";
import { MessageTable, MessageTableTableId } from "../src/codegen/Tables.sol";
import { IChatNamespacedSystem } from "../src/interfaces/IChatNamespacedSystem.sol";

contract ChatNamespacedTest is MudV2Test {
contract ChatNamespacedTest is MudTest {
function testEmitEphemeral() public {
bytes32[] memory keyTuple;
vm.expectEmit(true, true, true, true);
Expand Down
12 changes: 6 additions & 6 deletions examples/minimal/packages/contracts/test/CounterTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
pragma solidity >=0.8.0;

import "forge-std/Test.sol";
import { MudV2Test } from "@latticexyz/std-contracts/src/test/MudV2Test.t.sol";
import { MudTest } from "@latticexyz/store/src/MudTest.sol";
import { getKeysWithValue } from "@latticexyz/world/src/modules/keyswithvalue/getKeysWithValue.sol";

import { IWorld } from "../src/codegen/world/IWorld.sol";
import { CounterTable, CounterTableTableId } from "../src/codegen/Tables.sol";

import { SingletonKey } from "../src/systems/IncrementSystem.sol";

contract CounterTest is MudV2Test {
contract CounterTest is MudTest {
IWorld world;

function setUp() public override {
Expand All @@ -30,19 +30,19 @@ contract CounterTest is MudV2Test {
function testCounter() public {
// Expect the counter to be 1 because it was incremented in the PostDeploy script.
bytes32 key = SingletonKey;
uint32 counter = CounterTable.get(world, key);
uint32 counter = CounterTable.get(key);
assertEq(counter, 1);

// Expect the counter to be 2 after calling increment.
world.increment();
counter = CounterTable.get(world, key);
counter = CounterTable.get(key);
assertEq(counter, 2);
}

function testKeysWithValue() public {
bytes32 key = SingletonKey;
uint32 counter = CounterTable.get(world, key);
bytes32[] memory keysWithValue = getKeysWithValue(world, CounterTableTableId, CounterTable.encode(counter));
uint32 counter = CounterTable.get(key);
bytes32[] memory keysWithValue = getKeysWithValue(CounterTableTableId, CounterTable.encode(counter));
assertEq(keysWithValue.length, 1);
}
}
4 changes: 2 additions & 2 deletions examples/minimal/packages/contracts/test/StructTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
pragma solidity >=0.8.0;

import "forge-std/Test.sol";
import { MudV2Test } from "@latticexyz/std-contracts/src/test/MudV2Test.t.sol";
import { MudTest } from "@latticexyz/store/src/MudTest.sol";
import { getKeysWithValue } from "@latticexyz/world/src/modules/keyswithvalue/getKeysWithValue.sol";

import { IWorld } from "../src/codegen/world/IWorld.sol";
import { CounterTable, CounterTableTableId } from "../src/codegen/Tables.sol";
import { BytesStruct, StringStruct } from "../src/systems/structs.sol";

contract StructTest is MudV2Test {
contract StructTest is MudTest {
IWorld world;

function setUp() public override {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export interface IWorldInterface extends utils.Interface {
"increment()": FunctionFragment;
"installModule(address,bytes)": FunctionFragment;
"installRootModule(address,bytes)": FunctionFragment;
"isStore()": FunctionFragment;
"pickUp(uint32,uint32)": FunctionFragment;
"popFromField(bytes16,bytes16,bytes32[],uint8,uint256)": FunctionFragment;
"popFromField(bytes32,bytes32[],uint8,uint256)": FunctionFragment;
Expand Down Expand Up @@ -107,7 +106,6 @@ export interface IWorldInterface extends utils.Interface {
| "increment"
| "installModule"
| "installRootModule"
| "isStore"
| "pickUp"
| "popFromField(bytes16,bytes16,bytes32[],uint8,uint256)"
| "popFromField(bytes32,bytes32[],uint8,uint256)"
Expand Down Expand Up @@ -248,7 +246,6 @@ export interface IWorldInterface extends utils.Interface {
functionFragment: "installRootModule",
values: [PromiseOrValue<string>, PromiseOrValue<BytesLike>]
): string;
encodeFunctionData(functionFragment: "isStore", values?: undefined): string;
encodeFunctionData(
functionFragment: "pickUp",
values: [PromiseOrValue<BigNumberish>, PromiseOrValue<BigNumberish>]
Expand Down Expand Up @@ -526,7 +523,6 @@ export interface IWorldInterface extends utils.Interface {
functionFragment: "installRootModule",
data: BytesLike
): Result;
decodeFunctionResult(functionFragment: "isStore", data: BytesLike): Result;
decodeFunctionResult(functionFragment: "pickUp", data: BytesLike): Result;
decodeFunctionResult(
functionFragment: "popFromField(bytes16,bytes16,bytes32[],uint8,uint256)",
Expand Down Expand Up @@ -847,8 +843,6 @@ export interface IWorld extends BaseContract {
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;

isStore(overrides?: CallOverrides): Promise<[void]>;

pickUp(
item: PromiseOrValue<BigNumberish>,
itemVariant: PromiseOrValue<BigNumberish>,
Expand Down Expand Up @@ -1169,8 +1163,6 @@ export interface IWorld extends BaseContract {
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;

isStore(overrides?: CallOverrides): Promise<void>;

pickUp(
item: PromiseOrValue<BigNumberish>,
itemVariant: PromiseOrValue<BigNumberish>,
Expand Down Expand Up @@ -1489,8 +1481,6 @@ export interface IWorld extends BaseContract {
overrides?: CallOverrides
): Promise<void>;

isStore(overrides?: CallOverrides): Promise<void>;

pickUp(
item: PromiseOrValue<BigNumberish>,
itemVariant: PromiseOrValue<BigNumberish>,
Expand Down Expand Up @@ -1856,8 +1846,6 @@ export interface IWorld extends BaseContract {
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<BigNumber>;

isStore(overrides?: CallOverrides): Promise<BigNumber>;

pickUp(
item: PromiseOrValue<BigNumberish>,
itemVariant: PromiseOrValue<BigNumberish>,
Expand Down Expand Up @@ -2179,8 +2167,6 @@ export interface IWorld extends BaseContract {
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<PopulatedTransaction>;

isStore(overrides?: CallOverrides): Promise<PopulatedTransaction>;

pickUp(
item: PromiseOrValue<BigNumberish>,
itemVariant: PromiseOrValue<BigNumberish>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -732,13 +732,6 @@ const _abi = [
stateMutability: "nonpayable",
type: "function",
},
{
inputs: [],
name: "isStore",
outputs: [],
stateMutability: "view",
type: "function",
},
{
inputs: [
{
Expand Down
5 changes: 1 addition & 4 deletions examples/minimal/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 0 additions & 7 deletions packages/store/abi/IStore.sol/IStore.abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -428,13 +428,6 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isStore",
"outputs": [],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
Expand Down
7 changes: 0 additions & 7 deletions packages/store/abi/IStore.sol/IStoreData.abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,13 +290,6 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isStore",
"outputs": [],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
Expand Down
Loading