Skip to content

Commit 9212386

Browse files
frolicalvrs
andauthored
feat(world): support callFrom(batchCall) (#3506)
Co-authored-by: alvarius <[email protected]>
1 parent 7a3e580 commit 9212386

File tree

2 files changed

+50
-7
lines changed

2 files changed

+50
-7
lines changed

packages/world/src/modules/init/implementations/BatchCallSystem.sol

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { IBaseWorld } from "../../../codegen/interfaces/IBaseWorld.sol";
66
import { revertWithBytes } from "../../../revertWithBytes.sol";
77
import { SystemCallData, SystemCallFromData } from "../types.sol";
88
import { LimitedCallContext } from "../LimitedCallContext.sol";
9+
import { SystemCall } from "../../../SystemCall.sol";
910

1011
/**
1112
* @title Batch Call System
@@ -22,16 +23,15 @@ contract BatchCallSystem is System, LimitedCallContext {
2223
function batchCall(
2324
SystemCallData[] calldata systemCalls
2425
) public onlyDelegatecall returns (bytes[] memory returnDatas) {
25-
IBaseWorld world = IBaseWorld(_world());
2626
returnDatas = new bytes[](systemCalls.length);
2727

2828
for (uint256 i; i < systemCalls.length; i++) {
29-
(bool success, bytes memory returnData) = address(world).delegatecall(
30-
abi.encodeCall(world.call, (systemCalls[i].systemId, systemCalls[i].callData))
29+
returnDatas[i] = SystemCall.callWithHooksOrRevert(
30+
_msgSender(),
31+
systemCalls[i].systemId,
32+
systemCalls[i].callData,
33+
0
3134
);
32-
if (!success) revertWithBytes(returnData);
33-
34-
returnDatas[i] = abi.decode(returnData, (bytes));
3535
}
3636
}
3737

@@ -48,11 +48,11 @@ contract BatchCallSystem is System, LimitedCallContext {
4848
returnDatas = new bytes[](systemCalls.length);
4949

5050
for (uint256 i; i < systemCalls.length; i++) {
51+
// TODO: swap this with SystemCall.callFromWithHooksOrRevert once available
5152
(bool success, bytes memory returnData) = address(world).delegatecall(
5253
abi.encodeCall(world.callFrom, (systemCalls[i].from, systemCalls[i].systemId, systemCalls[i].callData))
5354
);
5455
if (!success) revertWithBytes(returnData);
55-
5656
returnDatas[i] = abi.decode(returnData, (bytes));
5757
}
5858
}

packages/world/test/BatchCall.t.sol

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { RESOURCE_SYSTEM } from "../src/worldResourceTypes.sol";
1414
import { IWorldErrors } from "../src/IWorldErrors.sol";
1515
import { IBaseWorld } from "../src/codegen/interfaces/IBaseWorld.sol";
1616
import { SystemCallData, SystemCallFromData } from "../src/modules/init/types.sol";
17+
import { BATCH_CALL_SYSTEM_ID } from "../src/modules/init/constants.sol";
18+
import { BatchCallSystem } from "../src/modules/init/implementations/BatchCallSystem.sol";
1719

1820
import { createWorld } from "./createWorld.sol";
1921

@@ -175,4 +177,45 @@ contract BatchCallTest is Test, GasReporter {
175177
assertEq(abi.decode(returnDatas[0], (address)), delegatee, "wrong delegatee returned");
176178
assertEq(abi.decode(returnDatas[1], (address)), delegator, "wrong delegator returned");
177179
}
180+
181+
/**
182+
* If all calls come from the same delegation, it should be simpler and cheaper to compose
183+
* calls via `callFrom(batchCall(...))` instead of `batchCallFrom(...)`.
184+
*/
185+
function testCallFromBatchCall() public {
186+
// Register a new system
187+
TestSystem system = new TestSystem();
188+
world.registerSystem(systemId, system, true);
189+
190+
// Try to increment the counter without creating a delegation
191+
SystemCallData[] memory systemCalls = new SystemCallData[](1);
192+
systemCalls[0] = SystemCallData(systemId, abi.encodeCall(TestSystem.increment, ()));
193+
194+
vm.prank(delegatee);
195+
vm.expectRevert(abi.encodeWithSelector(IWorldErrors.World_DelegationNotFound.selector, delegator, delegatee));
196+
world.callFrom(delegator, BATCH_CALL_SYSTEM_ID, abi.encodeCall(BatchCallSystem.batchCall, (systemCalls)));
197+
198+
// Create an unlimited delegation
199+
vm.prank(delegator);
200+
world.registerDelegation(delegatee, UNLIMITED_DELEGATION, new bytes(0));
201+
202+
// Try to increment the counter without setting the admin
203+
vm.prank(delegatee);
204+
vm.expectRevert("sender is not admin");
205+
world.callFrom(delegator, BATCH_CALL_SYSTEM_ID, abi.encodeCall(BatchCallSystem.batchCall, (systemCalls)));
206+
207+
assertEq(system.admin(), address(0));
208+
209+
// Set the admin and increment the counter twice
210+
systemCalls = new SystemCallData[](3);
211+
systemCalls[0] = SystemCallData(systemId, abi.encodeCall(TestSystem.setAdmin, (delegator)));
212+
systemCalls[1] = SystemCallData(systemId, abi.encodeCall(TestSystem.increment, ()));
213+
systemCalls[2] = SystemCallData(systemId, abi.encodeCall(TestSystem.increment, ()));
214+
215+
vm.prank(delegatee);
216+
world.callFrom(delegator, BATCH_CALL_SYSTEM_ID, abi.encodeCall(BatchCallSystem.batchCall, (systemCalls)));
217+
218+
assertEq(system.admin(), delegator);
219+
assertEq(system.counter(), 2, "wrong counter value");
220+
}
178221
}

0 commit comments

Comments
 (0)