fix(critical): eliminate uint256 max overflow by fixing signed int256 parsing across all event parsers
This commit resolves the uint256 max overflow causing amounts to display as +11579208923... Root cause: UniswapV3 uses signed int256 for amounts, but multiple parsers treated them as unsigned Files fixed: - pkg/events/parser.go: Fixed broken signed int conversion (line 392-396) - pkg/pools/discovery.go: Added signed parsing for UniswapV3 (lines 415-420, 705-710) Impact: Eliminates e+59 to e+70 overflow values, enables accurate arbitrage calculations
This commit is contained in:
@@ -18,6 +18,27 @@ import (
|
|||||||
"github.com/fraktal/mev-beta/pkg/uniswap"
|
"github.com/fraktal/mev-beta/pkg/uniswap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// parseSignedInt256 correctly parses a signed 256-bit integer from 32 bytes
|
||||||
|
// This is critical for UniswapV3 events which use int256 for amounts
|
||||||
|
func parseSignedInt256(data []byte) *big.Int {
|
||||||
|
if len(data) != 32 {
|
||||||
|
return big.NewInt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
value := new(big.Int).SetBytes(data)
|
||||||
|
|
||||||
|
// Check if the value is negative (MSB set)
|
||||||
|
if len(data) > 0 && data[0]&0x80 != 0 {
|
||||||
|
// Convert from two's complement
|
||||||
|
// Subtract 2^256 to get the negative value
|
||||||
|
maxUint256 := new(big.Int)
|
||||||
|
maxUint256.Lsh(big.NewInt(1), 256)
|
||||||
|
value.Sub(value, maxUint256)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
// EventType represents the type of DEX event
|
// EventType represents the type of DEX event
|
||||||
type EventType int
|
type EventType int
|
||||||
|
|
||||||
@@ -388,21 +409,13 @@ func (ep *EventParser) parseUniswapV3Swap(log *types.Log, blockNumber uint64, ti
|
|||||||
return nil, fmt.Errorf("invalid Uniswap V3 Swap event log")
|
return nil, fmt.Errorf("invalid Uniswap V3 Swap event log")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the data fields
|
// Parse the data fields - UniswapV3 uses signed int256 for amounts
|
||||||
amount0 := new(big.Int).SetBytes(log.Data[0:32])
|
amount0 := parseSignedInt256(log.Data[0:32])
|
||||||
amount1 := new(big.Int).SetBytes(log.Data[32:64])
|
amount1 := parseSignedInt256(log.Data[32:64])
|
||||||
sqrtPriceX96 := new(big.Int).SetBytes(log.Data[64:96])
|
sqrtPriceX96 := new(big.Int).SetBytes(log.Data[64:96])
|
||||||
liquidity := new(big.Int).SetBytes(log.Data[96:128])
|
liquidity := new(big.Int).SetBytes(log.Data[96:128])
|
||||||
tick := new(big.Int).SetBytes(log.Data[128:160])
|
tick := new(big.Int).SetBytes(log.Data[128:160])
|
||||||
|
|
||||||
// Convert to signed values if needed
|
|
||||||
if amount0.Cmp(big.NewInt(0)) > 0x7fffffffffffffff {
|
|
||||||
amount0 = amount0.Sub(amount0, new(big.Int).Lsh(big.NewInt(1), 256))
|
|
||||||
}
|
|
||||||
if amount1.Cmp(big.NewInt(0)) > 0x7fffffffffffffff {
|
|
||||||
amount1 = amount1.Sub(amount1, new(big.Int).Lsh(big.NewInt(1), 256))
|
|
||||||
}
|
|
||||||
|
|
||||||
event := &Event{
|
event := &Event{
|
||||||
Type: Swap,
|
Type: Swap,
|
||||||
Protocol: "UniswapV3",
|
Protocol: "UniswapV3",
|
||||||
|
|||||||
@@ -21,6 +21,27 @@ import (
|
|||||||
"github.com/fraktal/mev-beta/pkg/uniswap"
|
"github.com/fraktal/mev-beta/pkg/uniswap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// parseSignedInt256 correctly parses a signed 256-bit integer from 32 bytes
|
||||||
|
// This is critical for UniswapV3 events which use int256 for amounts
|
||||||
|
func parseSignedInt256(data []byte) *big.Int {
|
||||||
|
if len(data) != 32 {
|
||||||
|
return big.NewInt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
value := new(big.Int).SetBytes(data)
|
||||||
|
|
||||||
|
// Check if the value is negative (MSB set)
|
||||||
|
if len(data) > 0 && data[0]&0x80 != 0 {
|
||||||
|
// Convert from two's complement
|
||||||
|
// Subtract 2^256 to get the negative value
|
||||||
|
maxUint256 := new(big.Int)
|
||||||
|
maxUint256.Lsh(big.NewInt(1), 256)
|
||||||
|
value.Sub(value, maxUint256)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
// Pool represents a discovered liquidity pool
|
// Pool represents a discovered liquidity pool
|
||||||
type Pool struct {
|
type Pool struct {
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
@@ -412,9 +433,12 @@ func (pd *PoolDiscovery) parseSwapData(data, protocol string) *SwapData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "UniswapV3":
|
case "UniswapV3":
|
||||||
// Uniswap V3 has different swap event structure
|
// Uniswap V3 uses signed int256 for amounts
|
||||||
amountIn = new(big.Int).SetBytes(dataBytes[0:32])
|
amountIn = parseSignedInt256(dataBytes[0:32])
|
||||||
amountOut = new(big.Int).SetBytes(dataBytes[32:64])
|
amountOut = parseSignedInt256(dataBytes[32:64])
|
||||||
|
// Convert to absolute values for display
|
||||||
|
amountIn = new(big.Int).Abs(amountIn)
|
||||||
|
amountOut = new(big.Int).Abs(amountOut)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Generic parsing
|
// Generic parsing
|
||||||
@@ -485,7 +509,7 @@ func (pd *PoolDiscovery) handleLiquidityEvent(poolAddress string, topics []inter
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
eventData := pd.parseLiquidityData(data, eventType)
|
eventData := pd.parseLiquidityData(data, eventType, pool.Protocol)
|
||||||
if eventData == nil {
|
if eventData == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -661,7 +685,7 @@ func (pd *PoolDiscovery) discoverPoolFromSwap(poolAddress, txHash string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseLiquidityData parses liquidity event data
|
// parseLiquidityData parses liquidity event data
|
||||||
func (pd *PoolDiscovery) parseLiquidityData(data, eventType string) *SwapData {
|
func (pd *PoolDiscovery) parseLiquidityData(data, eventType, protocol string) *SwapData {
|
||||||
if len(data) < 2 {
|
if len(data) < 2 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -675,8 +699,20 @@ func (pd *PoolDiscovery) parseLiquidityData(data, eventType string) *SwapData {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
amount0 := new(big.Int).SetBytes(dataBytes[0:32])
|
var amount0, amount1 *big.Int
|
||||||
amount1 := new(big.Int).SetBytes(dataBytes[32:64])
|
|
||||||
|
// UniswapV3 uses signed int256 for liquidity amounts
|
||||||
|
if protocol == "UniswapV3" {
|
||||||
|
amount0 = parseSignedInt256(dataBytes[0:32])
|
||||||
|
amount1 = parseSignedInt256(dataBytes[32:64])
|
||||||
|
// Convert to absolute values
|
||||||
|
amount0 = new(big.Int).Abs(amount0)
|
||||||
|
amount1 = new(big.Int).Abs(amount1)
|
||||||
|
} else {
|
||||||
|
// V2 and others use unsigned uint256
|
||||||
|
amount0 = new(big.Int).SetBytes(dataBytes[0:32])
|
||||||
|
amount1 = new(big.Int).SetBytes(dataBytes[32:64])
|
||||||
|
}
|
||||||
|
|
||||||
return &SwapData{
|
return &SwapData{
|
||||||
AmountIn: amount0,
|
AmountIn: amount0,
|
||||||
|
|||||||
Reference in New Issue
Block a user