Paxeer Docs logo

Debugging for EVM

Advanced debugging techniques for EVM transactions on Paxeer. Learn transaction template generation and analysis using paxd and Foundry cast tools.

Overview

Debugging EVM transactions on Paxeer requires understanding both the transaction creation process and how to analyze transaction behavior. This guide covers advanced debugging techniques using transaction template generation, analysis tools, and comprehensive transaction inspection methods to help developers identify and resolve issues in their EVM interactions.

Transaction Template Generation

The --generate-only flag transforms any Paxeer CLI transaction command into a template generator, creating complete transaction structures without broadcasting them. Through the --generate-only flag and Foundry's cast tool, developers can craft, analyze, and debug transactions across the EVM environment.

Basic Command Pattern

The general pattern follows this structure:

paxd tx <module> <action> <parameters> --from <key> --evm-rpc https://public-rpc.paxeer.app/evm/reference --generate-only

Generating EVM Transaction Templates

To generate an EVM transaction template, use the evm module with --generate-only. Here's an example sending HPX to another EVM address:

paxd tx evm send 0xRecipientAddress 1000000000000000000 \
--gas-fee-cap=100000000000 \
--gas-limit=21000 \
--evm-rpc=https://public-rpc.paxeer.app/evm/reference \
--from=mykey \
--generate-only
This command returns a transaction template that you can analyze before broadcasting. The template includes all transaction details without executing the actual transaction.

Analyzing EVM Transactions with Cast

Once you have a transaction hash, you can use Foundry's cast command to inspect the transaction details:

cast tx 0x5010e6600e67f04a9bc3d3b670a7c2de380b180713d9a014a5dbd76b7e2190f1 \
--rpc-url=https://public-rpc.paxeer.app/evm/reference

Example Output:

blockHash               0x4696d63a9a9ae88b03bcc94ccbd87f407e994b309d1dff9c0626de51ac57b76e
blockNumber             130076639
from                    0xAa55a16dD4E73c48C968928983c2bcC98d913d96
transactionIndex        7
effectiveGasPrice       100000000000
accessList              []
chainId                 125
gasLimit                2500000
hash                    0x5010e6600e67f04a9bc3d3b670a7c2de380b180713d9a014a5dbd76b7e2190f1
input                   0xc31d960f0000...
maxFeePerGas            100000000000
maxPriorityFeePerGas    100000000000
nonce                   3
to                      0x000000000000000000000000000000000000100b
type                    2
value                   0

Additional Analysis Commands

Get transaction receipt:

cast receipt 0x5010e6600e67f04a9bc3d3b670a7c2de380b180713d9a014a5dbd76b7e2190f1 \
--rpc-url=https://public-rpc.paxeer.app/evm/reference

Decode transaction input data:

cast 4byte-decode 0xc31d960f0000...
All template generation commands create JSON files that you can inspect, modify, and use for debugging before executing the actual transactions.

RPC Consistency

Always point cast commands to the Paxeer EVM RPC endpoint (https://public-rpc.paxeer.app/evm/reference), not a Cosmos RPC URL.

Tracing and Revert Reasons

If your endpoint supports debug RPC methods, you can retrieve full execution traces and revert reasons:

# Full transaction trace
cast rpc debug_traceTransaction 0xTX_HASH '{"tracer":"callTracer","timeout":"120s"}' \
  --rpc-url=$EVM_RPC_URL

# Simulate and trace a call without broadcasting
cast rpc debug_traceCall '{"from":"0xFROM","to":"0xTO","data":"0xDATA"}' \
  'latest' '{"tracer":"callTracer","timeout":"120s"}' \
  --rpc-url=$EVM_RPC_URL

Many public RPC endpoints disable debug methods. If disabled, run a local fork and trace there.


Reproduce with a Local Fork

Fork the network locally to reproduce issues deterministically and run traces even if remote debug RPC is disabled:

# Start a local fork
anvil --fork-url https://public-rpc.paxeer.app/evm/reference

# Re-run calls against the fork
cast call 0xContract "method(uint256)" 1 --rpc-url=http://127.0.0.1:8545

# Trace the call on the fork via debug RPC
cast rpc debug_traceCall '{"to":"0xContract","data":"0xENCODED_DATA"}' \
  'latest' '{"tracer":"callTracer"}' --rpc-url=http://127.0.0.1:8545

Event Logs and Decoding

Use the receipt to inspect logs and decode with the contract ABI:

# Fetch receipt JSON and view logs
cast receipt 0xTX_HASH --rpc-url=$EVM_RPC_URL --json | jq '.logs'

# Compute an event signature for topic[0]
cast keccak "Transfer(address,address,uint256)"
Decode event topics/data using the contract ABI (from your repo or block explorer). Topic[0] equals the keccak of the event signature.

Nonce, Balance, and Gas Diagnostics

Check common failure points quickly:

cast nonce 0xYourAddress --rpc-url=$EVM_RPC_URL
cast balance 0xYourAddress --rpc-url=$EVM_RPC_URL
cast gas-price --rpc-url=$EVM_RPC_URL
cast block latest baseFeePerGas --rpc-url=$EVM_RPC_URL
cast chain-id --rpc-url=$EVM_RPC_URL

Checklist:

  • Incorrect nonce (pending tx in mempool)
  • Insufficient native balance for gas
  • Underpriced maxFeePerGas/maxPriorityFeePerGas
  • Chain ID mismatch (Paxeer mainnet is 125)

Offline Workflow with --generate-only

Generate, inspect, sign, and broadcast safely:

# 1) Generate a template (no broadcast)
paxd tx evm send 0xTO 1000000000000000000 \
  --from=$WALLET_NAME --evm-rpc=$EVM_RPC_URL --generate-only > tx.json

# 2) Sign offline with your key
paxd tx sign tx.json --from $WALLET_NAME --chain-id $CHAIN_ID > signed.json

# 3) Broadcast the signed tx
paxd tx broadcast signed.json
Never commit signed transactions or private keys. Use environment variables and .gitignore for sensitive data.

Storage Inspection

Verify on-chain state directly when debugging state changes:

cast storage 0xContract 0xSLOT --rpc-url=$EVM_RPC_URL

Transaction Analysis

When analyzing transactions, follow these essential practices:

  • Always verify EVM transactions thoroughly
  • Use cast to decode input data when working with EVM transactions
  • Keep track of gas parameters
  • Monitor transaction status on the EVM layer

Analysis Tips:

# Use Foundry's cast tool for detailed transaction inspection
cast tx 0x5010e6600e67f04a9bc3d3b670a7c2de380b180713d9a014a5dbd76b7e2190f1 \
--rpc-url=$EVM_RPC_URL

# Get transaction receipt to verify success
cast receipt 0x5010e6600e67f04a9bc3d3b670a7c2de380b180713d9a014a5dbd76b7e2190f1 \
--rpc-url=$EVM_RPC_URL

# Decode transaction input data
cast 4byte-decode 0xa9059cbb000000...

Transaction Analysis Checklist: Always verify transaction success before proceeding. Check gas usage to optimize future transactions. Use Foundry's cast tool for detailed transaction inspection.


Error Handling

Handle potential EVM transaction issues with proper monitoring:

try {
  // Check EVM transaction status
  const evmStatus = await checkEvmStatus(txHash);
  if (!evmStatus.success) {
    const evmError = await cast.call(['tx', txHash, '--rpc-url', evmRpcUrl]);
    console.error('EVM transaction failed:', evmError);
  }
} catch (error) {
  console.error('Transaction analysis failed:', error);
}

Best Practices for Error Handling:

  • Always check transaction status before proceeding
  • Use detailed error logging for debugging failed transactions
  • Implement retry logic for network-related failures
  • Monitor gas usage and adjust limits accordingly

Security Guidelines

Critical Security Requirements: Keep private keys secure and never include them in templates. Use an .env file or other environment variables when working with wallet keys or mnemonics. Never commit sensitive information to version control. Always verify transaction details before signing.

Environment Variable Setup:

# Create .env file for sensitive data
WALLET_NAME=mykey
EVM_RPC_URL=https://public-rpc.paxeer.app/evm/reference
PRIVATE_KEY=your_private_key_here

# Add .env to .gitignore
echo ".env" >> .gitignore

Secure Transaction Execution:

# Use environment variables in commands
paxd tx evm send 0x1234567890abcdef... 1000000000000000000 \
--from=$WALLET_NAME \
--evm-rpc=$EVM_RPC_URL

# Generate transaction template first to verify details
paxd tx evm send 0x1234567890abcdef... 1000000000000000000 \
--from=$WALLET_NAME \
--evm-rpc=$EVM_RPC_URL \
--generate-only