Examples
Test Deploy

Simulating World Extension Deployment

The commented code can be found in packages/contracts/script/RegisterReadDemoSystem.s.sol (opens in a new tab).

Code

examples/ReadDemo/packages/contracts/script/RegisterReadDemoSystem.s.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.24;
 
import { Script } from "forge-std/Script.sol";
import { console2 } from "forge-std/Test.sol";
 
import { WorldRegistrationSystem } from "@latticexyz/world/src/modules/init/implementations/WorldRegistrationSystem.sol";
import { System } from "@latticexyz/world/src/System.sol";
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
import { WorldResourceIdLib } from "@latticexyz/world/src/WorldResourceId.sol";
import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol";
import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol";
 
import { ReadDemoSystem } from "../src/systems/ReadDemoSystem.sol";
 
contract RegisterReadDemoSystem is Script {
 
  address worldAddress = vm.envAddress("WORLD_ADDRESS");
  uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY_ALICE");
  address playerAddress = vm.envAddress("ADDRESS_PLAYER");
 
  bytes14 namespace = bytes14("PluginExamples");
  bytes16 system = bytes16("ReadDemoSystem");
 
  function run() external {
    StoreSwitch.setStoreAddress(worldAddress);
 
    WorldRegistrationSystem world = WorldRegistrationSystem(worldAddress);
 
    ResourceId namespaceResource = WorldResourceIdLib.encodeNamespace(bytes14(namespace));
    ResourceId systemResource = WorldResourceIdLib.encode(RESOURCE_SYSTEM, namespace, system);
 
    vm.startBroadcast(deployerPrivateKey);
 
    // check if the namespace already exists
    // if you own the namespace, you can change/deregister it via other code
    // if you do not own the namespace but it is already registered, you will need to change your namespace
    bool existingNamespaceCheck = ResourceIds.getExists(namespaceResource);
    require(!existingNamespaceCheck, "Namespace already exists.");
 
    world.registerNamespace(namespaceResource);
 
    ReadDemoSystem readDemoSystem = new ReadDemoSystem();
 
    world.registerSystem(systemResource, readDemoSystem, true);
    world.registerFunctionSelector(systemResource, "readMainBaseLevel()");
 
    vm.stopBroadcast();
  }
}

This should look incredibly familiar. Most of the code is identical to the setUp() function of our tests.

Deploying your extension looks much like testing your extension, but occurs in a script. Most of the code is identical to the test, which is kind of the point. Test thoroughly before deploying; deployments are permanent.

Key differences are:

  • This is a Script, not a MudTest.
    • Tests (and MudTests) use vm cheatcodes like startPrank to execute a local simulation. Nothing is impacted on the live chain
    • Scripts can read from and broadcast to the live chain, causing permanent changes.
  • We must declare and specify the WORLD_ADDRESS variable; it is not inherited from MudTest.
  • When deploying, you must use a PRIVATE_KEY in .env, since this action will cost gas.
  • Writing to the chain requires startBroadcast() instead of startPrank()
  • You can do a simulation of a deployment with the following command:
forge script script/RegisterReadDemoSystem.s.sol --fork-url https://primodium-sepolia.rpc.caldera.xyz/http