Skip to content

Commit d17a9be

Browse files
authored
feat(store-consumer): extract store consumer contracts (#3345)
1 parent 09536b0 commit d17a9be

33 files changed

Lines changed: 279 additions & 75 deletions

.changeset/nine-countries-nail.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@latticexyz/store-consumer": patch
3+
"@latticexyz/world-module-erc20": patch
4+
---
5+
6+
Extracted StoreConsumer base contracts into an independent package.
7+
Added a `registerNamespace` boolean to `WithWorld` to provide more control over namespace registration.

packages/store-consumer/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cache
2+
out
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# @latticexyz/store-consumer

packages/store-consumer/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Store Consumer Contracts
2+
3+
> :warning: **Important note: these contracts have not been audited yet, so any production use is discouraged for now.**
4+
5+
This set of contracts provides an easy way to make use of a `Store` for read and write operations, with the possibility of fully abstracting away the type of underlying store being used.
6+
7+
- `StoreConsumer`: all contracts that don't explicitly need to know which type of store is being used can inherit from `StoreConsumer`, which abstracts the way in which `ResourceId`s are encoded. This allows us to have composable contracts whose implementations don't depend on the type of the underlying Store.
8+
- `WithStore(address) is StoreConsumer`: this contract initializes the store, using the contract's internal storage or the provided external `Store`. It encodes `ResourceId`s using `ResourceIdLib` from the `@latticexyz/store` package.
9+
- `WithWorld(IBaseWorld, bytes14) is WithStore`: initializes the store and also registers the provided namespace in the provided World. It encodes `ResourceId`s using `WorldResourceIdLib` (using the namespace). It also provides an `onlyNamespace` modifier, which can be used to restrict access to certain functions, only allowing calls from addresses that have access to the namespace.
10+
11+
For examples of how these are used in practice you can check the [examples directory](./src/examples/) or our [ERC20 World Module](../world-module-erc20/).
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[profile.default]
2+
solc = "0.8.24"
3+
ffi = false
4+
fuzz_runs = 256
5+
optimizer = true
6+
optimizer_runs = 3000
7+
verbosity = 2
8+
allow_paths = ["../../node_modules", "../"]
9+
src = "src"
10+
out = "out"
11+
bytecode_hash = "none"
12+
extra_output_files = [
13+
"abi",
14+
"evm.bytecode"
15+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"name": "@latticexyz/store-consumer",
3+
"version": "2.2.14",
4+
"description": "Store Consumer Contracts",
5+
"repository": {
6+
"type": "git",
7+
"url": "https://github.com/latticexyz/mud.git",
8+
"directory": "packages/store-consumer"
9+
},
10+
"license": "MIT",
11+
"type": "module",
12+
"exports": {
13+
"./out/*": "./out/*"
14+
},
15+
"typesVersions": {
16+
"*": {}
17+
},
18+
"files": [
19+
"out",
20+
"src"
21+
],
22+
"scripts": {
23+
"build": "pnpm run build:abi && pnpm run build:abi-ts",
24+
"build:abi": "forge build",
25+
"build:abi-ts": "abi-ts",
26+
"clean": "pnpm run clean:abi && pnpm run clean:js",
27+
"clean:abi": "forge clean",
28+
"clean:js": "shx rm -rf dist",
29+
"clean:mud": "shx rm -rf src/**/codegen",
30+
"dev": "tsup --watch",
31+
"gas-report": "gas-report --save gas-report.json",
32+
"lint": "solhint --config ./.solhint.json 'src/**/*.sol'",
33+
"test": "forge test",
34+
"test:ci": "pnpm run test"
35+
},
36+
"dependencies": {
37+
"@latticexyz/schema-type": "workspace:*",
38+
"@latticexyz/store": "workspace:*",
39+
"@latticexyz/world": "workspace:*"
40+
},
41+
"devDependencies": {
42+
"@latticexyz/abi-ts": "workspace:*",
43+
"@latticexyz/gas-report": "workspace:*",
44+
"@types/node": "^18.15.11",
45+
"forge-std": "https://github.com/foundry-rs/forge-std.git#1eea5bae12ae557d589f9f0f0edae2faa47cb262",
46+
"solhint": "^3.3.7",
47+
"tsup": "^6.7.0",
48+
"vitest": "0.34.6"
49+
},
50+
"publishConfig": {
51+
"access": "public"
52+
}
53+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
forge-std/=node_modules/forge-std/src/
2+
@latticexyz/=node_modules/@latticexyz/
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >=0.8.24;
3+
4+
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
5+
import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";
6+
import { NamespaceOwner } from "@latticexyz/world/src/codegen/tables/NamespaceOwner.sol";
7+
8+
import { WithWorld } from "../experimental/WithWorld.sol";
9+
10+
interface IERC20 {
11+
function transfer(address to, uint256 value) external returns (bool);
12+
function allowance(address owner, address spender) external view returns (uint256);
13+
function approve(address spender, uint256 value) external returns (bool);
14+
function transferFrom(address from, address to, uint256 value) external returns (bool);
15+
}
16+
17+
/**
18+
* @title SimpleVault (NOT AUDITED)
19+
* @dev Simple example of a Vault that allows accounts with namespace access to transfer its tokens out
20+
* IMPORTANT: this contract expects an existing namespace
21+
*/
22+
contract SimpleVault is WithWorld {
23+
error SimpleVault_TransferFailed();
24+
25+
constructor(IBaseWorld world, bytes14 namespace) WithWorld(world, namespace, false) {}
26+
27+
// Only accounts with namespace access (e.g. namespace systems) can transfer the ERC20 tokens held by this contract
28+
function transferTo(IERC20 token, address to, uint256 amount) external onlyNamespace {
29+
require(token.transfer(to, amount), "Transfer failed");
30+
}
31+
32+
// ... other methods to deposit, etc
33+
}
File renamed without changes.

0 commit comments

Comments
 (0)