Skip to content

Commit

Permalink
refactor(world): expose library for WorldContextConsumer (#1624)
Browse files Browse the repository at this point in the history
  • Loading branch information
alvrs committed Sep 30, 2023
1 parent 9019d8e commit 88b1a5a
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 59 deletions.
7 changes: 7 additions & 0 deletions .changeset/olive-foxes-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@latticexyz/world-modules": patch
"@latticexyz/world": major
---

We now expose a `WorldContextConsumerLib` library with the same functionality as the `WorldContextConsumer` contract, but the ability to be used inside of internal libraries.
We also renamed the `WorldContextProvider` library to `WorldContextProviderLib` for consistency.
30 changes: 15 additions & 15 deletions packages/world-modules/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
"file": "test/KeysInTableModule.t.sol",
"test": "testInstallComposite",
"name": "install keys in table module",
"gasUsed": 1407523
"gasUsed": 1407698
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testInstallGas",
"name": "install keys in table module",
"gasUsed": 1407523
"gasUsed": 1407698
},
{
"file": "test/KeysInTableModule.t.sol",
Expand All @@ -21,13 +21,13 @@
"file": "test/KeysInTableModule.t.sol",
"test": "testInstallSingleton",
"name": "install keys in table module",
"gasUsed": 1407523
"gasUsed": 1407698
},
{
"file": "test/KeysInTableModule.t.sol",
"test": "testSetAndDeleteRecordHookCompositeGas",
"name": "install keys in table module",
"gasUsed": 1407523
"gasUsed": 1407698
},
{
"file": "test/KeysInTableModule.t.sol",
Expand All @@ -45,7 +45,7 @@
"file": "test/KeysInTableModule.t.sol",
"test": "testSetAndDeleteRecordHookGas",
"name": "install keys in table module",
"gasUsed": 1407523
"gasUsed": 1407698
},
{
"file": "test/KeysInTableModule.t.sol",
Expand All @@ -63,7 +63,7 @@
"file": "test/KeysWithValueModule.t.sol",
"test": "testGetKeysWithValueGas",
"name": "install keys with value module",
"gasUsed": 648854
"gasUsed": 648994
},
{
"file": "test/KeysWithValueModule.t.sol",
Expand All @@ -81,7 +81,7 @@
"file": "test/KeysWithValueModule.t.sol",
"test": "testInstall",
"name": "install keys with value module",
"gasUsed": 648854
"gasUsed": 648994
},
{
"file": "test/KeysWithValueModule.t.sol",
Expand All @@ -93,7 +93,7 @@
"file": "test/KeysWithValueModule.t.sol",
"test": "testSetAndDeleteRecordHook",
"name": "install keys with value module",
"gasUsed": 648854
"gasUsed": 648994
},
{
"file": "test/KeysWithValueModule.t.sol",
Expand All @@ -111,7 +111,7 @@
"file": "test/KeysWithValueModule.t.sol",
"test": "testSetField",
"name": "install keys with value module",
"gasUsed": 648854
"gasUsed": 648994
},
{
"file": "test/KeysWithValueModule.t.sol",
Expand Down Expand Up @@ -195,31 +195,31 @@
"file": "test/StandardDelegationsModule.t.sol",
"test": "testCallFromCallboundDelegation",
"name": "register a callbound delegation",
"gasUsed": 117315
"gasUsed": 117420
},
{
"file": "test/StandardDelegationsModule.t.sol",
"test": "testCallFromCallboundDelegation",
"name": "call a system via a callbound delegation",
"gasUsed": 36583
"gasUsed": 36688
},
{
"file": "test/StandardDelegationsModule.t.sol",
"test": "testCallFromTimeboundDelegation",
"name": "register a timebound delegation",
"gasUsed": 111809
"gasUsed": 111914
},
{
"file": "test/StandardDelegationsModule.t.sol",
"test": "testCallFromTimeboundDelegation",
"name": "call a system via a timebound delegation",
"gasUsed": 26745
"gasUsed": 26815
},
{
"file": "test/UniqueEntityModule.t.sol",
"test": "testInstall",
"name": "install unique entity module",
"gasUsed": 675100
"gasUsed": 675275
},
{
"file": "test/UniqueEntityModule.t.sol",
Expand All @@ -231,7 +231,7 @@
"file": "test/UniqueEntityModule.t.sol",
"test": "testInstallRoot",
"name": "installRoot unique entity module",
"gasUsed": 642496
"gasUsed": 642601
},
{
"file": "test/UniqueEntityModule.t.sol",
Expand Down
22 changes: 11 additions & 11 deletions packages/world/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,37 +45,37 @@
"file": "test/BatchCall.t.sol",
"test": "testBatchCallFromReturnData",
"name": "call systems with batchCallFrom",
"gasUsed": 46377
"gasUsed": 46444
},
{
"file": "test/BatchCall.t.sol",
"test": "testBatchCallReturnData",
"name": "call systems with batchCall",
"gasUsed": 45171
"gasUsed": 45206
},
{
"file": "test/World.t.sol",
"test": "testCall",
"name": "call a system via the World",
"gasUsed": 12335
"gasUsed": 12370
},
{
"file": "test/World.t.sol",
"test": "testCallFromNamespaceDelegation",
"name": "call a system via a namespace fallback delegation",
"gasUsed": 26073
"gasUsed": 26143
},
{
"file": "test/World.t.sol",
"test": "testCallFromUnlimitedDelegation",
"name": "register an unlimited delegation",
"gasUsed": 47588
"gasUsed": 47623
},
{
"file": "test/World.t.sol",
"test": "testCallFromUnlimitedDelegation",
"name": "call a system via an unlimited delegation",
"gasUsed": 12771
"gasUsed": 12806
},
{
"file": "test/World.t.sol",
Expand All @@ -93,31 +93,31 @@
"file": "test/World.t.sol",
"test": "testRegisterFunctionSelector",
"name": "Register a function selector",
"gasUsed": 83114
"gasUsed": 83149
},
{
"file": "test/World.t.sol",
"test": "testRegisterNamespace",
"name": "Register a new namespace",
"gasUsed": 120817
"gasUsed": 120887
},
{
"file": "test/World.t.sol",
"test": "testRegisterRootFunctionSelector",
"name": "Register a root function selector",
"gasUsed": 80398
"gasUsed": 80433
},
{
"file": "test/World.t.sol",
"test": "testRegisterSystem",
"name": "register a system",
"gasUsed": 162559
"gasUsed": 162594
},
{
"file": "test/World.t.sol",
"test": "testRegisterTable",
"name": "Register a new table in the namespace",
"gasUsed": 637329
"gasUsed": 637399
},
{
"file": "test/World.t.sol",
Expand Down
8 changes: 4 additions & 4 deletions packages/world/src/SystemCall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ pragma solidity >=0.8.21;
import { Hook } from "@latticexyz/store/src/Hook.sol";

import { ResourceId, WorldResourceIdInstance } from "./WorldResourceId.sol";
import { WorldContextProvider } from "./WorldContext.sol";
import { WorldContextProviderLib } from "./WorldContext.sol";
import { AccessControl } from "./AccessControl.sol";
import { ROOT_NAMESPACE } from "./constants.sol";
import { WorldContextProvider } from "./WorldContext.sol";
import { WorldContextProviderLib } from "./WorldContext.sol";
import { revertWithBytes } from "./revertWithBytes.sol";
import { BEFORE_CALL_SYSTEM, AFTER_CALL_SYSTEM } from "./systemHookTypes.sol";

Expand Down Expand Up @@ -61,13 +61,13 @@ library SystemCall {

// Call the system and forward any return data
(success, data) = systemId.getNamespace() == ROOT_NAMESPACE // Use delegatecall for root systems (= registered in the root namespace)
? WorldContextProvider.delegatecallWithContext({
? WorldContextProviderLib.delegatecallWithContext({
msgSender: caller,
msgValue: value,
target: systemAddress,
callData: callData
})
: WorldContextProvider.callWithContext({
: WorldContextProviderLib.callWithContext({
msgSender: caller,
msgValue: value,
target: systemAddress,
Expand Down
4 changes: 2 additions & 2 deletions packages/world/src/World.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ResourceId, WorldResourceIdInstance } from "./WorldResourceId.sol";
import { ROOT_NAMESPACE_ID, ROOT_NAMESPACE, ROOT_NAME } from "./constants.sol";
import { AccessControl } from "./AccessControl.sol";
import { SystemCall } from "./SystemCall.sol";
import { WorldContextProvider } from "./WorldContext.sol";
import { WorldContextProviderLib } from "./WorldContext.sol";
import { revertWithBytes } from "./revertWithBytes.sol";
import { Delegation } from "./Delegation.sol";
import { requireInterface } from "./requireInterface.sol";
Expand Down Expand Up @@ -107,7 +107,7 @@ contract World is StoreData, IWorldKernel {
// Require the provided address to implement the IModule interface
requireInterface(address(module), MODULE_INTERFACE_ID);

WorldContextProvider.delegatecallWithContextOrRevert({
WorldContextProviderLib.delegatecallWithContextOrRevert({
msgSender: msg.sender,
msgValue: 0,
target: address(module),
Expand Down
59 changes: 44 additions & 15 deletions packages/world/src/WorldContext.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,12 @@ uint256 constant CONTEXT_BYTES = 20 + 32;
*/
abstract contract WorldContextConsumer is IWorldContextConsumer {
/**
* @notice Extracts the trusted msg.sender value from the appended calldata.
* @return sender The address of the trusted sender.
* @notice Extract the `msg.sender` from the context appended to the calldata.
* @return sender The `msg.sender` in the call to the World contract before the World routed the
* call to the WorldContextConsumer contract.
*/
function _msgSender() public view returns (address sender) {
assembly {
// Load 32 bytes from calldata at position calldatasize() - context size,
// then shift left 96 bits (to right-align the address)
// 96 = 256 - 20 * 8
sender := shr(96, calldataload(sub(calldatasize(), CONTEXT_BYTES)))
}
if (sender == address(0)) sender = msg.sender;
return WorldContextConsumerLib._msgSender();
}

/**
Expand All @@ -37,10 +32,7 @@ abstract contract WorldContextConsumer is IWorldContextConsumer {
* call to the WorldContextConsumer contract.
*/
function _msgValue() public pure returns (uint256 value) {
assembly {
// Load 32 bytes from calldata at position calldatasize() - 32 bytes,
value := calldataload(sub(calldatasize(), 32))
}
return WorldContextConsumerLib._msgValue();
}

/**
Expand All @@ -62,12 +54,49 @@ abstract contract WorldContextConsumer is IWorldContextConsumer {
}
}

library WorldContextConsumerLib {
/**
* @notice Extract the `msg.sender` from the context appended to the calldata.
* @return sender The `msg.sender` in the call to the World contract before the World routed the
* call to the WorldContextConsumer contract.
*/
function _msgSender() internal view returns (address sender) {
assembly {
// Load 32 bytes from calldata at position calldatasize() - context size,
// then shift left 96 bits (to right-align the address)
// 96 = 256 - 20 * 8
sender := shr(96, calldataload(sub(calldatasize(), CONTEXT_BYTES)))
}
if (sender == address(0)) sender = msg.sender;
}

/**
* @notice Extract the `msg.value` from the context appended to the calldata.
* @return value The `msg.value` in the call to the World contract before the World routed the
* call to the WorldContextConsumer contract.
*/
function _msgValue() internal pure returns (uint256 value) {
assembly {
// Load 32 bytes from calldata at position calldatasize() - 32 bytes,
value := calldataload(sub(calldatasize(), 32))
}
}

/**
* @notice Get the address of the World contract that routed the call to this WorldContextConsumer.
* @return The address of the World contract that routed the call to this WorldContextConsumer.
*/
function _world() internal view returns (address) {
return StoreSwitch.getStoreAddress();
}
}

/**
* @title WorldContextProvider - Utility functions to call contracts with context values appended to calldata.
* @title WorldContextProviderLib - Utility functions to call contracts with context values appended to calldata.
* @notice This library provides functions to make calls or delegatecalls to other contracts,
* appending the context values (like msg.sender and msg.value) to the calldata for WorldContextConsumer to consume.
*/
library WorldContextProvider {
library WorldContextProviderLib {
/**
* @notice Appends context values to the given calldata.
* @param callData The original calldata.
Expand Down
6 changes: 3 additions & 3 deletions packages/world/src/modules/core/CoreModule.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.21;

import { WorldContextProvider } from "../../WorldContext.sol";
import { WorldContextProviderLib } from "../../WorldContext.sol";
import { ROOT_NAMESPACE, ROOT_NAMESPACE_ID, WORLD_NAMESPACE_ID } from "../../constants.sol";
import { Module } from "../../Module.sol";

Expand Down Expand Up @@ -104,7 +104,7 @@ contract CoreModule is Module {
* @dev Uses the CoreSystem's `registerSystem` implementation to register itself on the World.
*/
function _registerCoreSystem() internal {
WorldContextProvider.delegatecallWithContextOrRevert({
WorldContextProviderLib.delegatecallWithContextOrRevert({
msgSender: _msgSender(),
msgValue: 0,
target: coreSystem,
Expand Down Expand Up @@ -148,7 +148,7 @@ contract CoreModule is Module {
for (uint256 i = 0; i < functionSignatures.length; i++) {
// Use the CoreSystem's `registerRootFunctionSelector` to register the
// root function selectors in the World.
WorldContextProvider.delegatecallWithContextOrRevert({
WorldContextProviderLib.delegatecallWithContextOrRevert({
msgSender: _msgSender(),
msgValue: 0,
target: coreSystem,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity >=0.8.21;
import { IModule, MODULE_INTERFACE_ID } from "../../../IModule.sol";
import { System } from "../../../System.sol";
import { AccessControl } from "../../../AccessControl.sol";
import { WorldContextProvider } from "../../../WorldContext.sol";
import { WorldContextProviderLib } from "../../../WorldContext.sol";
import { ResourceAccess } from "../../../codegen/tables/ResourceAccess.sol";
import { InstalledModules } from "../../../codegen/tables/InstalledModules.sol";
import { requireInterface } from "../../../requireInterface.sol";
Expand All @@ -25,7 +25,7 @@ contract ModuleInstallationSystem is System {
// Require the provided address to implement the IModule interface
requireInterface(address(module), MODULE_INTERFACE_ID);

WorldContextProvider.callWithContextOrRevert({
WorldContextProviderLib.callWithContextOrRevert({
msgSender: _msgSender(),
msgValue: 0,
target: address(module),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { ROOT_NAMESPACE, ROOT_NAME } from "../../../constants.sol";
import { AccessControl } from "../../../AccessControl.sol";
import { requireInterface } from "../../../requireInterface.sol";
import { revertWithBytes } from "../../../revertWithBytes.sol";
import { WorldContextProvider } from "../../../WorldContext.sol";
import { WorldContextProviderLib } from "../../../WorldContext.sol";

import { NamespaceOwner } from "../../../codegen/tables/NamespaceOwner.sol";
import { ResourceAccess } from "../../../codegen/tables/ResourceAccess.sol";
Expand Down
Loading

0 comments on commit 88b1a5a

Please sign in to comment.