一键导入
warp-route-check
A skill that allows a user to validate that a warp route deployment will be in the expected state after applying some configuration
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
A skill that allows a user to validate that a warp route deployment will be in the expected state after applying some configuration
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | warp-route-check |
| description | A skill that allows a user to validate that a warp route deployment will be in the expected state after applying some configuration |
You are a specialized agent for checking warp route deployments and updates using the Hyperlane CLI and Heimdall CLI.
This skill requires the following tools and setup:
npm install -g @hyperlane-xyz/clicurl -L https://foundry.paradigm.xyz | bash && foundryupbrew install jq or apt-get install jq)Hyperlane Registry cloned (default location: $HOME/hyperlane-registry):
git clone https://github.com/hyperlane-xyz/hyperlane-registry.git $HOME/hyperlane-registry
Hyperlane Monorepo cloned (required for http-registry):
git clone https://github.com/hyperlane-xyz/hyperlane-monorepo.git
export HYPERLANE_MONOREPO="/path/to/hyperlane-monorepo"
Optional: http_registry shell function (add to ~/.zshrc or ~/.bashrc):
function http_registry() {
pnpm -C $HYPERLANE_MONOREPO/typescript/infra start:http-registry
}
export HYPERLANE_REGISTRY="$HOME/hyperlane-registry" # Custom registry location
export HYPERLANE_MONOREPO="/path/to/monorepo" # Monorepo location
Follow these steps to verify a warp route deployment:
Verify all required tools and paths before proceeding:
# Check required CLI tools
command -v hyperlane >/dev/null 2>&1 || { echo "❌ hyperlane CLI not installed. Run: npm install -g @hyperlane-xyz/cli"; exit 1; }
command -v heimdall >/dev/null 2>&1 || { echo "❌ heimdall not installed"; exit 1; }
command -v cast >/dev/null 2>&1 || { echo "❌ foundry not installed. Run: curl -L https://foundry.paradigm.xyz | bash"; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "❌ jq not installed"; exit 1; }
command -v python3 >/dev/null 2>&1 || { echo "❌ python3 not installed"; exit 1; }
echo "✅ All required tools installed"
# Determine registry location (configurable via env var)
REGISTRY_PATH="${HYPERLANE_REGISTRY:-$HOME/hyperlane-registry}"
# Verify registry exists
if [ ! -d "$REGISTRY_PATH" ]; then
echo "❌ Registry not found at $REGISTRY_PATH"
echo "Clone it: git clone https://github.com/hyperlane-xyz/hyperlane-registry.git $REGISTRY_PATH"
exit 1
fi
echo "✅ Registry found at $REGISTRY_PATH"
# Determine HTTP registry start command
if type http_registry >/dev/null 2>&1; then
HTTP_REGISTRY_CMD="http_registry"
elif [ -n "$HYPERLANE_MONOREPO" ] && [ -d "$HYPERLANE_MONOREPO/typescript/infra" ]; then
HTTP_REGISTRY_CMD="pnpm -C $HYPERLANE_MONOREPO/typescript/infra start:http-registry"
else
echo "❌ Cannot start HTTP registry. Please either:"
echo " 1. Set HYPERLANE_MONOREPO env var pointing to monorepo, OR"
echo " 2. Define http_registry function in your shell"
exit 1
fi
echo "✅ HTTP registry command available"
Common Chain IDs Reference (for parsing transactions):
1 = ethereum 8453 = base
10 = optimism 42161 = arbitrum
56 = bsc 43114 = avalanche
88 = viction 59144 = linea
130 = unichain 137 = polygon
Check fork output for complete mappings
$REGISTRY_PATH (default: $HOME/hyperlane-registry)git -C "$REGISTRY_PATH" branch --show-currentmain at the endrun_in_background=true parameter for Bash tool# Use command determined in Step 0
$HTTP_REGISTRY_CMD > /tmp/http-registry.log 2>&1 &
hyperlane warp fork also blocks - it runs a server for the forked registryhyperlane commandhyperlane warp fork with the provided warp route ID in the background{ port: 8535 } Server running)http://localhost:<actual-port># Use ACTUAL registry URL from Step 3
hyperlane warp fork --id <warp-route-id> --registry <actual-registry-url-from-step-3>
Read fork output carefully to extract:
Create a port mapping from the fork output for later use.
IMPORTANT: Before submitting transactions, you MUST analyze the transaction file to detect if it targets multiple owners per chain.
# Get all unique chain IDs
jq -r '.[].chainId' <transactions-file> | sort -u
# Get all unique contract addresses per chain
jq -r '.[] | "\(.chainId)|\(.to)"' <transactions-file> | sort -u
Map chain IDs to names using the fork output (don't assume - verify actual chain names).
CRITICAL: For EACH unique contract address being targeted, query its current owner from the forked chain.
# For each contract on each chain (use ACTUAL ports from fork output):
cast call <contract-address> "owner()(address)" --rpc-url http://localhost:<ACTUAL-PORT-FOR-CHAIN>
Example workflow (ports shown are examples - use ACTUAL ports from YOUR fork output):
# Example assumes fork output showed: ethereum at port 8548, arbitrum at port 8545
# YOUR ports may differ - always check YOUR fork output
# Query ethereum contracts (use YOUR actual port from fork output)
cast call 0xe1De... "owner()(address)" --rpc-url http://localhost:<YOUR-ETH-PORT>
cast call 0xcf4ec... "owner()(address)" --rpc-url http://localhost:<YOUR-ETH-PORT>
# Query arbitrum contracts (use YOUR actual port from fork output)
cast call 0xAd435... "owner()(address)" --rpc-url http://localhost:<YOUR-ARB-PORT>
Create complete owner mapping:
{
"<chainId>_<contractAddress>": "<actual-owner-address>",
"1_0xe1De9910fe71cC216490AC7FCF019e13a34481D7": "0x3965...",
"1_0xcf4ecA86606372B975FaF04a97e8eE3AfeA5a02D": "0x8Ff4..."
}
Note: Owners may be contract addresses (multisigs, timelocks) - this is OK, anvil can impersonate them.
Group transactions by chain and owner to detect if splitting is needed:
# Pseudocode logic
for each chain:
unique_owners = set of owners for contracts on this chain
if len(unique_owners) > 1:
# Chain has multiple owners - splitting required
splitting_needed = True
If ANY chain has multiple owners: Proceed to Step 5d (split transactions) If all chains have single owner: Skip to Step 5e (create single strategy)
When to do this: If Step 5c detected multiple owners per chain.
How to split:
# Split transactions by owner
owner_groups = group_by(transactions, lambda tx: owner_map[f"{tx.chainId}_{tx.to}"])
for owner, txs in owner_groups:
write_file(f"/tmp/transactions-owner-{owner}.json", txs)
Example: If 171 transactions target 17 different owners across 6 chains, create 17 separate transaction files.
Proceed to Step 5f for each split file.
When to do this: If Step 5c found no multiple owners per chain.
Create one strategy file with one owner per chain:
<chain-name>:
submitter:
chain: <chain-name>
type: impersonatedAccount
userAddress: '<actual-owner-from-step-5b>'
Save to /tmp/<route>-strategy.yaml
Proceed to Step 5g.
When to do this: If Step 5d split transactions.
For each split transaction file, create a corresponding strategy file:
<chain-name>:
submitter:
chain: <chain-name>
type: impersonatedAccount
userAddress: '<owner-for-this-split>'
Save each as /tmp/strategy-owner-<owner>.yaml
Use anvil_setBalance to fund ALL unique owner addresses on their respective chains (use ACTUAL ports from fork output):
BALANCE="0x56BC75E2D63100000" # 100 ETH
# For each owner on each chain (use YOUR ACTUAL port from fork output):
cast rpc anvil_setBalance <owner-address> $BALANCE --rpc-url http://localhost:<YOUR-ACTUAL-PORT>
Example (ports shown are examples - use YOUR actual ports from fork output):
# Example assumes fork output showed ethereum at port 8548
# YOUR port may differ - use YOUR actual port from fork output
cast rpc anvil_setBalance 0x3965... $BALANCE --rpc-url http://localhost:<YOUR-ETH-PORT>
cast rpc anvil_setBalance 0x8Ff4... $BALANCE --rpc-url http://localhost:<YOUR-ETH-PORT>
Fund ALL unique owners you identified in Step 5b.
For each transaction file and its corresponding strategy:
# Set dummy HYP_KEY (required even with impersonation)
HYP_KEY="0x0000000000000000000000000000000000000000000000000000000000000001"
# Submit transactions using installed hyperlane command with ACTUAL forked registry URL
hyperlane submit \
--transactions <transactions-file> \
--strategy <corresponding-strategy-file> \
--registry <YOUR-ACTUAL-forked-registry-url-from-step-4> \
--yes
CRITICAL:
hyperlane commandTrack submission results:
If using split files: Submit all files sequentially, tracking success/failure for each.
IMPORTANT: After submission, decode ALL transactions using Heimdall for the final report.
# For each transaction in the original combined file:
for tx in transactions:
decoded = run_command(f"heimdall decode {tx.data} --default")
store_decoded(tx.chainId, tx.to, tx.annotation, decoded)
Save decoded output as JSON for inclusion in final report:
[
{
"index": 1,
"chain": "ethereum",
"to": "0x...",
"annotation": "...",
"decoded": "..."
}
]
Save to /tmp/decoded-transactions.json
Execute hyperlane warp check against the forked registry (use YOUR ACTUAL URL from Step 4):
hyperlane warp check \
--id <warp-route-id> \
--registry <YOUR-ACTUAL-forked-registry-url-from-step-4> \
--yes
Capture full output to /tmp/warp-check.log for the final report.
NOTE: Warp check may show provider errors for newly added chains - this is expected.
Analyze the warp check output carefully:
CRITICAL: Focus on violations for chains that have transactions. Violations on other chains are expected since those chains aren't being modified.
1. Violations on chains WITHOUT transactions: ALWAYS EXPECTED
avalanche: # ← No transactions for this chain
proxyAdmin:
owner:
EXPECTED: '0x...'
ACTUAL: '0x...'
Why: Chains not in the transactions file are not being modified. Their violations show the gap between current and target state.
2. Ownership mismatches on chains WITH transactions: EXPECTED if transactions don't include ownership transfers
ethereum: # ← Has transactions, but ownership not transferred yet
proxyAdmin:
owner:
EXPECTED: '0x...'
ACTUAL: '0x...'
Why: The registry shows TARGET state after full deployment. If transactions configure functionality but don't transfer ownership, ownership differences are expected.
3. Fee configuration differences: MAY BE EXPECTED
ethereum:
tokenFee:
maxFee:
ACTUAL: '115792...'
EXPECTED: ''
Why: Transactions may SET fee values that aren't in the registry config yet.
These indicate actual configuration issues on chains WITH transactions:
ethereum: # ← Has transactions but missing expected config
remoteRouters:
42161: # arbitrum domain
ACTUAL: ''
EXPECTED: '0x...'
Real problems to look for:
Key: Only violations on chains that have transactions AND should have been fixed by those transactions are real problems.
Create a comprehensive markdown report with the following sections:
# <WARP_ROUTE_ID> Validation Report
**Date:** <timestamp>
**Branch:** <registry-branch>
**Transaction File:** <filename>
## Executive Summary
[Overall pass/fail verdict]
[Key metrics: total transactions, chains modified, success rate]
## Port Detection (Dynamic)
[List all ports extracted from fork output]
- HTTP Registry: <actual-port>
- Forked Registry: <actual-port>
- Chain Ports: [chain: port mapping]
## Transaction Breakdown
[Table showing chains with transactions, counts, owners]
## Submission Results
[Detailed results of transaction submission]
- Split files created (if applicable)
- Submission success/failure counts
- Any errors encountered
## Warp Check Results
### Chains WITH Transactions
[Analysis of functional configuration]
- Routers: [status]
- Destination gas: [status]
- ISM: [status]
- Bridge allowances: [status]
### Chains WITHOUT Transactions
[List of chains not modified and their expected violations]
## Decoded Transactions (Heimdall Output)
```json
[Full decoded transaction output from /tmp/decoded-transactions.json]
```
[Full warp check output from /tmp/warp-check.log]
[Final verdict with supporting rationale]
**Save report** to `/tmp/<route>-validation-report.md`
### Step 11: Cleanup
- Clean up **both** background processes:
- Stop the `hyperlane warp fork` server
- Stop the `http_registry` server
- **Switch registry branch back to main**: `git -C "$REGISTRY_PATH" checkout main`
- Confirm cleanup is complete
```bash
# Kill background processes
pkill -f "hyperlane warp fork"
pkill -f "http_registry"
# Switch back to main (use $REGISTRY_PATH variable)
git -C "$REGISTRY_PATH" checkout main
anvil_setBalance (Step 5g) for ALL unique ownershyperlane warp read as fallback validation if neededCRITICAL: Never assume port numbers. Always extract from actual output.
# ❌ WRONG - Hardcoded port
cast call <addr> "owner()" --rpc-url http://localhost:8550
# ✅ CORRECT - Use actual port from YOUR fork output
# First: Extract port from YOUR fork output file
PORT=$(grep "Successfully started Anvil node for chain ethereum" /tmp/warp-fork.log | \
grep -oE "http://127.0.0.1:([0-9]+)" | cut -d: -f3)
cast call <addr> "owner()" --rpc-url http://localhost:$PORT
Build a port mapping dictionary from YOUR fork output and reference it throughout.
| Variable | Default | Purpose |
|---|---|---|
HYPERLANE_REGISTRY | $HOME/hyperlane-registry | Registry location |
HYPERLANE_MONOREPO | (required) | Monorepo location for http-registry |
REGISTRY_PATH | $HYPERLANE_REGISTRY | Used internally by skill |
HTTP_REGISTRY_CMD | (auto-detected) | Command to start HTTP registry |