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
code
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:
bash
# Is the node reachable?
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
# Expected: {"jsonrpc":"2.0","id":1,"result":"0x1"}
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:
java
// Enable Brane debug logging
System.setProperty("BRANE_DEBUG", "true");
// This will print:
// [BRANE] → eth_call {"to":"0x...", "data":"0x..."}
// [BRANE] ← "0x..."
Verify calldata manually:
bash
# Using cast (foundry) cast calldata "balanceOf(address)" 0xYourAddress # Compare with what Brane generates
Layer 3: Transaction Signing
Symptoms: Invalid sender, signature error
Checks:
- •
Is the signer address what you expect?
javaSystem.out.println("Signer address: " + signer.address()); - •
Is chain ID correct?
java// Chain ID mismatch causes "invalid sender" var chainId = publicClient.getChainId(); System.out.println("Chain ID: " + chainId); - •
Verify signature recovery:
bash# Using cast cast wallet sign --private-key 0x... "message"
Layer 4: Contract Execution
Symptoms: Revert, out of gas, unexpected return value
Debug with eth_call first:
java
// Test without sending transaction
var result = publicClient.call(TransactionRequest.builder()
.to(contractAddress)
.data(encodedCalldata)
.build());
Get revert reason:
java
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)
code
0x08c379a0 0000000000000000000000000000000000000000000000000000000000000020 // offset 0000000000000000000000000000000000000000000000000000000000000011 // length (17) 496e73756666696369656e742066756e647300000000000000000000000000 // "Insufficient funds"
Decode:
bash
cast 4byte-decode 0x08c379a0... # Or cast --to-ascii 0x496e73756666696369656e742066756e6473
Panic Code (0x4e487b71)
code
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
code
0x<4-byte-selector><encoded-params>
Find selector:
bash
# If you have the ABI cast sig "InsufficientBalance(uint256,uint256)" # Returns: 0x... # Or search online # https://openchain.xyz/signatures
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
java
// What Brane computes
var selector = Abi.computeSelector("transfer(address,uint256)");
System.out.println("Selector: " + Hex.encode(selector));
// Should be: 0xa9059cbb
bash
# Verify with cast cast sig "transfer(address,uint256)"
Verify Encoded Parameters
java
// Print full calldata
var calldata = abi.encodeFunction("transfer", recipient, amount);
System.out.println("Calldata: " + calldata.value());
bash
# Decode to verify 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
bash
# Verbose mode shows all RPC calls anvil -vvvv # Fork mainnet for testing against real contracts anvil --fork-url https://eth.llamarpc.com
Useful Anvil Commands
bash
# Mine a block cast rpc anvil_mine # Set balance cast rpc anvil_setBalance 0xAddress 0x1000000000000000000 # Impersonate account cast rpc anvil_impersonateAccount 0xWhale # Get transaction trace cast run <txhash> --trace
Compare with Cast
bash
# Send same transaction with cast, compare results cast send --private-key 0x... \ 0xContractAddress \ "transfer(address,uint256)" \ 0xRecipient \ 1000000
Debugging Contract Binding
Method Not Found
code
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
code
IllegalArgumentException: Unsupported parameter type for transfer
Checks:
- •Java type matches Solidity type
- •For arrays: use
List<T>orT[] - •For uint256: use
BigInteger, notlong
Return Type Mismatch
code
IllegalArgumentException: Unsupported return type for view function
Checks:
- •View functions return the decoded type
- •State-changing functions return
TransactionReceiptorvoid
Debug Logging
Enable Brane Debug Output
java
// Set before any Brane calls
System.setProperty("BRANE_DEBUG", "true");
Output includes:
- •RPC method and parameters
- •Response data
- •Transaction encoding details
- •Gas estimation
Custom Logging Points
java
// Log transaction request
System.out.println("To: " + request.to());
System.out.println("Data: " + request.data());
System.out.println("Value: " + request.value());
// Log raw signed transaction
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_chainIdworks?) - • 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)