Zeus manages complex deploy processes for onchain software.
You may find Zeus useful if:
- You use forge,
forge create
orforge script
to deploy your projects. - You use multiple multisigs to deploy your onchain software. (i.e for permissioned proxy/implementation upgrades)
- You have multiple deploy environments (i.e. testnet vs mainnet) and want to automatically track where your contracts are deployed.
- Zeus upgrade scripts are "write once, run anywhere". No more writing a "holesky" script, and then a "mainnet" script.
Zeus integrates with forge
, and adds:
- Expressing your transactions, meant for a multisig, as a forge script.
- Managing the lifecycle of your deploys across multiple environments. (
zeus deploy status
) - Tracking deployed contracts across multiple environments. (
zeus which MyContract
) - Testing your upgrade scripts (
zeus test
) - Running binaries which require contract addresses (without hardcoding addresses) (
zeus run
) - Generating a paper trail of all deploys, logs, and artifacts generated.
- Node 22 (
node --version
to check) forge
- Create a new Github repository, and install the Zeus Deployer app.
npm install -g @layr-labs/zeus
zeus login
zeus init
-- when prompted for your metadata repo, provide the repo from step 0.zeus env new
-- create your first environment to deploy your contracts into.
Check out our examples here: zeus-examples.
Here are some common things to do with Zeus:
See the "How to write upgrades" section.
Every upgrade script you write will (hopefully) have tests in it. You can run those scripts as tests
by using zeus test
.
zeus test --env <env> ./path/to/upgrade/script.s.sol
(NOTE: this accepts a glob / multiple arguments)
zeus env show <env>
(view all contracts, environment parameters, etc. for a given environment)
-
See if your upgrade is available to run in your environment:
zeus upgrade list --env <env>
-
If it's there, great. If it's not, your environment is either on the wrong version OR you didn't register your upgrade.
To see if you registered your upgrade at all, check:
zeus upgrade list
If your upgrade isn't in that list, you need to register it. Make sure you're on the correct commit you want everyone to run your upgrade from, and then run;
zeus upgrade register
and follow the on-screen instructions.
-
Start your deploy!
zeus deploy run --upgrade <directory name> --env <env>
NOTE:directory name
is what Zeus uses right now to identify upgrades.
-
Your deploy may halt periodically in between steps. You can resume your deploy with:
zeus deploy run --resume --env <env>
- While a deploy is ongoing, you can run:
zeus deploy verify --env <env>
To verify that the contracts this deploy claims to have produced match what is available in the repository.
- Zeus uses an algorithm that compares your local bytecode, with immutableReferences zero'd out, against bytecode that is available onchain (with the same bytecode segments zero'd out).
Tip
Make sure you double check your foundry version (forge --version) before doing this. Differences in forge versions have been known to affect hash calculations.
Note
If you are logged in and have write access to the ZEUS_HOST, you will automatically post a small commit indicating that you verified those contracts locally.
-
You may be able to cancel a deploy, depending on what state it is in.
zeus deploy cancel --env <env>
For multisig transactions, Zeus will attempt to propose an alternate null transaction to overwrite the nonce onchain. EOA transactions are not cancellable if they have been executed.
-
Zeus environments maintain two things:
- A set of scalar parameters. You can modify these overtime, using the methods exposed in the base Zeus script.
- A set of contract addresses. These evolve over time when you invoke
deploySingleton()
ordeployInstance()
((see here)[https://github.com/Layr-Labs/zeus-templates/blob/master/test/ZeusScript.test.sol#L46]).
Generally, scalar parameters should be read only. If you find yourself modifying scalar parameters, you should probably be tracking that value onchain!
-
Zeus upgrades will apply any changes to the environment (contracts or parameters) ONLY if the entire deploy is successful (i.e all steps up to and including the final step of the upgrade succeed)
- In the case of a failure, cancellation, or other abort, the environment in zeus will not reflect any updated parameters.
forge install Layr-Labs/zeus-templates
- Create a new upgrade, under your upgrades directory (see
.zeus
in your repo for the directory name). - Your upgrade is a directory that should contain:
- One or more upgrade scripts.
- An upgrade manifest (example).
{
"name": "my-upgrade-name", // the name of this upgrade
"from": ">=0.0.0 <=0.5.1", // must be a valid semver version constraint
"to": "0.5.2", // the version you are upgrading to
"phases": [ // each phase corresponds to a script you intend to run
{
"type": "eoa", // subclasses "EOADeployer" in the contract.
"filename": "1-eoa.s.sol" // the name of the contract.
},
{
"type": "multisig", // subclasses "MultisigBuilder" in the contract.
"filename": "2-multisig.s.sol"
},
{
"type": "multisig",
"filename": "3-multisig.s.sol" // etc.
}
]
}
- Once you've written your upgrade, confirm that any tests you've added in the file pass. Any
test*
prefixed functions are run example.
zeus test --env MyFirstEnv ./path/to/my/script.s.sol
- Now, register your upgrade with zeus. Zeus keeps a record of the commit that your upgrade belongs to, so that all parties execute on the same commit. You can move this later by re-running the command.
From your project's root directory:
zeus upgrade register
.
- If your environment is ready to run this upgrade, you should be able to see it now!
zeus upgrade list --env MyFirstEnv
-
Deploying a contract with an EOA
- In this example, we specify that any EOA can be used to run the following transaction, by extending from
EOADeployer
.
- In this example, we specify that any EOA can be used to run the following transaction, by extending from
-
Expressing a multisig transaction
- In this example, we use a special multisig to queue a protocol upgrade using our OpenZeppelin Timelock controller.
See CONTRIBUTING.md.
See LICENSE.