-
Notifications
You must be signed in to change notification settings - Fork 202
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 CallBatchSystem to core module #1500
Changes from 2 commits
f2d79e0
e5bba67
ca27801
8ab8d04
4f00381
c3c3d00
ad2bebb
f7c9bc9
7cd8904
c2a9869
295ed8c
7159e83
312dba9
f27d7a2
94cfee6
2218493
059b0e6
5cf3012
8300aa0
480b721
1affa39
e8144b7
56f1094
9f8a2a2
4ce27d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.0; | ||
|
||
interface IBatchCallSystem { | ||
function batchCall_system_batchCall(bytes32[] memory resourceSelectors, bytes[] memory funcSelectorAndArgs) external; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.0; | ||
|
||
import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; | ||
|
||
import { Module } from "../../Module.sol"; | ||
import { ResourceSelector } from "../../ResourceSelector.sol"; | ||
|
||
import { BatchCallSystem } from "./BatchCallSystem.sol"; | ||
|
||
import { NAMESPACE, MODULE_NAME, SYSTEM_NAME } from "./constants.sol"; | ||
|
||
contract BatchCallModule is Module { | ||
BatchCallSystem private immutable batchCallSystem = new BatchCallSystem(); | ||
|
||
function getName() public pure returns (bytes16) { | ||
return MODULE_NAME; | ||
} | ||
|
||
function installRoot(bytes memory args) public { | ||
install(args); | ||
} | ||
|
||
function install(bytes memory) public { | ||
IBaseWorld world = IBaseWorld(_world()); | ||
|
||
world.registerSystem(ResourceSelector.from(NAMESPACE, SYSTEM_NAME), batchCallSystem, true); | ||
|
||
world.registerFunctionSelector(ResourceSelector.from(NAMESPACE, SYSTEM_NAME), "batchCall", "(bytes32[],bytes[])"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.0; | ||
import { System } from "../../System.sol"; | ||
import { IBaseWorld } from "../../interfaces/IBaseWorld.sol"; | ||
|
||
contract BatchCallSystem is System { | ||
function batchCall(bytes32[] memory resourceSelectors, bytes[] memory funcSelectorAndArgss) public { | ||
IBaseWorld world = IBaseWorld(_world()); | ||
|
||
for (uint256 i; i < resourceSelectors.length; i++) { | ||
world.callFrom(_msgSender(), resourceSelectors[i], funcSelectorAndArgss[i]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we make this a root system and then do this so the users don't need to create a delegation? (bool success, bytes memory returnData) = address(world).delegatecall(abi.encodeCall(
world.call,
(
_msgSender(),
resourceSelector[i],
funcSelectorAndArgs[i]
)
));
if(!success) revertWithBytes(returnData); We can actually do both, have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need this to be a module? if we intend to use this for deploys anyway, would it make sense to just have this under There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah it can also be part of the core module There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this approach without the delegation. I'm going to add the root version to the core module. I'll also remove the non-root version, because the root version will be installed on worlds by default. |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.0; | ||
|
||
bytes16 constant NAMESPACE = bytes16("batchCall"); | ||
bytes16 constant MODULE_NAME = bytes16("batchCall.m"); | ||
bytes16 constant SYSTEM_NAME = bytes16("system"); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// 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 { ROOT_NAMESPACE, UNLIMITED_DELEGATION } from "../src/constants.sol"; | ||
import { World } from "../src/World.sol"; | ||
import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; | ||
import { IWorldErrors } from "../src/interfaces/IWorldErrors.sol"; | ||
|
||
import { CoreModule } from "../src/modules/core/CoreModule.sol"; | ||
import { BatchCallModule } from "../src/modules/batchcall/BatchCallModule.sol"; | ||
import { IBatchCallSystem } from "../src/interfaces/IBatchCallSystem.sol"; | ||
|
||
import { NAMESPACE } from "../src/modules/batchcall/constants.sol"; | ||
import { ResourceSelector } from "../src/ResourceSelector.sol"; | ||
|
||
import { WorldTestSystem } from "./World.t.sol"; | ||
|
||
contract BatchCallModuleTest is Test, GasReporter { | ||
using ResourceSelector for bytes32; | ||
|
||
IBaseWorld world; | ||
BatchCallModule batchCallModule = new BatchCallModule(); | ||
|
||
function setUp() public { | ||
world = IBaseWorld(address(new World())); | ||
world.initialize(new CoreModule()); | ||
} | ||
|
||
function testInstall() public { | ||
startGasReport("install batch call module"); | ||
world.installModule(batchCallModule, new bytes(0)); | ||
endGasReport(); | ||
|
||
// Register a new system | ||
WorldTestSystem system = new WorldTestSystem(); | ||
bytes32 resourceSelector = ResourceSelector.from("namespace", "testSystem"); | ||
|
||
world.registerSystem(resourceSelector, system, false); | ||
|
||
bytes32[] memory resourceSelectors = new bytes32[](1); | ||
bytes[] memory funcSelectorAndArgss = new bytes[](1); | ||
|
||
resourceSelectors[0] = resourceSelector; | ||
funcSelectorAndArgss[0] = abi.encodeWithSelector(WorldTestSystem.getStoreAddress.selector); | ||
|
||
// TODO: do not hardcode this | ||
address delegatee = 0x104fBc016F4bb334D775a19E8A6510109AC63E00; | ||
|
||
vm.expectRevert(abi.encodeWithSelector(IWorldErrors.DelegationNotFound.selector, address(this), delegatee)); | ||
IBatchCallSystem(address(world)).batchCall_system_batchCall(resourceSelectors, funcSelectorAndArgss); | ||
|
||
// Register an unlimited delegation | ||
world.registerDelegation(delegatee, UNLIMITED_DELEGATION, new bytes(0)); | ||
|
||
IBatchCallSystem(address(world)).batchCall_system_batchCall(resourceSelectors, funcSelectorAndArgss); | ||
} | ||
|
||
function testInstallRoot() public { | ||
startGasReport("installRoot batch call module"); | ||
world.installRootModule(batchCallModule, new bytes(0)); | ||
endGasReport(); | ||
|
||
// Register a new system | ||
WorldTestSystem system = new WorldTestSystem(); | ||
bytes32 resourceSelector = ResourceSelector.from("namespace", "testSystem"); | ||
|
||
world.registerSystem(resourceSelector, system, false); | ||
|
||
bytes32[] memory resourceSelectors = new bytes32[](1); | ||
bytes[] memory funcSelectorAndArgss = new bytes[](1); | ||
|
||
resourceSelectors[0] = resourceSelector; | ||
funcSelectorAndArgss[0] = abi.encodeWithSelector(WorldTestSystem.getStoreAddress.selector); | ||
|
||
// TODO: do not hardcode this | ||
address delegatee = 0x104fBc016F4bb334D775a19E8A6510109AC63E00; | ||
|
||
vm.expectRevert(abi.encodeWithSelector(IWorldErrors.DelegationNotFound.selector, address(this), delegatee)); | ||
IBatchCallSystem(address(world)).batchCall_system_batchCall(resourceSelectors, funcSelectorAndArgss); | ||
|
||
// Register an unlimited delegation | ||
world.registerDelegation(delegatee, UNLIMITED_DELEGATION, new bytes(0)); | ||
|
||
IBatchCallSystem(address(world)).batchCall_system_batchCall(resourceSelectors, funcSelectorAndArgss); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be worse on calldata length if this was something like
(this feels cleaner but I would prob optimize for calldata/gas here, since these calls will be abstracted away anyway)