Files
gh-tenequm-claude-plugins-f…/skills/skill/references/debugging.md
2025-11-30 09:01:14 +08:00

252 lines
5.1 KiB
Markdown

# Debugging Workflows
Foundry debugging tools for finding and fixing smart contract issues.
## Verbosity Levels
```bash
forge test # Summary only
forge test -v # Show passing test names
forge test -vv # Print logs for all tests
forge test -vvv # Traces for failing tests
forge test -vvvv # Traces for all tests + setup
forge test -vvvvv # All traces + storage changes
```
**Use:**
- `-vv`: Quick check of console.log output
- `-vvv`: First step when test fails
- `-vvvv`: Full debugging with all traces
## Understanding Traces
### Trace Format
```
[24661] TestContract::testFunction()
├─ [2262] Target::read()
│ └─ ← 0
├─ [20398] Target::write(42)
│ └─ ← ()
└─ ← ()
```
- `[gas]`: Gas consumed by call and nested calls
- **Green**: Successful calls
- **Red**: Reverting calls
- **Blue**: Cheatcode calls
- **Cyan**: Emitted logs
- **Yellow**: Contract deployments
### Common Trace Errors
| Error | Meaning |
|-------|---------|
| `OOG` | Out of gas |
| `Revert` | Transaction reverted |
| `InvalidFEOpcode` | Unknown opcode (0xFE) |
| `NotActivated` | EVM feature not available |
## Console Logging
### Basic Usage
```solidity
import {console} from "forge-std/console.sol";
function test_Debug() public {
console.log("Value:", value);
console.log("Address:", msg.sender);
console.log("Balance:", address(this).balance);
}
```
### Format Specifiers
```solidity
console.log("String: %s", "hello");
console.log("Decimal: %d", 123);
console.log("Hex: %x", 255);
// Multiple arguments (up to 4)
console.log("From %s to %s: %d", from, to, amount);
// Type-specific
console.logBytes32(hash);
console.logAddress(token);
console.logBool(success);
```
### Debugging Pattern
```solidity
function test_Transfer() public {
console.log("=== Transfer ===");
console.log("From:", from);
console.log("To:", to);
console.log("Amount:", amount);
token.transfer(to, amount);
console.log("Balance after:", token.balanceOf(to));
}
```
## Breakpoints
Set breakpoints in code, jump to them in debugger:
```solidity
function test_Complex() public {
vm.breakpoint("start");
uint256 x = calculate();
vm.breakpoint("middle");
process(x);
vm.breakpoint("end");
}
```
In debugger, press `'` + letter to jump (e.g., `'a` for first breakpoint).
## Interactive Debugger
### Starting
```bash
# Debug specific test
forge test --debug --match-test "test_Function"
# Debug script
forge script script/Deploy.s.sol --debug
# Debug transaction from chain
cast run --debug 0x123...
```
### Debugger Layout
Four quadrants:
1. **Top-left**: EVM opcodes (current instruction highlighted)
2. **Top-right**: Stack state
3. **Bottom-left**: Solidity source code
4. **Bottom-right**: Memory contents
### Navigation Keys
**Movement:**
- `j/k`: Step forward/backward
- `g/G`: Go to beginning/end
- `c/C`: Next/previous CALL instruction
- `'a-z`: Jump to breakpoint
**Display:**
- `t`: Toggle stack labels
- `m`: Toggle memory as UTF8
- `h`: Help
- `q`: Quit
### Debugging Workflow
```bash
# 1. Test fails
forge test --match-test "test_Deposit"
# 2. See what failed
forge test -vvv --match-test "test_Deposit"
# 3. Add console.log for quick debugging
# OR use interactive debugger
forge test --debug --match-test "test_Deposit"
# 4. Step through with j/k, watch stack with t
```
## Gas Profiling
### Gas Reports
```bash
forge test --gas-report
```
Output:
```
│ Function │ min │ avg │ median │ max │ calls │
├─────────────┼───────┼───────┼────────┼───────┼───────┤
│ transfer │ 2900 │ 5234 │ 5200 │ 8901 │ 145 │
│ balanceOf │ 596 │ 596 │ 596 │ 596 │ 234 │
```
### Gas Snapshots
```bash
forge snapshot # Create snapshot
forge snapshot --diff # Compare to previous
forge snapshot --check # Fail if changed
```
### Inline Measurement
```solidity
function test_GasUsage() public {
uint256 gasBefore = gasleft();
contract.operation();
uint256 gasUsed = gasBefore - gasleft();
console.log("Gas used:", gasUsed);
}
```
## Common Error Patterns
### Assertion Failure
```
AssertionError: a == b
Expected: 1000000
Actual: 500000
```
**Debug:** Run with `-vvv` to trace calculation.
### Revert Without Message
```
Error: reverted
```
**Debug:**
1. Run with `-vvvv` for full trace
2. Find red (reverting) call in trace
3. Add console.log before suspect operations
### Out of Gas
```
Error: OutOfGas
```
**Fix:** Reduce loop iterations or split into batches.
### Custom Error
```solidity
vm.expectRevert(abi.encodeWithSelector(
InsufficientBalance.selector,
1000, // have
2000 // need
));
token.transfer(recipient, 2000);
```
## Best Practices
1. **Start simple**: Use console.log before --debug
2. **Isolate tests**: Test one thing per test function
3. **Use descriptive logs**: Log state at each step
4. **Check assumptions**: Verify preconditions
5. **Save traces**: `forge test -vvvv > trace.txt`