diff --git a/docs/pages/config.mdx b/docs/pages/config.mdx index e87a499fa9..d251fd99ad 100644 --- a/docs/pages/config.mdx +++ b/docs/pages/config.mdx @@ -121,3 +121,7 @@ The global configuration keys are all optional. - **`worldsFile`** a `string`: JSON file for the chain to `World` deploy address mapping. The default is `./worlds.json`. + + - + **`upgradeableWorldImplementation`** a `bool`: Whether the `World` is to be deployed behind a proxy to [enable upgrades + of the core World implementation](/world/upgrade). The default is `false`. diff --git a/docs/pages/world/_meta.js b/docs/pages/world/_meta.js index 655c9a21d5..506ec2a1df 100644 --- a/docs/pages/world/_meta.js +++ b/docs/pages/world/_meta.js @@ -9,6 +9,7 @@ export default { balance: "Balance", "account-delegation": "Account Delegation", "batch-calls": "Batch Calls", + "upgrade": "Upgrading", modules: "Modules", reference: "Reference", }; diff --git a/docs/pages/world/upgrade.mdx b/docs/pages/world/upgrade.mdx new file mode 100644 index 0000000000..fc3ea7597d --- /dev/null +++ b/docs/pages/world/upgrade.mdx @@ -0,0 +1,95 @@ +import { CollapseCode } from "../../components/CollapseCode"; +import { Callout } from "nextra/components"; + +# Upgrading worlds + +The [`System`s](./systems) can be upgraded without changing the underlying `World` code. +However, if the `World` was deployed [behind a proxy](/config#upgradeableWorldImplementation) it is also possible to upgrade the `World` itself. +This allows you to upgrade to a future version of MUD, but adds some gas overhead for all calls (due to one more level of indirection). + +## Are upgrades possible? + +As per [ERC-1967](https://eips.ethereum.org/EIPS/eip-1967#logic-contract-address), the storage slot `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` stores the address of the `World` implementation in a proxy. +So to identify if a `World` is deployed behind a proxy run these commands: + +```sh copy +WORLD_ADDRESS=0xbe6b85dc88f969e45d8d8ae128c5a9c9744d6464 +cast implementation $WORLD_ADDRESS +``` + +If the answer is anything other than zero, the `World` is behind a proxy and can be upgraded. + +## Performing an upgrade + +To upgrade the `World` use these steps in a `package/contracts` directory: + +1. Edit `.env` to add `WORLD_ADDRESS` with the address displayed by MUD Dev Tools. + For example, you might want to use this file: + + + + ```sh filename=".env" showLineNumbers copy {12} + # This .env file is for demonstration purposes only. + # + # This should usually be excluded via .gitignore and the env vars attached to + # your deployment environment, but we're including this here for ease of local + # development. Please do not commit changes to this file! + # + # Enable debug logs for MUD CLI + DEBUG=mud:* + # + # Anvil default private key: + PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + WORLD_ADDRESS=0xbe6b85dc88f969e45d8d8ae128c5a9c9744d6464 + ``` + + + +1. Create this script in `scripts/UpgradeWorld.s.sol`. + + + + ```solidity filename="UpgradeWorld.s.sol" copy showLineNumbers {18,23} + // SPDX-License-Identifier: MIT + pragma solidity >=0.8.24; + + import { Script } from "forge-std/Script.sol"; + import { console } from "forge-std/console.sol"; + + import { World } from "@latticexyz/world/src/World.sol"; + import { WorldProxy } from "@latticexyz/world/src/WorldProxy.sol"; + + contract SetImplementation is Script { + function run() external { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + address proxyAddress = vm.envAddress("WORLD_ADDRESS"); + + // Deploy new world implementation + World newWorld = new World(); + + console.log("proxy:", proxyAddress); + console.log("new World:", address(newWorld)); + + WorldProxy(payable(proxyAddress)).setImplementation(address(newWorld)); + + vm.stopBroadcast(); + } + } + ``` + + + +1. Run the script. + + ```sh copy + forge script script/UpgradeWorld.s.sol --rpc-url http://localhost:8545 --broadcast + ``` + +1. See the new address. + + ```sh copy + source .env + cast implementation $WORLD_ADDRESS + ```