name brane-debugging description Systematic approach to debugging Brane SDK issues. Use when diagnosing transaction failures, RPC errors, encoding mismatches, or unexpected behavior.
Brane SDK Debugging Guide
Debugging Philosophy
Reproduce first - Get a minimal reproduction
Isolate the layer - RPC? Encoding? Signing? Contract?
Compare with known-good - Use Anvil, compare with viem/cast
Read the actual bytes - Hex doesn't lie
Quick Diagnosis Flowchart
Transaction Failed
│
▼
┌─────────────────┐
│ What error? │
└────────┬────────┘
│
┌────┴────┬────────────┬─────────────┐
▼ ▼ ▼ ▼
"reverted" "nonce" "gas" "insufficient
│ │ │ funds"
▼ ▼ ▼ │
Decode Check Estimate ▼
revert pending gas Check
data txs balance
Layer-by-Layer Debugging
Layer 1: RPC Communication
Symptoms : Connection refused, timeout, unexpected null
Checks :
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
Common Issues :
Symptom Cause Fix Connection refused Node not running Start Anvil/node 403 Forbidden Rate limited or auth required Check API key, rate limits Timeout Node overloaded or network issue Retry, use different endpoint Empty result Method not supported Check node type (full vs light)
Layer 2: Request Encoding
Symptoms : Invalid params error, unexpected behavior
Debug Approach :
System.setProperty("BRANE_DEBUG" , "true" );
Verify calldata manually :
cast calldata "balanceOf(address)" 0xYourAddress
Layer 3: Transaction Signing
Symptoms : Invalid sender, signature error
Checks :
Is the signer address what you expect?
System.out.println("Signer address: " + signer.address());
Is chain ID correct?
var chainId = publicClient.getChainId();
System.out.println("Chain ID: " + chainId);
Verify signature recovery:
cast wallet sign --private-key 0x... "message"
Layer 4: Contract Execution
Symptoms : Revert, out of gas, unexpected return value
Debug with eth_call first :
var result = publicClient.call(TransactionRequest.builder()
.to(contractAddress)
.data(encodedCalldata)
.build());
Get revert reason :
try {
walletClient.sendTransaction(request);
} catch (RevertException e) {
System.out.println("Revert kind: " + e.kind());
System.out.println("Reason: " + e.reason());
System.out.println("Raw data: " + e.rawDataHex());
}
Decoding Revert Data
Standard Error (0x08c379a0)
0x08c379a0
0000000000000000000000000000000000000000000000000000000000000020 // offset
0000000000000000000000000000000000000000000000000000000000000011 // length (17)
496e73756666696369656e742066756e647300000000000000000000000000 // "Insufficient funds"
Decode :
cast 4byte-decode 0x08c379a0...
cast --to-ascii 0x496e73756666696369656e742066756e6473
Panic Code (0x4e487b71)
0x4e487b71
0000000000000000000000000000000000000000000000000000000000000011 // panic code
Code Meaning 0x01 assert() failed 0x11 Arithmetic overflow 0x12 Division by zero 0x21 Invalid enum 0x32 Array out of bounds
Custom Error
0x<4-byte-selector><encoded-params>
Find selector :
cast sig "InsufficientBalance(uint256,uint256)"
Common Error Messages
Transaction Errors
Error Cause Solution "nonce too low" Nonce already used Fetch fresh nonce with "pending" "nonce too high" Gap in nonce sequence Use correct sequential nonce "replacement transaction underpriced" Replacing tx needs +10% gas Increase gas price "intrinsic gas too low" Gas limit < base cost Increase gas limit "insufficient funds" Can't afford gas + value Check balance "invalid sender" Signature/chainId mismatch Check signer, chain ID "already known" Duplicate transaction Transaction already pending
RPC Errors
Code Message Cause -32000 (various) Server-specific, read message -32601 Method not found Node doesn't support method -32602 Invalid params Wrong parameter format -32005 Limit exceeded Rate limit or block range
eth_call Errors
Symptom Cause Debug Returns 0x Function doesn't exist or wrong address Verify contract address, function selector Returns weird data Wrong ABI, wrong return type Compare selector, check ABI Reverts Contract logic revert Decode revert data
Debugging ABI Encoding
Verify Function Selector
var selector = Abi.computeSelector("transfer(address,uint256)" );
System.out.println("Selector: " + Hex.encode(selector));
cast sig "transfer(address,uint256)"
Verify Encoded Parameters
var calldata = abi.encodeFunction("transfer" , recipient, amount);
System.out.println("Calldata: " + calldata.value());
cast calldata-decode "transfer(address,uint256)" 0xa9059cbb...
Common Encoding Mistakes
Symptom Cause Fix Wrong selector Signature has spaces or wrong types Use canonical signature Wrong address Not left-padded Check Address encoding Wrong number Not proper hex Use BigInteger, not long
Debugging with Anvil
Start Anvil with Logging
anvil -vvvv
anvil --fork-url https://eth.llamarpc.com
Useful Anvil Commands
cast rpc anvil_mine
cast rpc anvil_setBalance 0xAddress 0x1000000000000000000
cast rpc anvil_impersonateAccount 0xWhale
cast run <txhash> --trace
Compare with Cast
cast send --private-key 0x... \
0xContractAddress \
"transfer(address,uint256)" \
0xRecipient \
1000000
Debugging Contract Binding
Method Not Found
IllegalArgumentException: No ABI function named 'transfer'
Checks :
Method name matches ABI exactly (case-sensitive)
ABI JSON is valid and contains the function
Interface method matches ABI signature
Parameter Type Mismatch
IllegalArgumentException: Unsupported parameter type for transfer
Checks :
Java type matches Solidity type
For arrays: use List<T> or T[]
For uint256: use BigInteger, not long
Return Type Mismatch
IllegalArgumentException: Unsupported return type for view function
Checks :
View functions return the decoded type
State-changing functions return TransactionReceipt or void
Debug Logging
Enable Brane Debug Output
System.setProperty("BRANE_DEBUG" , "true" );
Output includes :
RPC method and parameters
Response data
Transaction encoding details
Gas estimation
Custom Logging Points
System.out.println("To: " + request.to());
System.out.println("Data: " + request.data());
System.out.println("Value: " + request.value());
System.out.println("Signed: " + Hex.encode(signedTx));
Network-Specific Issues
Mainnet
Rate limits from public RPCs
High gas prices during congestion
MEV/frontrunning effects
Testnets
Faucet rate limits
Occasional reorgs
Different behavior than mainnet
L2s (Arbitrum, Optimism, Base)
Different gas model
Sequencer delays
L1 data costs in gas
Checklist: Transaction Won't Send
Node reachable? (eth_chainId works?)
Correct chain ID?
Sender has balance for gas + value?
Nonce is correct? (fetch with "pending")
Gas limit sufficient? (try eth_estimateGas)
Gas price acceptable? (not below minimum)
Contract address correct?
Function selector correct?
Parameters encoded correctly?
Signer address matches expected?
Checklist: eth_call Returns Wrong Data
Contract address correct?
Function exists in contract?
Selector matches? (compare with cast sig)
Parameters encoded correctly?
Return type matches ABI?
Block parameter correct? (latest vs specific)
Contract not proxy? (might need implementation address)