feat: comprehensive audit infrastructure and Phase 1 refactoring
This commit includes: ## Audit & Testing Infrastructure - scripts/audit.sh: 12-section comprehensive codebase audit - scripts/test.sh: 7 test types (unit, integration, race, bench, coverage, contracts, pkg) - scripts/check-compliance.sh: SPEC.md compliance validation - scripts/check-docs.sh: Documentation coverage checker - scripts/dev.sh: Unified development script with all commands ## Documentation - SPEC.md: Authoritative technical specification - docs/AUDIT_AND_TESTING.md: Complete testing guide (600+ lines) - docs/SCRIPTS_REFERENCE.md: All scripts documented (700+ lines) - docs/README.md: Documentation index and navigation - docs/DEVELOPMENT_SETUP.md: Environment setup guide - docs/REFACTORING_PLAN.md: Systematic refactoring plan ## Phase 1 Refactoring (Critical Fixes) - pkg/validation/helpers.go: Validation functions for addresses/amounts - pkg/sequencer/selector_registry.go: Thread-safe selector registry - pkg/sequencer/reader.go: Fixed race conditions with atomic metrics - pkg/sequencer/swap_filter.go: Fixed race conditions, added error logging - pkg/sequencer/decoder.go: Added address validation ## Changes Summary - Fixed race conditions on 13 metric counters (atomic operations) - Added validation at all ingress points - Eliminated silent error handling - Created selector registry for future ABI migration - Reduced SPEC.md violations from 7 to 5 Build Status: ✅ All packages compile Compliance: ✅ No race conditions, no silent failures Documentation: ✅ 1,700+ lines across 5 comprehensive guides 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
193
bindings/README.md
Normal file
193
bindings/README.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# Contract Bindings
|
||||
|
||||
This directory contains Go bindings generated from DEX contract ABIs using `abigen`.
|
||||
|
||||
## Generated Bindings
|
||||
|
||||
### UniswapV2
|
||||
- **Router** (`uniswap_v2/router.go`): UniswapV2Router02 interface
|
||||
- `SwapExactTokensForTokens()`
|
||||
- `SwapTokensForExactTokens()`
|
||||
- `SwapExactETHForTokens()`
|
||||
- `SwapETHForExactTokens()`
|
||||
- `SwapExactTokensForETH()`
|
||||
- `SwapTokensForExactETH()`
|
||||
|
||||
- **Pair** (`uniswap_v2/pair.go`): UniswapV2Pair interface
|
||||
- `Swap()` - Direct pool swap function
|
||||
- `GetReserves()` - Get pool reserves
|
||||
- `Token0()`, `Token1()` - Get token addresses
|
||||
- Swap event for parsing logs
|
||||
|
||||
### UniswapV3
|
||||
- **Router** (`uniswap_v3/router.go`): SwapRouter interface
|
||||
- `ExactInputSingle()` - Single-hop exact input swap
|
||||
- `ExactInput()` - Multi-hop exact input swap
|
||||
- `ExactOutputSingle()` - Single-hop exact output swap
|
||||
- `ExactOutput()` - Multi-hop exact output swap
|
||||
|
||||
## Usage
|
||||
|
||||
### Detecting Swaps Using ABIs
|
||||
|
||||
Instead of hardcoding function selectors, use the generated bindings to parse transaction data:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/your-org/mev-bot/bindings/uniswap_v2"
|
||||
)
|
||||
|
||||
// Parse UniswapV2 router ABI
|
||||
routerABI, err := abi.JSON(strings.NewReader(uniswap_v2.UniswapV2RouterABI))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Detect swap function from calldata
|
||||
method, err := routerABI.MethodById(txData[:4])
|
||||
if err != nil {
|
||||
// Not a known method
|
||||
return
|
||||
}
|
||||
|
||||
// Check if it's a swap function
|
||||
isSwap := strings.Contains(method.Name, "swap") ||
|
||||
strings.Contains(method.Name, "Swap")
|
||||
|
||||
// Decode swap parameters
|
||||
if isSwap {
|
||||
params, err := method.Inputs.Unpack(txData[4:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Access typed parameters
|
||||
// For swapExactTokensForTokens: amountIn, amountOutMin, path, to, deadline
|
||||
amountIn := params[0].(*big.Int)
|
||||
path := params[2].([]common.Address)
|
||||
// ... etc
|
||||
}
|
||||
```
|
||||
|
||||
### Parsing Swap Events
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/your-org/mev-bot/bindings/uniswap_v2"
|
||||
)
|
||||
|
||||
// Parse swap event from logs
|
||||
pairABI, _ := abi.JSON(strings.NewReader(uniswap_v2.UniswapV2PairABI))
|
||||
|
||||
for _, log := range receipt.Logs {
|
||||
event, err := pairABI.EventByID(log.Topics[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if event.Name == "Swap" {
|
||||
// Decode swap event
|
||||
var swapEvent struct {
|
||||
Sender common.Address
|
||||
Amount0In *big.Int
|
||||
Amount1In *big.Int
|
||||
Amount0Out *big.Int
|
||||
Amount1Out *big.Int
|
||||
To common.Address
|
||||
}
|
||||
|
||||
err = pairABI.UnpackIntoInterface(&swapEvent, "Swap", log.Data)
|
||||
if err == nil {
|
||||
// Process swap event
|
||||
fmt.Printf("Swap: %s -> %s\n", swapEvent.Amount0In, swapEvent.Amount1Out)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Adding New Bindings
|
||||
|
||||
### 1. Create ABI File
|
||||
|
||||
Save the contract ABI in JSON format to the appropriate subdirectory:
|
||||
|
||||
```bash
|
||||
mkdir -p bindings/camelot
|
||||
# Create bindings/camelot/ICamelotRouter.json
|
||||
```
|
||||
|
||||
### 2. Generate Binding
|
||||
|
||||
Run `abigen` to generate Go code:
|
||||
|
||||
```bash
|
||||
podman exec mev-go-dev sh -c "cd /workspace && \
|
||||
/go/bin/abigen \
|
||||
--abi=bindings/camelot/ICamelotRouter.json \
|
||||
--pkg=camelot \
|
||||
--type=CamelotRouter \
|
||||
--out=bindings/camelot/router.go"
|
||||
```
|
||||
|
||||
### 3. Import in Your Code
|
||||
|
||||
```go
|
||||
import "github.com/your-org/mev-bot/bindings/camelot"
|
||||
|
||||
// Use the generated ABI
|
||||
routerABI, _ := abi.JSON(strings.NewReader(camelot.CamelotRouterABI))
|
||||
```
|
||||
|
||||
## ABI Sources
|
||||
|
||||
Contract ABIs can be obtained from:
|
||||
|
||||
1. **Etherscan/Arbiscan**: Verified contract → Contract → Code → Contract ABI
|
||||
2. **GitHub Repositories**: Official DEX repositories
|
||||
3. **npm Packages**: `@uniswap/v2-periphery`, `@uniswap/v3-periphery`, etc.
|
||||
|
||||
## Regenerating All Bindings
|
||||
|
||||
To regenerate all bindings after updating ABIs:
|
||||
|
||||
```bash
|
||||
./scripts/generate-bindings.sh
|
||||
```
|
||||
|
||||
Or manually:
|
||||
|
||||
```bash
|
||||
podman exec mev-go-dev sh -c "cd /workspace && \
|
||||
/go/bin/abigen --abi=bindings/uniswap_v2/IUniswapV2Router02.json \
|
||||
--pkg=uniswap_v2 \
|
||||
--type=UniswapV2Router \
|
||||
--out=bindings/uniswap_v2/router.go && \
|
||||
/go/bin/abigen --abi=bindings/uniswap_v2/IUniswapV2Pair.json \
|
||||
--pkg=uniswap_v2 \
|
||||
--type=UniswapV2Pair \
|
||||
--out=bindings/uniswap_v2/pair.go && \
|
||||
/go/bin/abigen --abi=bindings/uniswap_v3/ISwapRouter.json \
|
||||
--pkg=uniswap_v3 \
|
||||
--type=SwapRouter \
|
||||
--out=bindings/uniswap_v3/router.go"
|
||||
```
|
||||
|
||||
## Benefits of Using Bindings
|
||||
|
||||
1. **Type Safety**: Compile-time verification of parameters
|
||||
2. **No Hardcoded Selectors**: Function signatures derived from ABIs
|
||||
3. **Automatic Encoding/Decoding**: Built-in parameter packing/unpacking
|
||||
4. **Event Parsing**: Type-safe event decoding
|
||||
5. **Maintainability**: Single source of truth (ABI files)
|
||||
|
||||
## Next Steps
|
||||
|
||||
To fully integrate ABI-based swap detection:
|
||||
|
||||
1. Replace hardcoded selectors in `pkg/sequencer/decoder.go` with ABI lookups
|
||||
2. Use `MethodById()` to identify swap functions dynamically
|
||||
3. Parse swap parameters using typed binding structs
|
||||
4. Add bindings for Balancer, Curve, Kyber, Camelot
|
||||
5. Implement event-based swap detection for pools
|
||||
Reference in New Issue
Block a user