From moonbeam-engineering
Debugs issues in the Moonbeam parachain including runtime panics, EVM execution failures, XCM message delivery problems, and client-side errors. Use when encountering transaction failures, unexpected behavior, state inconsistencies, block production issues, or RPC errors.
How this skill is triggered — by the user, by Claude, or both
Slash command
/moonbeam-engineering:debugging-moonbeamThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- [Lazy Loading (Fork Mode)](#lazy-loading-fork-mode)
Lazy loading allows running a local Moonbeam node that fetches state on-demand from a live RPC endpoint. This is the most powerful tool for debugging production issues as it lets you replay transactions against real chain state.
# Build with lazy-loading feature enabled
cargo build --release --features lazy-loading
# Fork from Moonbeam mainnet at latest block
./target/release/moonbeam \
--lazy-loading-remote-rpc https://rpc.api.moonbeam.network \
--sealing 6000
# Fork from specific block
./target/release/moonbeam \
--lazy-loading-remote-rpc https://rpc.api.moonbeam.network \
--lazy-loading-block 0x1234...abcd \
--sealing 6000
# Fork Moonriver
./target/release/moonbeam \
--lazy-loading-remote-rpc https://rpc.api.moonriver.moonbeam.network \
--sealing 6000
# Fork Moonbase Alpha
./target/release/moonbeam \
--lazy-loading-remote-rpc https://rpc.api.moonbase.moonbeam.network \
--sealing 6000
# Use custom runtime (test new runtime against production state)
./target/release/moonbeam \
--lazy-loading-remote-rpc https://rpc.api.moonbeam.network \
--lazy-loading-runtime-override ./target/release/wbuild/moonbeam-runtime/moonbeam_runtime.wasm \
--sealing 6000
# Apply state overrides (modify storage for testing)
./target/release/moonbeam \
--lazy-loading-remote-rpc https://rpc.api.moonbeam.network \
--lazy-loading-state-overrides ./state-overrides.json \
--sealing 6000
# Adjust RPC request throttling (avoid rate limits)
./target/release/moonbeam \
--lazy-loading-remote-rpc https://rpc.api.moonbeam.network \
--lazy-loading-delay-between-requests 100 \
--lazy-loading-max-retries-per-request 5 \
--sealing 6000
{
"0x1234...": {
"balance": "0x1000000000000000000",
"nonce": "0x0",
"code": "0x...",
"storage": {
"0x0": "0x1234"
}
}
}
Reproduce a production issue:
# Fork at the block before the problematic transaction
./target/release/moonbeam \
--lazy-loading-remote-rpc https://rpc.api.moonbeam.network \
--lazy-loading-block 0xBLOCK_BEFORE_ISSUE \
--ethapi=debug,trace \
--sealing manual
Replay the failing transaction:
// Get original tx details from production
const tx = await prodProvider.getTransaction(txHash);
// Replay on forked node with tracing
const trace = await localProvider.send('debug_traceCall', [{
from: tx.from,
to: tx.to,
data: tx.data,
value: tx.value,
gas: tx.gas
}, 'latest', { tracer: 'callTracer' }]);
Test runtime fixes:
# Build fixed runtime
cargo build --release -p moonbeam-runtime
# Test against production state
./target/release/moonbeam \
--lazy-loading-remote-rpc https://rpc.api.moonbeam.network \
--lazy-loading-runtime-override ./target/release/wbuild/moonbeam-runtime/moonbeam_runtime.wasm \
--sealing 6000
| Use Case | Configuration |
|---|---|
| Debug failed tx | Fork at block before tx, replay with tracing |
| Test migration | Use --lazy-loading-runtime-override with new runtime |
| Simulate whale actions | Use --lazy-loading-state-overrides to modify balances |
| Test governance | Override voting power via state overrides |
| Debug precompile | Fork + trace precompile calls |
Identify the failing component:
WARN or ERROR messagesReproduce locally:
# Run dev node with verbose logging
RUST_LOG=debug ./target/release/moonbeam --dev --alice --sealing 6000 --rpc-port 9944
# Target specific module logging
RUST_LOG=pallet_parachain_staking=trace ./target/release/moonbeam --dev
Add debug logging in the pallet:
use frame_support::log;
log::debug!(target: "pallet-name", "Debug info: {:?}", value);
Check storage state:
state_getStorageEnable EVM tracing:
# Run with tracing enabled
./target/release/moonbeam --dev --ethapi=debug,trace
Use debug_traceTransaction:
const trace = await provider.send('debug_traceTransaction', [txHash, {}]);
Check precompile calls:
Common EVM issues:
Enable XCM logging:
RUST_LOG=xcm=trace ./target/release/moonbeam --dev
Check XCM message structure:
Common XCM issues:
TooExpensive: Insufficient weight/feeUntrustedReserveLocation: Asset origin mismatchAssetNotFound: Asset not registeredTest XCM locally:
# Use zombienet for multi-chain testing
zombienet spawn zombienet/moonbeam.toml
Check RPC method availability:
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method":"rpc_methods"}' http://localhost:9944
Verify client version compatibility:
Debug connection issues:
# Test WebSocket connection
wscat -c ws://localhost:9944
Check collator status:
AuthorMapping.MappingWithDepositMonitor block production:
# Watch block events
RUST_LOG=cumulus=debug ./target/release/moonbeam
Common block issues:
| Target | Component |
|---|---|
pallet_evm | EVM execution |
pallet_ethereum | Ethereum transaction processing |
xcm | XCM message handling |
cumulus | Parachain consensus |
moonbeam_rpc | Custom RPC methods |
frontier | Ethereum compatibility layer |
// Get transaction receipt with logs
eth_getTransactionReceipt(txHash)
// Trace transaction execution
debug_traceTransaction(txHash, {tracer: 'callTracer'})
// Get storage at specific block
eth_getStorageAt(address, slot, blockNumber)
// Check pending transactions
txpool_content()
// Get block details
eth_getBlockByNumber(blockNumber, true)
Write a failing test:
// test/suites/dev/moonbase/test-debug/test-issue-xxxx.ts
describeSuite({
id: "Dxxxxxx",
title: "Bug reproduction for issue #xxxx",
foundationMethods: "dev",
testCases: ({ context, it }) => {
it({ id: "T01", title: "Reproduces the bug", test: async () => {
// Reproduction steps
}});
}
});
Run the test:
cd test && pnpm moonwall test dev_moonbase Dxxxxxx
frame_support::log outputs/precompiles/*/src/lib.rs - look for Err() returns/runtime/*/xcm_config.rs - check barrier implementations/runtime/*/weights/ - verify weight calculations| Error | Likely Cause | Investigation |
|---|---|---|
BadOrigin | Wrong caller type | Check origin requirements |
InsufficientBalance | Not enough funds | Check free vs reserved balance |
StorageOverflow | Arithmetic overflow | Check bounded types |
TooManyDelegations | Hit delegation limit | Check MaxDelegationsPerDelegator |
| Error | Cause | Debug Steps |
|---|---|---|
OutOfGas | Gas limit too low | Increase gas, check precompile costs |
Revert | Contract/precompile failure | Check revert reason, trace tx |
InvalidNonce | Nonce mismatch | Check pending txs, use eth_getTransactionCount |
IntrinsicGas | Base gas cost not met | Ensure gas >= 21000 + calldata |
// Common revert patterns to search for
revert("Invalid input")
revert("Not enough balance")
revert("Permission denied")
Err(PrecompileFailure::Error { exit_status: ... })
Developer → Chain State → Select pallet → Query storage
Developer → Extrinsics → Submit test calls
Developer → RPC Calls → Raw RPC queries
# Decode storage key
subkey inspect --public "0x1234..."
# Parse extrinsic
subxt explore --url ws://localhost:9944
# Metadata inspection
frame-omni-bencher v1 metadata --runtime path/to/runtime.wasm
// Get tx details
const tx = await api.rpc.eth.getTransactionByHash(txHash);
const receipt = await api.rpc.eth.getTransactionReceipt(txHash);
// Replay on dev node
const rawTx = await context.createTxn!({
to: tx.to,
data: tx.input,
value: tx.value,
gas: tx.gas,
});
await context.createBlock(rawTx);
# Fork mainnet state with Chopsticks
npx @acala-network/chopsticks@latest \
--config chopsticks/moonbeam.yml \
--block 5000000
# Run with benchmark feature
RUST_LOG=runtime::executive=trace ./target/release/moonbeam --dev
// Add weight logging
log::info!(
target: "benchmark",
"Extrinsic weight: reads={}, writes={}, compute={}",
weight.proof_size(),
weight.ref_time()
);
# Check for memory leaks
RUST_BACKTRACE=1 cargo test --release -- --nocapture
# Profile memory usage
heaptrack ./target/release/moonbeam --dev
# Check peer connections
curl -H "Content-Type: application/json" \
-d '{"id":1,"jsonrpc":"2.0","method":"system_peers"}' \
http://localhost:9944
# Check sync state
curl -H "Content-Type: application/json" \
-d '{"id":1,"jsonrpc":"2.0","method":"system_syncState"}' \
http://localhost:9944
# Check GRANDPA state
RUST_LOG=grandpa=debug ./target/release/moonbeam
# Verify finalized block
curl -H "Content-Type: application/json" \
-d '{"id":1,"jsonrpc":"2.0","method":"chain_getFinalizedHead"}' \
http://localhost:9944
npx claudepluginhub moonsong-labs/knowledge-work-plugins --plugin moonbeam-engineeringConfigures and spawns ephemeral Polkadot/Substrate networks for integration testing using zombienet-sdk TOML configs or Rust NetworkConfigBuilder; debugs spawn timeouts, port errors, and block production issues on native, Docker, or Kubernetes providers.
Scans Substrate/Polkadot pallets for 7 critical vulnerabilities like arithmetic overflow, panic DoS, incorrect weights, and bad origin checks. For auditing FRAME runtimes.
Tracks Ethereum protocol evolution, EIP lifecycle, fork schedules via forkcast.org and EIPs repo. Use for checking feature status, upcoming changes, or proposing EIPs.