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

feat(world): add World prototype #405

Merged
merged 42 commits into from
Feb 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a0dbcc1
feat(world): initial package scaffold
alvrs Feb 15, 2023
ee1ce70
feat(world): add core tables
alvrs Feb 15, 2023
f39c2ce
feat(store): add more types and overloads
alvrs Feb 15, 2023
dad190b
feat(world): register core tables
alvrs Feb 15, 2023
ce31edd
feat(store): allow StoreSwitch usage in constructors
alvrs Feb 15, 2023
9a267f9
feat(world): add registerRoute
alvrs Feb 15, 2023
43b7070
feat(world): add registerTable
alvrs Feb 16, 2023
a3f5e68
feat(world): add registerSystem
alvrs Feb 16, 2023
d0f8e12
feat(world): add grantAccess and retractAccess
alvrs Feb 16, 2023
cdad26d
feat(store): change IStore to use calldata
alvrs Feb 16, 2023
4e216e0
feat(world): add setRecord with access control based on route
alvrs Feb 16, 2023
d1ecc42
feat(world): add call entry point
alvrs Feb 16, 2023
b1bda3e
feat(world): return errors to caller via _call
alvrs Feb 16, 2023
d2b54a9
fix(store): update Store interfaces to use calldata instead of memory
alvrs Feb 17, 2023
177d98d
feat(world): forward error from system calls via World
alvrs Feb 17, 2023
a466e62
fix(store): update deleteRecord to use calldata
alvrs Feb 17, 2023
29c1558
feat(world): add setField, deleteRecord, _isRoute, _isSingleLevelRoute
alvrs Feb 17, 2023
accef11
test(world): add test for deleteRecord
alvrs Feb 17, 2023
416288d
feat(store): rename registerHook to registerStoreHook
alvrs Feb 17, 2023
c38bfc4
feat(world): add registerTableHook and prepare for registerSystemHook
alvrs Feb 17, 2023
2cc28af
refactor(world): change tableId type from bytes32 to uint256
alvrs Feb 17, 2023
7fc68d0
test(world): add tests for systems writing to the world
alvrs Feb 17, 2023
270f193
docs(store): update comment for clarity
alvrs Feb 21, 2023
f25f3be
build(world): remove explicit --out from forge build command
alvrs Feb 21, 2023
ba8ed10
chore(world): update imports from store to @latticexyz/store
alvrs Feb 21, 2023
f37a289
chore(world): remove unused import
alvrs Feb 21, 2023
f010ea2
refactor(world): save baseRouteId in memory
alvrs Feb 21, 2023
da48c0f
refactor(world): use bytes32ToBool util instead of Slice.toBool
alvrs Feb 21, 2023
9901b65
refactor(store): remove unused toBool and toString methods
alvrs Feb 21, 2023
bcfcf68
docs(store): add comments to StoreView
alvrs Feb 21, 2023
0c91fba
build(world): reduce forge optimizer runs to 3000
alvrs Feb 21, 2023
26642b3
fix(world): prevent empty routes
alvrs Feb 21, 2023
0278f0a
refactor(world): use uint256 for routeId instead of bytes32
alvrs Feb 21, 2023
8247a54
ci(world): avoid conflicting Store contracts
alvrs Feb 21, 2023
fdcc1da
refactor(store): remove unused World and System contracts and tests
alvrs Feb 21, 2023
b6258e5
test: update gas report
alvrs Feb 21, 2023
9a68d83
refactor(world): update remapping
alvrs Feb 21, 2023
1f2f19e
ci: disable automatic gas-report commit and instead just check if gas…
alvrs Feb 21, 2023
75849f2
docs(world): update index.yml
alvrs Feb 21, 2023
253d8bb
ci: fix gas-report action typo
alvrs Feb 22, 2023
7a9c9f7
fix: rebase changes
alvrs Feb 22, 2023
6d349f1
fix(world): use released mud cli for gas report
alvrs Feb 22, 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
9 changes: 3 additions & 6 deletions .github/workflows/gasreport.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
pull_request:
paths:
- packages/store/**
- packages/world/**

jobs:
gas-report:
Expand All @@ -29,9 +30,5 @@ jobs:
- name: Install local CLI
run: cd packages/cli && yarn build && npm link && cd ../..

- name: Run gas report
run: yarn workspace @latticexyz/store run gasreport

- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "test: update gas report"
- name: Verify that gas report is up to date
run: yarn workspace @latticexyz/store run gasreport && yarn workspace @latticexyz/world run gasreport && if [ -n "$(git status --porcelain)" ]; then exit 0; fi
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"ds-test/=node_modules/ds-test/src/",
"solecs/=node_modules/@latticexyz/solecs/src/",
"royalty-registry/=node_modules/@manifoldxzy/royalty-registry/contracts/",
"std-contracts/=node_modules/@latticexyz/std-contracts/src/"
"std-contracts/=node_modules/@latticexyz/std-contracts/src/",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not blocking for this PR but we should update these usages to use the @latticexyz/std-contracts import format

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

considering it's a breaking change and not relevant for v2, is it worth it for v1 packages?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we do breaking changes all the time 🙈

"@latticexyz/=node_modules/@latticexyz/"
]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"packages/schema-type",
"packages/solecs",
"packages/store",
"packages/world",
"packages/cli",
"packages/recs",
"packages/react",
Expand Down
2 changes: 1 addition & 1 deletion packages/store/gas-report.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,4 @@
(test/Vector2Table.t.sol) | set Vector2Table record [Vector2Table.set({ key: key, x: 1, y: 2 })]: 35773
(test/Vector2Table.t.sol) | get Vector2Table record [Vector2 memory vector = Vector2Table.get(key)]: 3638
(test/World.t.sol) | call autonomous system via World contract [WorldWithWorldTestSystem(address(world)).WorldTestSystem_move(entity, 1, 2)]: 43386
(test/World.t.sol) | call delegate system via World contract [WorldWithWorldTestSystem(address(world)).WorldTestSystem_move(entity, 1, 2)]: 41226
(test/World.t.sol) | call delegate system via World contract [WorldWithWorldTestSystem(address(world)).WorldTestSystem_move(entity, 1, 2)]: 41226
2 changes: 1 addition & 1 deletion packages/store/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@latticexyz/store",
"license": "MIT",
"version": "1.33.1",
"version": "1.34.0",
"description": "Store",
"types": "./types/ethers-contracts/",
"repository": {
Expand Down
14 changes: 7 additions & 7 deletions packages/store/src/IStore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@ interface IStore {
// Set full record (including full dynamic data)
function setRecord(
uint256 table,
bytes32[] memory key,
bytes memory data
bytes32[] calldata key,
bytes calldata data
) external;

// Set partial data at schema index
function setField(
uint256 table,
bytes32[] memory key,
bytes32[] calldata key,
uint8 schemaIndex,
bytes memory data
bytes calldata data
) external;

// Register hooks to be called when a record or field is set or deleted
function registerHook(uint256 table, IStoreHook hooks) external;
function registerStoreHook(uint256 table, IStoreHook hooks) external;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be IStoreHook hook (singular) not IStoreHook hooks?


// Set full record (including full dynamic data)
function deleteRecord(uint256 table, bytes32[] memory key) external;
Expand All @@ -40,14 +40,14 @@ interface IStore {
// Get full record (including full array)
function getRecord(
uint256 table,
bytes32[] memory key,
bytes32[] calldata key,
Schema schema
) external view returns (bytes memory data);

// Get partial data at schema index
function getField(
uint256 table,
bytes32[] memory key,
bytes32[] calldata key,
uint8 schemaIndex
) external view returns (bytes memory data);

Expand Down
12 changes: 10 additions & 2 deletions packages/store/src/Slice.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ using DecodeSlice for Slice global;
* @title Static functions for Slice
*/
library SliceLib {
error Slice_OutOfBounds();
error Slice_OutOfBounds(bytes data, uint256 start, uint256 end);

uint256 constant MASK_LEN = uint256(type(uint128).max);
uint256 constant MASK_PTR = uint256(type(uint128).max) << 128;
Expand All @@ -36,16 +36,24 @@ library SliceLib {
return Slice.wrap((_pointer << 128) | (data.length & MASK_LEN));
}

/**
* @dev Subslice a bytes array using the given start index until the end of the array (without copying data)
*/
function getSubslice(bytes memory data, uint256 start) internal pure returns (Slice) {
return getSubslice(data, start, data.length);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming nit: what about just slice?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I named it that way pretty much just to avoid confusion with the Slice type, and make searching for it easier


/**
* @dev Subslice a bytes array using the given indexes (without copying data)
* The start index is inclusive, the end index is exclusive
*/
function getSubslice(
bytes memory data,
uint256 start,
uint256 end
) internal pure returns (Slice) {
// TODO this check helps catch bugs and can eventually be removed
if (!(start <= end && end <= data.length)) revert Slice_OutOfBounds();
if (!(start <= end && end <= data.length)) revert Slice_OutOfBounds(data, start, end);

uint256 _pointer;
assembly {
Expand Down
42 changes: 42 additions & 0 deletions packages/store/src/Store.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import { SchemaType } from "./Types.sol";
import { IStore, IStoreHook } from "./IStore.sol";
import { StoreCore } from "./StoreCore.sol";
import { Schema } from "./Schema.sol";

abstract contract Store is IStore {
constructor() {
StoreCore.initialize();
}

function getSchema(uint256 table) public view virtual returns (Schema schema) {
schema = StoreCore.getSchema(table);
}

// Get full record (static and dynamic data, load schema from storage)
function getRecord(uint256 table, bytes32[] calldata key) public view virtual returns (bytes memory data) {
data = StoreCore.getRecord(table, key);
}

// Get full record (static and dynamic data)
function getRecord(
uint256 table,
bytes32[] calldata key,
Schema schema
) public view virtual returns (bytes memory data) {
data = StoreCore.getRecord(table, key, schema);
}

// Get partial data at schema index
function getField(
uint256 table,
bytes32[] calldata key,
uint8 schemaIndex
) public view virtual returns (bytes memory data) {
data = StoreCore.getField(table, key, schemaIndex);
}

function isStore() public view {}
}
2 changes: 1 addition & 1 deletion packages/store/src/StoreCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ library StoreCore {
/*
* Register hooks to be called when a record or field is set or deleted
*/
function registerHook(uint256 table, IStoreHook hook) external {
function registerStoreHook(uint256 table, IStoreHook hook) external {
HooksTable.push(table, address(hook));
}

Expand Down
4 changes: 3 additions & 1 deletion packages/store/src/StoreSwitch.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ library StoreSwitch {
assembly {
codeSize := extcodesize(address())
}
if (codeSize == 0) revert StoreSwitch_InvalidInsideConstructor();

// If the call is from within a constructor, use StoreCore to write to own storage
if (codeSize == 0) return true;

// Check whether this contract implements the IStore interface
try IStore(address(this)).isStore() {
Expand Down
66 changes: 24 additions & 42 deletions packages/store/src/StoreView.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,56 @@
pragma solidity >=0.8.0;

import { SchemaType } from "./Types.sol";
import { IStore, IStoreHook } from "./IStore.sol";
import { IStoreHook } from "./IStore.sol";
import { StoreCore } from "./StoreCore.sol";
import { Schema } from "./Schema.sol";
import { Store } from "./Store.sol";

// Not abstract, so that it can be used as a base contract for testing and wherever write access is not needed
contract StoreView is IStore {
contract StoreView is Store {
error StoreView_NotImplemented();

constructor() {
StoreCore.initialize();
}

function getSchema(uint256 table) public view virtual returns (Schema schema) {
schema = StoreCore.getSchema(table);
}

/**
* Not implemented in StoreView
*/
function registerSchema(uint256, Schema) public virtual {
dk1a marked this conversation as resolved.
Show resolved Hide resolved
revert StoreView_NotImplemented();
}

/**
* Not implemented in StoreView
*/
function setRecord(
uint256,
bytes32[] memory,
bytes memory
bytes32[] calldata,
bytes calldata
) public virtual {
revert StoreView_NotImplemented();
}

// Set partial data at schema index
/**
* Not implemented in StoreView
*/
function setField(
uint256,
bytes32[] memory,
bytes32[] calldata,
uint8,
bytes memory
bytes calldata
) public virtual {
revert StoreView_NotImplemented();
}

function registerHook(uint256, IStoreHook) public virtual {
/**
* Not implemented in StoreView
*/
function registerStoreHook(uint256, IStoreHook) public virtual {
alvrs marked this conversation as resolved.
Show resolved Hide resolved
revert StoreView_NotImplemented();
}

function deleteRecord(uint256, bytes32[] memory) public virtual {
/**
* Not implemented in StoreView
*/
function deleteRecord(uint256, bytes32[] calldata) public virtual {
revert StoreView_NotImplemented();
}

// Get full record (including full array, load schema from storage)
function getRecord(uint256 table, bytes32[] memory key) public view virtual returns (bytes memory data) {
data = StoreCore.getRecord(table, key);
}

// Get full record (including full array)
function getRecord(
uint256 table,
bytes32[] memory key,
Schema schema
) public view virtual returns (bytes memory data) {
data = StoreCore.getRecord(table, key, schema);
}

// Get partial data at schema index
function getField(
uint256 table,
bytes32[] memory key,
uint8 schemaIndex
) public view virtual returns (bytes memory data) {
data = StoreCore.getField(table, key, schemaIndex);
}

function isStore() public view {}
}
Loading