System hooks
This page is about hooks that are called before or after a System call. You can also use store
hooks that are called whenever information in a table is modified, regardless of the source of
the change.
The namespace owner can register (opens in a new tab) hooks that are called before and/or after calls to a specific System.
System hook contracts
A system hook contract is a contract that implements the ISystemHook (opens in a new tab) interface.
This interface requires the implementation of two functions.
- onBeforeCallSystem, which is called before the actual call.
- onAfterCallSystem, which is called afterward.
- supportsInterface, which is part of IEP-165 (opens in a new tab) used to specify which interfaces are supported by a contract.
To have the correct supportsInterface you can inherit from SystemHook (opens in a new tab).
Sample code
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.24;
 
import { Script } from "forge-std/Script.sol";
import { console } from "forge-std/console.sol";
 
import { IWorld } from "../src/codegen/world/IWorld.sol";
 
import { SystemHook } from "@latticexyz/world/src/SystemHook.sol";
 
import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol";
import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol";
import { BEFORE_CALL_SYSTEM, AFTER_CALL_SYSTEM } from "@latticexyz/world/src/systemHookTypes.sol";
 
contract JustSayNo is SystemHook {
  function onBeforeCallSystem(address msgSender, ResourceId systemId, bytes memory callData) external {
    return;
  }
 
  function onAfterCallSystem(address msgSender, ResourceId systemId, bytes memory callData) external {
    revert("Just say no");
  }
}
 
contract SystemHookDeploy is Script {
  function run() external {
    address worldAddress = 0xC14fBdb7808D9e2a37c1a45b635C8C3fF64a1cc1;
 
    // Load the private key from the `PRIVATE_KEY` environment variable (in .env)
    uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
 
    // Start broadcasting transactions from the deployer account
    vm.startBroadcast(deployerPrivateKey);
 
    // Deploy JustSayNo
    JustSayNo justSayNo = new JustSayNo();
    console.log(address(justSayNo));
 
    ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "", name: "TasksSystem" });
 
    IWorld(worldAddress).registerSystemHook(systemId, justSayNo, AFTER_CALL_SYSTEM);
 
    vm.stopBroadcast();
  }
}Explanation
import { SystemHook } from "@latticexyz/world/src/SystemHook.sol";The system hook contract inherits from SystemHook.
import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol";
import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol";We need to create the resource of the System for which we register a hook.
import { BEFORE_CALL_SYSTEM, AFTER_CALL_SYSTEM } from "@latticexyz/world/src/systemHookTypes.sol";We need these constants to specify when the hook applies.
contract JustSayNo is SystemHook {
 
  function onBeforeCallSystem(address msgSender, ResourceId systemId, bytes memory callData) external {
    return ;
  }
 
  function onAfterCallSystem(address msgSender, ResourceId systemId, bytes memory callData) external {This is the system hook contract. It has two functions:
- onBeforeCallSystem, which is executed before the call
- onAfterCallSystem, which is executed after the call
Both functions get the sender, the system being called, and the call data it receives.
    revert("Just say no");
  }
}This hook disables the System by causing all calls to revert.
contract SystemHookDeploy is Script {
  function run() external {
   ...This is the function that the script executes.
    // Deploy JustSayNo
    JustSayNo justSayNo = new JustSayNo();Deploy the system hook contract.
    ResourceId systemId = WorldResourceIdLib.encode(
      { typeId: RESOURCE_SYSTEM,
        namespace: "",
        name: "TasksSystem"
      });Create the resource ID for the System we are disabling.
    IWorld(worldAddress)
        .registerSystemHook(systemId, justSayNo, AFTER_CALL_SYSTEM);
  }
}Register the system hook.