Files
mev-beta/pkg/calldata/swaps_payload_test.go
Krypto Kajun 850223a953 fix(multicall): resolve critical multicall parsing corruption issues
- Added comprehensive bounds checking to prevent buffer overruns in multicall parsing
- Implemented graduated validation system (Strict/Moderate/Permissive) to reduce false positives
- Added LRU caching system for address validation with 10-minute TTL
- Enhanced ABI decoder with missing Universal Router and Arbitrum-specific DEX signatures
- Fixed duplicate function declarations and import conflicts across multiple files
- Added error recovery mechanisms with multiple fallback strategies
- Updated tests to handle new validation behavior for suspicious addresses
- Fixed parser test expectations for improved validation system
- Applied gofmt formatting fixes to ensure code style compliance
- Fixed mutex copying issues in monitoring package by introducing MetricsSnapshot
- Resolved critical security vulnerabilities in heuristic address extraction
- Progress: Updated TODO audit from 10% to 35% complete

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-17 00:12:55 -05:00

176 lines
5.1 KiB
Go

package calldata
import (
"encoding/hex"
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
)
type payloadFixture struct {
Protocol string `json:"protocol"`
Function string `json:"function"`
FunctionSig string `json:"function_sig"`
InputData string `json:"input_data"`
}
func loadPayload(t *testing.T, name string) payloadFixture {
t.Helper()
fullPath := filepath.Join("testdata", "payloads", name)
raw, err := os.ReadFile(fullPath)
if err != nil {
t.Fatalf("failed to read payload fixture %s: %v", name, err)
}
var pf payloadFixture
if err := json.Unmarshal(raw, &pf); err != nil {
t.Fatalf("failed to unmarshal payload %s: %v", name, err)
}
return pf
}
func decodeDirect(raw []byte, ctx *MulticallContext) []*SwapCall {
validator := getAddressValidator()
return decodeSwapCallRecursive(raw, ctx, validator, 0)
}
func TestCapturedPayloadDecoding(t *testing.T) {
cases := []struct {
name string
fixture string
expectSwaps int
expectSelector string
tokenIn string
tokenOut string
verifyProtocol string
isMulticall bool
}{
{
name: "uniswap_v3_exact_output_single",
fixture: "uniswapv3_exact_output_single.json",
expectSwaps: 1,
expectSelector: "db3e2198",
tokenIn: "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8",
tokenOut: "0x912ce59144191c1204e64559fe8253a0e49e6548",
verifyProtocol: "UniswapV3",
},
{
name: "uniswap_v3_exact_input_single",
fixture: "uniswapv3_exact_input_single.json",
expectSwaps: 1,
expectSelector: "414bf389",
tokenIn: "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
tokenOut: "0x440017a1b021006d556d7fc06a54c32e42eb745b",
verifyProtocol: "UniswapV3",
},
{
name: "uniswap_v2_swap_exact_tokens",
fixture: "uniswapv2_exact_tokens.json",
expectSwaps: 1,
expectSelector: "38ed1739",
tokenIn: "0x03f6921f6e948016631ce796331294d5a863a9ee",
tokenOut: "0xdcc9691793633176acf5cfdc1a658cb3b982e2fb",
verifyProtocol: "UniswapV2",
},
{
name: "multicall_without_recognised_swaps",
fixture: "multicall_uniswap.json",
expectSwaps: 0,
isMulticall: true,
},
{
name: "uniswap_v3_decrease_liquidity",
fixture: "uniswapv3_decrease_liquidity.json",
expectSwaps: 0,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
payload := loadPayload(t, tc.fixture)
raw, err := hex.DecodeString(strings.TrimPrefix(payload.InputData, "0x"))
if err != nil {
t.Fatalf("failed to decode input data: %v", err)
}
if len(raw) < 4 {
t.Fatalf("payload too short: %d bytes", len(raw))
}
ctx := &MulticallContext{Protocol: payload.Protocol}
var swaps []*SwapCall
if tc.isMulticall {
swaps, err = DecodeSwapCallsFromMulticall(raw[4:], ctx)
if err != nil {
t.Fatalf("multicall decode failed: %v", err)
}
} else {
swaps = decodeDirect(raw, ctx)
}
if len(swaps) != tc.expectSwaps {
selector := strings.ToLower(hex.EncodeToString(raw[:4]))
if !tc.isMulticall {
// attempt direct decode based on selector for diagnostics
var diag *SwapCall
switch selector {
case "414bf389":
diag = decodeExactInputSingle(raw[4:], ctx)
case "db3e2198":
diag = decodeExactInput(raw[4:], ctx)
case "38ed1739":
diag = decodeUniswapV2Swap(selector, raw[4:], ctx)
}
if diag != nil {
t.Fatalf("expected %d swaps, got %d (selector=%s, diag=%s)", tc.expectSwaps, len(swaps), selector, diag.String())
}
}
t.Fatalf("expected %d swaps, got %d (selector=%s)", tc.expectSwaps, len(swaps), selector)
}
if tc.expectSwaps == 0 {
return
}
swap := swaps[0]
if !selectorsMatch(swap.Selector, tc.expectSelector) {
t.Fatalf("expected selector %s, got %s", tc.expectSelector, swap.Selector)
}
if !strings.EqualFold(swap.TokenIn.Hex(), tc.tokenIn) {
t.Fatalf("expected tokenIn %s, got %s", tc.tokenIn, swap.TokenIn.Hex())
}
if !strings.EqualFold(swap.TokenOut.Hex(), tc.tokenOut) {
t.Fatalf("expected tokenOut %s, got %s", tc.tokenOut, swap.TokenOut.Hex())
}
if tc.verifyProtocol != "" && !strings.EqualFold(swap.Protocol, tc.verifyProtocol) {
t.Fatalf("expected protocol %s, got %s", tc.verifyProtocol, swap.Protocol)
}
if selectorEquals(tc.expectSelector, "db3e2198") {
if swap.AmountOut == nil || swap.AmountOut.Sign() == 0 {
t.Fatalf("expected non-zero amountOut for exactOutputSingle")
}
}
if selectorEquals(tc.expectSelector, "414bf389") || selectorEquals(tc.expectSelector, "38ed1739") {
if swap.AmountIn == nil || swap.AmountIn.Sign() == 0 {
t.Fatalf("expected non-zero amountIn for selector %s", tc.expectSelector)
}
}
})
}
}
func normalizeSelectorHex(sel string) string {
s := strings.TrimSpace(strings.ToLower(sel))
return strings.TrimPrefix(s, "0x")
}
func selectorEquals(a, b string) bool {
return normalizeSelectorHex(a) == normalizeSelectorHex(b)
}
func selectorsMatch(actual, expected string) bool {
return selectorEquals(actual, expected)
}