Launching Catapult: Declarative and Composable Smart Contract Deployments
Catapult is a YAML‑first deployment runner that feels like CI for smart contracts. You describe what needs to exist; Catapult figures out how to make it true deterministically across every network you point it at.

At Sequence, we’ve believed from day one that crypto is multi‑chain. Not just co‑existing L1s, but an ecosystem of L2s and L3s riding on Ethereum. That’s why our whole stack ships with multi‑chain as a design pillar: light‑state‑sync to mirror wallet config across networks, and first‑class support for 50+ testnets and mainnets (and climbing).
Multi‑chain at Sequence has always had two sides:
- Off‑chain services we operate (indexer, relayer, metadata, etc.)
- On‑chain contracts that must be deployed and configured correctly on every network
For years we carried around “the deployment script.” We’ve done it all; Truffle, Hardhat (hi, Buidler), Foundry... with bespoke glue code per project. It worked, until it didn’t. Verification took extra steps, logs and reports lived in random places, and every new chain felt like re‑teaching a machine the same dance.
We wanted something different: declarative, hermetic, repeatable. No fragile plugin towers. If you have a build, you should be able to reproduce the deployment, anywhere, as many times as needed.
So we built Catapult.
Catapult is a YAML‑first deployment runner that feels like CI for smart contracts. You describe what needs to exist; Catapult figures out how to make it true deterministically across every network you point it at.
Why Catapult (and why now)
- Declarative, not imperative. Blueprints over scripts. You define target state; Catapult compiles a plan.
- Hermetic & repeatable. Artifacts in, transactions out. No framework‑specific plugins required.
- Idempotent by design. If the thing already exists at the address you expect, Catapult skips the work and records the outputs.
- Composable. Jobs call templates; templates call actions; everything can depend on everything (safely) through a dependency graph Catapult builds for you.
If you’re shipping to many chains, this is the way.
Mental model
Think of Catapult as a CI runner for contracts:
- Jobs are the tasks (e.g.,
deploy-sequence-v1
,setup-token-factory
). - Templates are reusable blueprints (e.g., “deploy via ERC‑2470,” “verify on Etherscan/Sourcify”).
- Actions are the atomic steps (send tx, call a template, verify bytecode, write output).
- Value resolver lets any YAML value be computed at runtime via
{{ ... }}
: ABI‑encode, compute CREATE2 addresses, read previous outputs, do basic math, etc. - Dependency graph is inferred automatically from
depends_on
and value references.
Result: you add a network RPC, run the job, and get the same state everywhere.
Jobs (your deployment plan)
Jobs declare what should happen and in which order. Here’s a minimal example that deploys a ValueForwarder
via a singleton factory (ERC‑2470), then verifies it:
name: "value-forwarder"
version: "1"
description: "ValueForwarder contract for forwarding value to other addresses"
actions:
- name: "value-forwarder"
template: "erc-2470"
arguments:
salt: "{{salt-zero}}"
creationCode: "{{Contract(./build-info/ValueForwarder.json:ValueForwarder).creationCode}}"
output: true
- name: "verify-value-forwarder"
template: "verify-contract"
depends_on: ["value-forwarder"]
arguments:
address: "{{value-forwarder.address}}"
contract: "{{Contract(./build-info/ValueForwarder.json:ValueForwarder)}}"
Catapult builds an internal contract repository for each project from your build-info
/artifacts
so jobs can reference contracts by name, not file paths.
$ catapult list contracts
- ValueForwarder (test/mocks/ValueForwarder.sol)
Unique Hash: 47a54182c5...a3ac6fc
Build Info ID: 2446f63c5bf18eb3
Sources: jobs/relayer/build-info/ValueForwarder.json
- Factory (contracts/Factory.sol)
Unique Hash: 6582461549...d5f6302
Build Info ID: sequence-factory-v1
Sources: jobs/sequence_v1/build-info/sequence-factory-v1.json
With a build-info
present, Catapult can verify on Etherscan (v2) and Sourcify without you writing extra glue.
Templates (reuse, don’t re‑code)
Multi‑chain teams usually lean on Nick’s Method to get the same address across chains. In practice, most protocols don’t hand‑craft pre‑signed txs for every contract; they deploy a factory once (via Nick’s Method) and have it CREATE2 everything else. There are many flavors here: CreateX, ERC‑2470 (SingletonFactory), Nano deployers, DDP, and niche ones you’ve never heard of… yet.
Rather than hard‑coding support, Catapult uses templates that can live inside or outside your project. Define them once, reuse forever.
name: "assured-deployment"
type: "template"
arguments:
targetAddress: { type: "address" } # Expected result (e.g., CREATE2)
factoryAddress:{ type: "address" } # Deployer/factory contract
callData: { type: "bytes" } # ABI-encoded call
actions:
- type: "create-contract"
arguments:
data:
type: "abi-pack"
arguments:
types: ["bytes","address","address","bytes"]
values: [
"0x383d8039602c5160601c3d813b60295780806054380360548260405160601c5af150903b60295780fd5b80f3", # checked-call.huff
"{{targetAddress}}",
"{{factoryAddress}}",
"{{callData}}"
]
You can also make templates idempotent with skip conditions (e.g., “skip if bytecode already at computed CREATE2 address”) and still compute the outputs so downstream jobs keep working.
Under the hood
- Deterministic addressing. Compute CREATE2 addresses up front and verify results post‑deploy.
- Graph‑aware execution.
depends_on
and value references build the DAG for you. - Dry runs. Validate the entire plan without sending a tx:
catapult dry-run
. - Clean outputs. Results are grouped across networks when identical, so your
output/
stays readable. - Network filters.
only_networks
/skip_networks
per job when you need to scope changes. - Standard library. Battle‑tested templates like
erc-2470
,sequence-universal-deployer-2
, and verification helpers to get you shipping fast.
Quickstart
It takes a few seconds to get started:
# Install
npm install -g @0xsequence/catapult
# Peek at what Catapult sees
catapult list contracts
catapult list jobs
catapult list templates
# Sanity check
catapult dry-run
# Deploy everywhere in networks.yaml
export PRIVATE_KEY=0x...
export ETHERSCAN_API_KEY=...
catapult run
# Or pin to a chain
catapult run --network "Arbitrum Sepolia"
Built for builders
Catapult grew out of the reality of running Sequence across dozens of chains. It turned our deployment chaos into a repeatable, auditable pipeline; the same way CI turned ad‑hoc shell scripts into pipelines.
If you manage contracts on more than one network, this is probably the tool you wanted before you knew to name it.
- GitHub: https://github.com/0xsequence/catapult
- NPM:
@0xsequence/catapult
- Real‑world usage: https://github.com/0xsequence/live-contracts