⚠️ UNDER HEAVY DEVELOPMENT ⚠️
This documentation is actively being developed and may change frequently.
Introduction
Kurtosis Devnet is a development and testing environment for Optimism devnets, providing a local development setup for testing and validating L2 functionality. This environment is built around Kurtosis, adding convenience features for dev-oriented features.
Getting Started
To use Kurtosis Devnet, you'll need:
- A Docker daemon (Docker Desktop or any drop-in replacement)
- Kurtosis installed on your system
Detailed setup instructions and usage examples can be found in the following chapters of this documentation.
Use Cases
The Kurtosis DevNet is particularly useful for:
- Protocol developers working on Optimism
- Smart contract developers testing L2 functionality
- Engineers validating cross-chain interactions
This documentation will guide you through setting up, using, and extending Kurtosis Devnet for your development needs.
Basic Deployment
The Kurtosis devnet provides several pre-configured devnet templates and convenient commands to deploy and interact with them.
Built-in Devnets
The following devnet templates are available out of the box:
-
Simple Devnet (
simple.yaml
)- Basic single-chain setup
- Ideal for local development and testing
- Deploy with:
just simple-devnet
-
Interop Devnet (
interop.yaml
)- Designed for interop testing
- Includes test suite for cross-chain interactions
- Deploy with:
just interop-devnet
- Run tests with:
just interop-devnet-test
-
Pectra Devnet (
pectra.yaml
)- Specialized configuration for Pectra testing
- Deploy with:
just pectra-devnet
User-Defined Devnets (Experimental)
Note: User-defined devnets are an experimental feature and not actively supported at this time. Use at your own risk.
The user devnet template (user.yaml
) allows for customizable devnet configurations through a JSON input file. This feature is designed to simplify devnet creation for future devnet-as-a-service scenarios.
Deployment
just user-devnet <data-file>
Example Configuration
Here's an example of a user devnet configuration file:
{
"interop": true,
"l2s": {
"2151908": {
"nodes": ["op-geth", "op-geth"]
},
"2151909": {
"nodes": ["op-reth"]
}
},
"overrides": {
"flags": {
"log_level": "--log.level=debug"
}
}
}
This configuration:
- Enables interop testing features
- Defines two L2 chains:
- Chain
2151908
with twoop-geth
nodes - Chain
2151909
with oneop-reth
node
- Chain
- Sets custom logging level for all nodes
Deployment Commands
Arbitrary devnets can be deployed using the general devnet
command with the following syntax:
just devnet <template-file> [data-file] [name]
Where:
template-file
: The YAML template to use (e.g.,simple.yaml
)data-file
: Optional JSON file with configuration dataname
: Optional custom name for the devnet (defaults to template name)
For example:
# Deploy simple devnet with default name
just devnet simple.yaml
# Deploy user devnet with custom data and name
just devnet user.yaml my-config.json my-custom-devnet
This can be convenient when experimenting with devnet definitions
Entering a Devnet Shell
The devnet provides a powerful feature to "enter" a devnet environment, which sets up the necessary environment variables for interacting with the chains.
Basic Usage
just enter-devnet <devnet-name> [chain-name]
Where:
devnet-name
: The name of your deployed devnetchain-name
: Optional chain to connect to (defaults to "Ethereum")
Example:
# Enter the Ethereum chain environment in the simple devnet
just enter-devnet simple-devnet
# Enter a specific chain environment
just enter-devnet my-devnet l2-chain
# Use exec to replace the current shell process (recommended)
exec just enter-devnet my-devnet l2-chain
Note: The enter feature creates a new shell process. To avoid accumulating shell processes, you can use the exec
command, which replaces the current shell with the new one. This is especially useful in scripts or when you want to maintain a clean process tree.
Features of the Devnet Shell
When you enter a devnet shell, you get:
- All necessary environment variables set for the chosen chain
- Integration with tools like
cast
for blockchain interaction - Chain-specific configuration and endpoints
- A new shell session with the devnet context
The shell inherits your current environment and adds:
- Chain-specific RPC endpoints
- Network identifiers
- Authentication credentials (if any)
- Tool configurations
To exit the devnet shell, simply type exit
or press Ctrl+D
.
Environment Variables
The devnet shell automatically sets up environment variables needed for development and testing:
ETH_RPC_URL
: The RPC endpoint for the selected chainETH_RPC_JWT_SECRET
: JWT secret for authenticated RPC connections (when cast integration is enabled)DEVNET_ENV_URL
: The URL or absolute path to the devnet environment fileDEVNET_CHAIN_NAME
: The name of the currently selected chain
These variables are automatically picked up by tools like cast
, making it easy to interact with the chain directly from the shell.
AUTOFIX Feature
The devnet includes an AUTOFIX feature that helps recover from failed devnet deployments by automatically cleaning up the environment. It has two modes:
-
Normal Mode (
AUTOFIX=true
)- Cleans up stopped or empty enclaves
- Removes associated Docker resources (containers, volumes, networks)
- Preserves running enclaves
- Good for fixing minor deployment issues
-
Nuke Mode (
AUTOFIX=nuke
)- Completely resets the Kurtosis environment
- Removes all enclaves and associated Docker resources
- Use when you need a fresh start
How AUTOFIX Works
AUTOFIX operates by:
- Checking the status of the enclave (running, stopped, or empty)
- For stopped or empty enclaves in normal mode:
- Removes the enclave
- Cleans up potential kurtosis Docker resources
- For nuke mode:
- Removes all enclaves
- Cleans up all potential kurtosis Docker resources
Usage
# For normal cleanup
AUTOFIX=true just devnet simple.yaml
# For complete reset
AUTOFIX=nuke just devnet simple.yaml
Note: Nuke mode will stop all running enclaves, so use it carefully.
Troubleshooting
If you encounter issues with older Kurtosis versions, you can use AUTOFIX to recover:
# For normal cleanup
AUTOFIX=true just devnet simple.yaml
# For complete reset
AUTOFIX=nuke just devnet simple.yaml
Alternatively, you can manually clean up Docker resources:
# Remove old Kurtosis containers
docker rm -f $(docker ps -aqf "name=kurtosis-*")
# Clean up dangling networks
docker network rm -f $(docker network ls -qf "name=kt-*")
Local Artifacts Integration
The Kurtosis devnet provides powerful templating capabilities that allow you to seamlessly integrate locally built artifacts (Docker images, smart contracts, and prestates) into your devnet configuration. This integration is managed through a combination of Go-based builders and YAML templates.
Component Eligibility
Not all components can be built locally. Only components that are part of the Optimism monorepo can be built using the local artifact system. Here's a breakdown:
Buildable Components
Components that can be built locally include:
op-node
op-batcher
op-proposer
op-challenger
op-deployer
External Components
Some components are dependencies living outside the monorepo and cannot be built locally:
op-geth
op-reth
For example, in your configuration:
# This will use an external image - cannot be built locally
el_type: op-geth
el_image: "" # Will use the default op-geth image
# This can be built locally
cl_type: op-node
cl_image: {{ localDockerImage "op-node" }} # Will build from local source
Template Functions
In the simple.yaml
configuration, you'll notice several custom template functions that enable local artifact integration:
# Example usage in simple.yaml
image: {{ localDockerImage "op-node" }}
l1_artifacts_locator: {{ localContractArtifacts "l1" }}
faultGameAbsolutePrestate: {{ localPrestate.Hashes.prestate_mt64 }}
These template functions map to specific builders in the Go codebase that handle artifact construction.
Builder Components
1. Docker Image Builder
The Docker image builder manages the building and tagging of local Docker images:
// Usage in YAML:
image: {{ localDockerImage "op-node" }}
This builder:
- Executes build commands using the
just
task runner - Caches built images to prevent redundant builds (in particular when we have multiple L2s and/or participants to any L2)
2. Contract Builder
The contract builder handles the compilation and bundling of smart contracts:
# Usage in YAML:
l1_artifacts_locator: {{ localContractArtifacts "l1" }}
l2_artifacts_locator: {{ localContractArtifacts "l2" }}
This builder:
- Manages contract compilation through
just
commands - Caches built contract bundles
3. Prestate Builder
The prestate builder manages the generation of fault proof prestates:
# Usage in YAML:
faultGameAbsolutePrestate: {{ localPrestate.Hashes.prestate_mt64 }}
This builder:
- Generates prestate data for fault proofs
- Caches built prestates
Using Local Artifacts
To use local artifacts in your devnet:
- Ensure your local environment has the necessary build dependencies
- Reference local artifacts in your YAML configuration using the appropriate template functions
- The builders will automatically handle building and caching of artifacts
Example configuration using all types of local artifacts:
optimism_package:
chains:
- participants:
- el_type: op-geth
el_image: "" # Uses default external op-geth image
cl_type: op-node
cl_image: {{ localDockerImage "op-node" }}
op_contract_deployer_params:
image: {{ localDockerImage "op-deployer" }}
l1_artifacts_locator: {{ localContractArtifacts "l1" }}
l2_artifacts_locator: {{ localContractArtifacts "l2" }}
global_deploy_overrides:
faultGameAbsolutePrestate: {{ localPrestate.Hashes.prestate_mt64 }}
This integration system ensures that your devnet can seamlessly use locally built components while maintaining reproducibility and ease of configuration.
Standard Output Format
Kurtosis-devnet is tightly integrated with the Optimism Devnet SDK. This integration is achieved through a standardized devnet descriptor format that enables powerful testing and automation capabilities.
Accessing the Devnet Descriptor
The devnet descriptor is available in two ways:
-
Deployment Output
- When you run any of the deployment commands (
just devnet ...
), the descriptor is printed to stdout - The output is a JSON file that fully describes your devnet configuration
- You can capture this output for later use or automation
- When you run any of the deployment commands (
-
Kurtosis Enclave Artifact
- The descriptor is also stored as a file artifact named "devnet" in the Kurtosis enclave
- This allows other tools and services to discover and interact with your devnet
- The descriptor can be accessed through devnet-sdk using the Kurtosis URL format:
kt://<enclave-name>/files/devnet
Here's a simplified example of a devnet descriptor:
{
"l1": {
"name": "Ethereum",
"nodes": [
{
"services": {
"cl": {
"name": "cl-1-lighthouse-geth",
"endpoints": {
"http": {
"host": "127.0.0.1",
"port": 8545
}
}
},
"el": {
"name": "el-1-geth-lighthouse",
"endpoints": {
"rpc": {
"host": "127.0.0.1",
"port": 8551
}
}
}
}
}
],
"addresses": {
"l1CrossDomainMessenger": "0x...",
"l1StandardBridge": "0x...",
"optimismPortal": "0x..."
// ... other contract addresses
},
"wallets": {
"user-key-0": {
"address": "0x...",
"private_key": "0x..."
}
// ... other wallets
},
"jwt": "0x..."
},
"l2": [
{
"name": "op-kurtosis",
"id": "2151908",
"services": {
"batcher": {
"name": "op-batcher-op-kurtosis",
"endpoints": {
"http": {
"host": "127.0.0.1",
"port": 8547
}
}
},
"proposer": {
"name": "op-proposer-op-kurtosis",
"endpoints": {
"http": {
"host": "127.0.0.1",
"port": 8548
}
}
}
},
"nodes": [
{
"services": {
"cl": {
"name": "op-node",
"endpoints": {
"http": {
"host": "127.0.0.1",
"port": 8546
}
}
},
"el": {
"name": "op-geth",
"endpoints": {
"rpc": {
"host": "127.0.0.1",
"port": 8549
}
}
}
}
}
],
"jwt": "0x..."
}
]
}
This standardized output enables seamless integration with the devnet-sdk and other tools in the ecosystem.
Devnet SDK Integration
By leveraging the devnet-sdk integration, your devnets automatically gain access to:
-
Test Framework Integration
- Use your devnet as a System Under Test (SUT) with tests written in the devnet-sdk framework
- Seamless integration with existing test suites
- Standardized approach to devnet interaction in tests
-
Test Runner Support
- Native support for op-nat as a test runner
- Consistent test execution across different devnet configurations
- Automated test setup and teardown
These capabilities make kurtosis-devnet an ideal platform for both development and testing environments.