Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@latticexyz/store-sync": "workspace:*",
"@latticexyz/utils": "workspace:*",
"@latticexyz/world": "workspace:*",
"@latticexyz/world-module-batchstore": "workspace:*",
"@latticexyz/world-module-callwithsignature": "workspace:*",
"@latticexyz/world-module-metadata": "workspace:*",
"abitype": "1.0.9",
Expand Down
49 changes: 31 additions & 18 deletions packages/cli/src/deploy/configToModules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,48 @@ import { World } from "@latticexyz/world";
import { importContractArtifact } from "../utils/importContractArtifact";
import { resolveWithContext } from "@latticexyz/world/internal";
import callWithSignatureModule from "@latticexyz/world-module-callwithsignature/out/CallWithSignatureModule.sol/CallWithSignatureModule.json" with { type: "json" };
import batchStoreModule from "@latticexyz/world-module-batchstore/out/BatchStoreModule.sol/BatchStoreModule.json" with { type: "json" };
import { getContractArtifact } from "../utils/getContractArtifact";
import { excludeCallWithSignatureModule } from "./compat/excludeUnstableCallWithSignatureModule";
import { moduleArtifactPathFromName } from "./compat/moduleArtifactPathFromName";

const callWithSignatureModuleArtifact = getContractArtifact(callWithSignatureModule);
const batchStoreModuleArtifact = getContractArtifact(batchStoreModule);

// metadata module is installed inside `ensureResourceTags`
const defaultModules: Module[] = [
{
// optional for now
// TODO: figure out approach to install on existing worlds where deployer may not own root namespace
optional: true,
name: "CallWithSignatureModule",
installStrategy: "root",
installData: "0x",
prepareDeploy: createPrepareDeploy(
callWithSignatureModuleArtifact.bytecode,
callWithSignatureModuleArtifact.placeholders,
),
deployedBytecodeSize: callWithSignatureModuleArtifact.deployedBytecodeSize,
abi: callWithSignatureModuleArtifact.abi,
},
{
// optional for now
// TODO: figure out approach to install on existing worlds where deployer may not own root namespace
optional: true,
name: "BatchStoreModule",
installStrategy: "root",
installData: "0x",
prepareDeploy: createPrepareDeploy(batchStoreModuleArtifact.bytecode, batchStoreModuleArtifact.placeholders),
deployedBytecodeSize: batchStoreModuleArtifact.deployedBytecodeSize,
abi: batchStoreModuleArtifact.abi,
},
];

export async function configToModules<config extends World>(
config: config,
// TODO: remove/replace `forgeOutDir`
forgeOutDir: string,
): Promise<readonly Module[]> {
// metadata module is installed inside `ensureResourceTags`
const defaultModules: Module[] = [
{
// optional for now
// TODO: figure out approach to install on existing worlds where deployer may not own root namespace
optional: true,
name: "CallWithSignatureModule",
installStrategy: "root",
installData: "0x",
prepareDeploy: createPrepareDeploy(
callWithSignatureModuleArtifact.bytecode,
callWithSignatureModuleArtifact.placeholders,
),
deployedBytecodeSize: callWithSignatureModuleArtifact.deployedBytecodeSize,
abi: callWithSignatureModuleArtifact.abi,
},
];

const modules = await Promise.all(
config.modules
.filter(excludeCallWithSignatureModule)
Expand Down
2 changes: 2 additions & 0 deletions packages/world-module-batchstore/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cache
out
8 changes: 8 additions & 0 deletions packages/world-module-batchstore/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "solhint:recommended",
"rules": {
"compiler-version": ["error", ">=0.8.0"],
"avoid-low-level-calls": "off",
"func-visibility": ["warn", { "ignoreConstructors": true }]
}
}
1 change: 1 addition & 0 deletions packages/world-module-batchstore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# BatchStore world module
15 changes: 15 additions & 0 deletions packages/world-module-batchstore/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[profile.default]
solc = "0.8.24"
ffi = false
fuzz_runs = 256
optimizer = true
optimizer_runs = 3000
verbosity = 3
allow_paths = ["../../node_modules", "../"]
src = "src"
out = "out"
bytecode_hash = "none"
extra_output_files = [
"abi",
"evm.bytecode"
]
17 changes: 17 additions & 0 deletions packages/world-module-batchstore/mud.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { defineWorld } from "@latticexyz/world";

export default defineWorld({
codegen: {
generateSystemLibraries: true,
// generate into experimental dir until these are stable/audited
systemLibrariesDirectory: "experimental/systems",
},
systems: {
BatchStoreSystem: {
deploy: {
disabled: true,
registerWorldFunctions: false,
},
},
},
});
58 changes: 58 additions & 0 deletions packages/world-module-batchstore/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@latticexyz/world-module-batchstore",
"version": "2.2.23",
"description": "BatchStore world module",
"repository": {
"type": "git",
"url": "https://github.com/latticexyz/mud.git",
"directory": "packages/world-module-batchstore"
},
"license": "MIT",
"type": "module",
"exports": {
"./mud.config": "./dist/mud.config.js",
"./out/*": "./out/*"
},
"typesVersions": {
"*": {
"mud.config": [
"./dist/mud.config.d.ts"
]
}
},
"files": [
"dist",
"out",
"src"
],
"scripts": {
"build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts && pnpm run build:js",
"build:abi": "forge build",
"build:abi-ts": "abi-ts",
"build:js": "tsup",
"build:mud": "tsx ./ts/build.ts",
"clean": "pnpm run clean:abi && pnpm run clean:js && pnpm run clean:mud",
"clean:abi": "forge clean",
"clean:js": "shx rm -rf dist",
"clean:mud": "shx rm -rf src/**/codegen",
"dev": "tsup --watch",
"gas-report": "gas-report --save gas-report.json",
"lint": "solhint --config ./.solhint.json 'src/**/*.sol'",
"test": "tsc --noEmit && forge test",
"test:ci": "pnpm run test"
},
"dependencies": {
"@latticexyz/schema-type": "workspace:*",
"@latticexyz/store": "workspace:*",
"@latticexyz/world": "workspace:*"
},
"devDependencies": {
"@latticexyz/abi-ts": "workspace:*",
"@latticexyz/gas-report": "workspace:*",
"forge-std": "https://github.com/foundry-rs/forge-std.git#60acb7aaadcce2d68e52986a0a66fe79f07d138f",
"solhint": "^3.3.7"
},
"publishConfig": {
"access": "public"
}
}
2 changes: 2 additions & 0 deletions packages/world-module-batchstore/remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
forge-std/=node_modules/forge-std/src/
@latticexyz/=node_modules/@latticexyz/
25 changes: 25 additions & 0 deletions packages/world-module-batchstore/src/BatchStoreModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.24;

import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";

import { Module } from "@latticexyz/world/src/Module.sol";
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
import { ResourceIds } from "@latticexyz/store/src/codegen/tables/ResourceIds.sol";
import { worldRegistrationSystem } from "@latticexyz/world/src/codegen/experimental/systems/WorldRegistrationSystemLib.sol";

import { BatchStoreSystem } from "./BatchStoreSystem.sol";
import { batchStoreSystem } from "./codegen/experimental/systems/BatchStoreSystemLib.sol";

contract BatchStoreModule is Module {
BatchStoreSystem private immutable systemAddress = new BatchStoreSystem();

function installRoot(bytes memory encodedArgs) public override {
ResourceId systemId = batchStoreSystem.toResourceId();

if (batchStoreSystem.getAddress() != address(systemAddress)) {
// install or upgrade system
worldRegistrationSystem.callAsRoot().registerSystem(systemId, systemAddress, true);
}
}
}
60 changes: 60 additions & 0 deletions packages/world-module-batchstore/src/BatchStoreSystem.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.24;

import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
import { System } from "@latticexyz/world/src/System.sol";
import { AccessControl } from "@latticexyz/world/src/AccessControl.sol";
import { StoreCore } from "@latticexyz/store/src/StoreCore.sol";
import { EncodedLengths } from "@latticexyz/store/src/EncodedLengths.sol";
import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol";
import { TableRecord } from "./common.sol";

contract BatchStoreSystem is System {
function getTableRecords(
ResourceId tableId,
bytes32[][] memory keyTuples
) external view returns (TableRecord[] memory records) {
AccessControl._requireAccess(tableId, _msgSender());
Copy link
Member

Choose a reason for hiding this comment

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

do we need access control the read function?

Copy link
Member Author

Choose a reason for hiding this comment

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

oh whoops, copy pasta mistake


FieldLayout fieldLayout = StoreCore.getFieldLayout(tableId);
records = new TableRecord[](keyTuples.length);

for (uint256 i = 0; i < keyTuples.length; i++) {
(bytes memory staticData, EncodedLengths encodedLengths, bytes memory dynamicData) = StoreCore.getRecord(
tableId,
keyTuples[i],
fieldLayout
);
records[i] = TableRecord({
keyTuple: keyTuples[i],
staticData: staticData,
encodedLengths: encodedLengths,
dynamicData: dynamicData
});
}
}

function setTableRecords(ResourceId tableId, TableRecord[] memory records) external {
AccessControl._requireAccess(tableId, _msgSender());

Copy link
Member Author

Choose a reason for hiding this comment

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

need to get field layout here to save gas

for (uint256 i = 0; i < records.length; i++) {
StoreCore.setRecord(
tableId,
records[i].keyTuple,
records[i].staticData,
records[i].encodedLengths,
records[i].dynamicData
);
}
}

function deleteTableRecords(ResourceId tableId, bytes32[][] memory keyTuples) external {
AccessControl._requireAccess(tableId, _msgSender());
Copy link
Member Author

Choose a reason for hiding this comment

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

should these be requireAccess rather than _requireAccess?


FieldLayout fieldLayout = StoreCore.getFieldLayout(tableId);

for (uint256 i = 0; i < keyTuples.length; i++) {
StoreCore.deleteRecord(tableId, keyTuples[i], fieldLayout);
}
}
}
Loading
Loading