@latticexyz/gas-report
Advanced tools
Changelog
Version 2.0.0-next.5
refactor(world): separate call utils into WorldContextProvider
and SystemCall
(#1370) (@latticexyz/world)
The previous Call.withSender
util is replaced with WorldContextProvider
, since the usecase of appending the msg.sender
to the calldata is tightly coupled with WorldContextConsumer
(which extracts the appended context from the calldata).
The previous Call.withSender
utility reverted if the call failed and only returned the returndata on success. This is replaced with callWithContextOrRevert
/delegatecallWithContextOrRevert
-import { Call } from "@latticexyz/world/src/Call.sol";
+import { WorldContextProvider } from "@latticexyz/world/src/WorldContext.sol";
-Call.withSender({
- delegate: false,
- value: 0,
- ...
-});
+WorldContextProvider.callWithContextOrRevert({
+ value: 0,
+ ...
+});
-Call.withSender({
- delegate: true,
- value: 0,
- ...
-});
+WorldContextProvider.delegatecallWithContextOrRevert({
+ ...
+});
In addition there are utils that return a bool success
flag instead of reverting on errors. This mirrors the behavior of Solidity's low level call
/delegatecall
functions and is useful in situations where additional logic should be executed in case of a reverting external call.
library WorldContextProvider {
function callWithContext(
address target, // Address to call
bytes memory funcSelectorAndArgs, // Abi encoded function selector and arguments to pass to pass to the contract
address msgSender, // Address to append to the calldata as context for msgSender
uint256 value // Value to pass with the call
) internal returns (bool success, bytes memory data);
function delegatecallWithContext(
address target, // Address to call
bytes memory funcSelectorAndArgs, // Abi encoded function selector and arguments to pass to pass to the contract
address msgSender // Address to append to the calldata as context for msgSender
) internal returns (bool success, bytes memory data);
}
WorldContext
is renamed to WorldContextConsumer
to clarify the relationship between WorldContextProvider
(appending context to the calldata) and WorldContextConsumer
(extracting context from the calldata)
-import { WorldContext } from "@latticexyz/world/src/WorldContext.sol";
-import { WorldContextConsumer } from "@latticexyz/world/src/WorldContext.sol";
The World
contract previously had a _call
method to handle calling systems via their resource selector, performing accesss control checks and call hooks registered for the system.
library SystemCall {
/**
* Calls a system via its resource selector and perform access control checks.
* Does not revert if the call fails, but returns a `success` flag along with the returndata.
*/
function call(
address caller,
bytes32 resourceSelector,
bytes memory funcSelectorAndArgs,
uint256 value
) internal returns (bool success, bytes memory data);
/**
* Calls a system via its resource selector, perform access control checks and trigger hooks registered for the system.
* Does not revert if the call fails, but returns a `success` flag along with the returndata.
*/
function callWithHooks(
address caller,
bytes32 resourceSelector,
bytes memory funcSelectorAndArgs,
uint256 value
) internal returns (bool success, bytes memory data);
/**
* Calls a system via its resource selector, perform access control checks and trigger hooks registered for the system.
* Reverts if the call fails.
*/
function callWithHooksOrRevert(
address caller,
bytes32 resourceSelector,
bytes memory funcSelectorAndArgs,
uint256 value
) internal returns (bytes memory data);
}
System hooks now are called with the system's resource selector instead of its address. The system's address can still easily obtained within the hook via Systems.get(resourceSelector)
if necessary.
interface ISystemHook {
function onBeforeCallSystem(
address msgSender,
- address systemAddress,
+ bytes32 resourceSelector,
bytes memory funcSelectorAndArgs
) external;
function onAfterCallSystem(
address msgSender,
- address systemAddress,
+ bytes32 resourceSelector,
bytes memory funcSelectorAndArgs
) external;
}
feat(world): add support for upgrading systems (#1378) (@latticexyz/world)
It is now possible to upgrade systems by calling registerSystem
again with an existing system id (resource selector).
// Register a system
world.registerSystem(systemId, systemAddress, publicAccess);
// Upgrade the system by calling `registerSystem` with the
// same system id but a new system address or publicAccess flag
world.registerSystem(systemId, newSystemAddress, newPublicAccess);
feat(world): add callFrom entry point (#1364) (@latticexyz/world)
The World
has a new callFrom
entry point which allows systems to be called on behalf of other addresses if those addresses have registered a delegation.
If there is a delegation, the call is forwarded to the system with delegator
as msgSender
.
interface IBaseWorld {
function callFrom(
address delegator,
bytes32 resourceSelector,
bytes memory funcSelectorAndArgs
) external payable virtual returns (bytes memory);
}
A delegation can be registered via the World
's registerDelegation
function.
If delegatee
is address(0)
, the delegation is considered to be a "fallback" delegation and is used in callFrom
if there is no delegation is found for the specific caller.
Otherwise the delegation is registered for the specific delegatee
.
interface IBaseWorld {
function registerDelegation(
address delegatee,
bytes32 delegationControl,
bytes memory initFuncSelectorAndArgs
) external;
}
The delegationControl
refers to the resource selector of a DelegationControl
system that must have been registered beforehand.
As part of registering the delegation, the DelegationControl
system is called with the provided initFuncSelectorAndArgs
.
This can be used to initialize data in the given DelegationControl
system.
The DelegationControl
system must implement the IDelegationControl
interface:
interface IDelegationControl {
function verify(address delegator, bytes32 systemId, bytes calldata funcSelectorAndArgs) external returns (bool);
}
When callFrom
is called, the World
checks if a delegation is registered for the given caller, and if so calls the delegation control's verify
function with the same same arguments as callFrom
.
If the call to verify
is successful and returns true
, the delegation is valid and the call is forwarded to the system with delegator
as msgSender
.
Note: if UNLIMITED_DELEGATION
(from @latticexyz/world/src/constants.sol
) is passed as delegationControl
, the external call to the delegation control contract is skipped and the delegation is considered valid.
For examples of DelegationControl
systems, check out the CallboundDelegationControl
or TimeboundDelegationControl
systems in the std-delegations
module.
See StandardDelegations.t.sol
for usage examples.
feat(world): allow transferring ownership of namespaces (#1274) (@latticexyz/world)
It is now possible to transfer ownership of namespaces!
// Register a new namespace
world.registerNamespace("namespace");
// It's owned by the caller of the function (address(this))
// Transfer ownership of the namespace to address(42)
world.transferOwnership("namespace", address(42));
// It's now owned by address(42)
fix(services): correctly export typescript types (#1377) (@latticexyz/services)
Fixed an issue where the TypeScript types for createFaucetService were not exported correctly from the @latticexyz/services package
feat: docker monorepo build (#1219) (@latticexyz/services)
The build phase of services now works on machines with older protobuf compilers
refactor: remove v1 network package, remove snap sync module, deprecate std-client (#1311) (@latticexyz/common, @latticexyz/store, @latticexyz/world)
TightCoder
libraryisLeftAligned
and getLeftPaddingBits
common codegen helpersfix(cli): make mud test exit with code 1 on test error (#1371) (@latticexyz/cli)
The mud test
cli now exits with code 1 on test failure. It used to exit with code 0, which meant that CIs didn't notice test failures.