mirror of
https://github.com/luxfi/indexer.git
synced 2026-10-30 14:45:22 +00:00
561 lines
17 KiB
Go
561 lines
17 KiB
Go
// Package defi provides EVM log parsers for DeFi protocol events.
|
|
package defi
|
|
|
|
import (
|
|
"math/big"
|
|
"strings"
|
|
)
|
|
|
|
// event topic0 signatures (keccak256 hashes).
|
|
//
|
|
// Source contracts:
|
|
// - contracts/liquidity/CrossChainDeFiRouter.sol
|
|
// - contracts/liquidity/oma/OMARouter.sol
|
|
// - contracts/liquidity/oma/LiquidityOracle.sol
|
|
// - contracts/liquidity/dex/QuantumSwap.sol
|
|
// - contracts/liquidity/bridges/IBridgeAggregator.sol
|
|
// - contracts/liquidity/UniversalLiquidityRouter.sol
|
|
const (
|
|
// CrossChainSwapInitiated(bytes32 indexed messageId, address indexed sender, uint256 srcChainId, uint256 dstChainId, address tokenIn, address tokenOut, uint256 amountIn, uint256 estimatedAmountOut)
|
|
TopicCrossChainSwapInitiated = "0x5aaedcb0fb0c21816765e0b386414c2c85eeb7765fadfd7b7aa9b7f9d9abddf2"
|
|
|
|
// CrossChainSwapCompleted(bytes32 indexed messageId, address indexed recipient, address tokenOut, uint256 amountOut, uint256 executionPrice)
|
|
TopicCrossChainSwapCompleted = "0xeb74b510f8fc32c7f5b72af5efaa1488dd2f74ade0a466a92f21fc9b7cc169d3"
|
|
|
|
// CrossChainLimitOrderPlaced(bytes32 indexed orderId, address indexed trader, uint256 dstChainId, uint256 limitPrice)
|
|
TopicCrossChainLimitOrderPlaced = "0x91c234ac4f6ccb650ecaac76ec6b4a82bf396e93eb17d48b9b8c6af7f598c1e2"
|
|
|
|
// ArbitrageExecuted(address indexed executor, uint256 profit, address[] tokens, uint256[] chainIds)
|
|
TopicArbitrageExecuted = "0x010e8d8d5d71cf26ef51d7559461890175f20dd77dbb89117e0028bb3dc92342"
|
|
|
|
// PoolAdded(address indexed pool, uint256 index)
|
|
TopicOMAPoolAdded = "0x0881f4d3b99fd7463802bc8dfe78c3e826bd94c68121556d11b49e06f220dc78"
|
|
|
|
// PoolRemoved(address indexed pool)
|
|
TopicOMAPoolRemoved = "0x02b80da32f14fb41765f573f6d1c813bfed50d91af7f5ad0574a4f9bd270e4e9"
|
|
|
|
// RouterSwap(address indexed user, string symbol, bool isBuy, uint256 amountIn, uint256 amountOut, uint256 poolUsed)
|
|
TopicOMARouterSwap = "0xf29e26d254cd060d81fd68a5d2efe203d9e49370263ecd160a0f3bd1a1dce165"
|
|
|
|
// PriceUpdated(bytes32 indexed symbolHash, uint256 price, uint256 timestamp)
|
|
TopicPriceUpdated = "0x11efda7380f42c6625ecf15268120374ee099aeacaa5e274bec7f077d9b33c64"
|
|
|
|
// PriceBatchUpdated(uint256 count, uint256 timestamp)
|
|
TopicPriceBatchUpdated = "0xc27b551ca3c95d62aa00caf660ed02e5b93186e1919ba64d0da5ced66ab81a84"
|
|
|
|
// StrategyOrderCreated(bytes32 indexed strategyId, address indexed trader, uint8 strategy, address tokenIn, address tokenOut, uint256 totalAmount)
|
|
TopicStrategyOrderCreated = "0xa1a4e96a7d80a17112b5ecc47ff7b3074699c0df90b0e129d78c8e1ceeafae57"
|
|
|
|
// StrategyOrderExecuted(bytes32 indexed strategyId, uint256 sliceFilled, uint256 slicePrice, uint256 remainingAmount)
|
|
TopicStrategyOrderExecuted = "0x98a7391f1a8bf9ba961298845aa4df36db2d639b8f4b1735ad0396bfdaba91f5"
|
|
|
|
// MarketMakingStarted(bytes32 indexed mmId, address indexed maker, address token0, address token1, uint256 spread)
|
|
TopicMarketMakingStarted = "0x7b4e38181afcf221c4e7952a9131cd6319cdd0d5844e2c282b769e7603edfdf0"
|
|
|
|
// MarketMakingQuote(bytes32 indexed mmId, uint256 bidPrice, uint256 bidSize, uint256 askPrice, uint256 askSize)
|
|
TopicMarketMakingQuote = "0x0d4540fce44355fc16f26f689a9a62a5b4c2248b7bd909ed208abad67b49c22d"
|
|
|
|
// BridgeInitiated(bytes32 indexed messageId, uint8 indexed protocol, uint256 srcChainId, uint256 dstChainId, address indexed sender, address recipient, address token, uint256 amount)
|
|
TopicBridgeInitiated = "0x361f7ab6c28983fd8675e656733a3bec1d29dae3567998b3d6a39e094c0a3d86"
|
|
|
|
// BridgeCompleted(bytes32 indexed messageId, uint8 indexed protocol, address indexed recipient, address token, uint256 amount)
|
|
TopicBridgeCompleted = "0xc14ac049648829462fa6d9aa5d76efcfa4e6f3c67fe6273529889734f1ab4edb"
|
|
|
|
// BridgeFailed(bytes32 indexed messageId, uint8 indexed protocol, string reason)
|
|
TopicBridgeFailed = "0xe467f664c0e3537dd585564069ba0752ce99770dd8111d79843ed7a78a898b83"
|
|
)
|
|
|
|
// LiquidityProtocolTopics returns all event topic0 strings.
|
|
func LiquidityProtocolTopics() []string {
|
|
return []string{
|
|
TopicCrossChainSwapInitiated,
|
|
TopicCrossChainSwapCompleted,
|
|
TopicCrossChainLimitOrderPlaced,
|
|
TopicArbitrageExecuted,
|
|
TopicOMAPoolAdded,
|
|
TopicOMAPoolRemoved,
|
|
TopicOMARouterSwap,
|
|
TopicPriceUpdated,
|
|
TopicPriceBatchUpdated,
|
|
TopicStrategyOrderCreated,
|
|
TopicStrategyOrderExecuted,
|
|
TopicMarketMakingStarted,
|
|
TopicMarketMakingQuote,
|
|
TopicBridgeInitiated,
|
|
TopicBridgeCompleted,
|
|
TopicBridgeFailed,
|
|
}
|
|
}
|
|
|
|
// OmniSwapEvent represents a parsed event.
|
|
type OmniSwapEvent struct {
|
|
Event string // event name
|
|
Contract string
|
|
Block uint64
|
|
TxHash string
|
|
|
|
// CrossChainSwapInitiated / Completed
|
|
MessageID string // bytes32 hex
|
|
Sender string
|
|
Recipient string
|
|
SrcChainID *big.Int
|
|
DstChainID *big.Int
|
|
TokenIn string
|
|
TokenOut string
|
|
AmountIn *big.Int
|
|
AmountOut *big.Int
|
|
ExecPrice *big.Int
|
|
|
|
// CrossChainLimitOrderPlaced
|
|
OrderID string
|
|
Trader string
|
|
LimitPrice *big.Int
|
|
|
|
// ArbitrageExecuted
|
|
Executor string
|
|
Profit *big.Int
|
|
|
|
// OMA Router
|
|
Pool string
|
|
Symbol string
|
|
IsBuy bool
|
|
PoolUsed *big.Int
|
|
|
|
// Oracle
|
|
SymbolHash string
|
|
Price *big.Int
|
|
Timestamp *big.Int
|
|
BatchCount *big.Int
|
|
|
|
// QuantumSwap strategy
|
|
StrategyID string
|
|
Strategy uint8
|
|
TotalAmt *big.Int
|
|
SliceFilled *big.Int
|
|
SlicePrice *big.Int
|
|
Remaining *big.Int
|
|
|
|
// Market making
|
|
MMID string
|
|
Maker string
|
|
Token0 string
|
|
Token1 string
|
|
Spread *big.Int
|
|
BidPrice *big.Int
|
|
BidSize *big.Int
|
|
AskPrice *big.Int
|
|
AskSize *big.Int
|
|
|
|
// Bridge
|
|
Protocol uint8
|
|
Token string
|
|
Amount *big.Int
|
|
Reason string
|
|
}
|
|
|
|
// ParseOmniSwapEvents extracts events from EVM logs.
|
|
func ParseOmniSwapEvents(logs []Log) []OmniSwapEvent {
|
|
var events []OmniSwapEvent
|
|
for i := range logs {
|
|
l := &logs[i]
|
|
if len(l.Topics) == 0 {
|
|
continue
|
|
}
|
|
switch l.Topics[0] {
|
|
case TopicCrossChainSwapInitiated:
|
|
if e := parseCrossChainSwapInitiated(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicCrossChainSwapCompleted:
|
|
if e := parseCrossChainSwapCompleted(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicCrossChainLimitOrderPlaced:
|
|
if e := parseCCLimitOrderPlaced(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicArbitrageExecuted:
|
|
if e := parseArbitrageExecuted(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicOMAPoolAdded:
|
|
if e := parseOMAPoolAdded(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicOMAPoolRemoved:
|
|
if e := parseOMAPoolRemoved(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicOMARouterSwap:
|
|
if e := parseOMARouterSwap(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicPriceUpdated:
|
|
if e := parsePriceUpdated(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicPriceBatchUpdated:
|
|
if e := parsePriceBatchUpdated(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicStrategyOrderCreated:
|
|
if e := parseStrategyOrderCreated(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicStrategyOrderExecuted:
|
|
if e := parseStrategyOrderExecuted(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicMarketMakingStarted:
|
|
if e := parseMarketMakingStarted(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicMarketMakingQuote:
|
|
if e := parseMarketMakingQuote(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicBridgeInitiated:
|
|
if e := parseBridgeInitiated(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicBridgeCompleted:
|
|
if e := parseBridgeCompleted(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
case TopicBridgeFailed:
|
|
if e := parseBridgeFailed(l); e != nil {
|
|
events = append(events, *e)
|
|
}
|
|
}
|
|
}
|
|
return events
|
|
}
|
|
|
|
// CrossChainSwapInitiated(bytes32 indexed messageId, address indexed sender, uint256 srcChainId, uint256 dstChainId, address tokenIn, address tokenOut, uint256 amountIn, uint256 estimatedAmountOut)
|
|
// data: srcChainId(0) | dstChainId(1) | tokenIn(2) | tokenOut(3) | amountIn(4) | estimatedAmountOut(5)
|
|
func parseCrossChainSwapInitiated(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 3 || len(l.Data) < 386 { // "0x" + 6*64
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "cross_chain_swap_initiated",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
MessageID: l.Topics[1],
|
|
Sender: topicAddress(l.Topics[2]),
|
|
SrcChainID: decodeWordStr(d, 0),
|
|
DstChainID: decodeWordStr(d, 1),
|
|
TokenIn: wordAddress(d, 2),
|
|
TokenOut: wordAddress(d, 3),
|
|
AmountIn: decodeWordStr(d, 4),
|
|
AmountOut: decodeWordStr(d, 5),
|
|
}
|
|
}
|
|
|
|
// CrossChainSwapCompleted(bytes32 indexed messageId, address indexed recipient, address tokenOut, uint256 amountOut, uint256 executionPrice)
|
|
func parseCrossChainSwapCompleted(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 3 || len(l.Data) < 194 { // "0x" + 3*64
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "cross_chain_swap_completed",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
MessageID: l.Topics[1],
|
|
Recipient: topicAddress(l.Topics[2]),
|
|
TokenOut: wordAddress(d, 0),
|
|
AmountOut: decodeWordStr(d, 1),
|
|
ExecPrice: decodeWordStr(d, 2),
|
|
}
|
|
}
|
|
|
|
// CrossChainLimitOrderPlaced(bytes32 indexed orderId, address indexed trader, uint256 dstChainId, uint256 limitPrice)
|
|
func parseCCLimitOrderPlaced(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 3 || len(l.Data) < 130 {
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "cross_chain_limit_order_placed",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
OrderID: l.Topics[1],
|
|
Trader: topicAddress(l.Topics[2]),
|
|
DstChainID: decodeWordStr(d, 0),
|
|
LimitPrice: decodeWordStr(d, 1),
|
|
}
|
|
}
|
|
|
|
// ArbitrageExecuted(address indexed executor, uint256 profit, address[] tokens, uint256[] chainIds)
|
|
func parseArbitrageExecuted(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 2 || len(l.Data) < 66 {
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "arbitrage_executed",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
Executor: topicAddress(l.Topics[1]),
|
|
Profit: decodeWordStr(d, 0),
|
|
}
|
|
}
|
|
|
|
// PoolAdded(address indexed pool, uint256 index)
|
|
func parseOMAPoolAdded(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 2 || len(l.Data) < 66 {
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "oma_pool_added",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
Pool: topicAddress(l.Topics[1]),
|
|
PoolUsed: decodeWordStr(d, 0),
|
|
}
|
|
}
|
|
|
|
// PoolRemoved(address indexed pool)
|
|
func parseOMAPoolRemoved(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 2 {
|
|
return nil
|
|
}
|
|
return &OmniSwapEvent{
|
|
Event: "oma_pool_removed",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
Pool: topicAddress(l.Topics[1]),
|
|
}
|
|
}
|
|
|
|
// RouterSwap(address indexed user, string symbol, bool isBuy, uint256 amountIn, uint256 amountOut, uint256 poolUsed)
|
|
// Dynamic types: string encoded with offset. data: offset(0) | isBuy(1) | amountIn(2) | amountOut(3) | poolUsed(4) | strLen(5) | strData(6+)
|
|
// Simplified: parse the numeric fields at known offsets.
|
|
func parseOMARouterSwap(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 2 || len(l.Data) < 322 { // 5 words min
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
isBuy := decodeWordStr(d, 1).Sign() > 0
|
|
return &OmniSwapEvent{
|
|
Event: "oma_router_swap",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
Sender: topicAddress(l.Topics[1]),
|
|
IsBuy: isBuy,
|
|
AmountIn: decodeWordStr(d, 2),
|
|
AmountOut: decodeWordStr(d, 3),
|
|
PoolUsed: decodeWordStr(d, 4),
|
|
}
|
|
}
|
|
|
|
// PriceUpdated(bytes32 indexed symbolHash, uint256 price, uint256 timestamp)
|
|
func parsePriceUpdated(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 2 || len(l.Data) < 130 {
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "price_updated",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
SymbolHash: l.Topics[1],
|
|
Price: decodeWordStr(d, 0),
|
|
Timestamp: decodeWordStr(d, 1),
|
|
}
|
|
}
|
|
|
|
// PriceBatchUpdated(uint256 count, uint256 timestamp)
|
|
func parsePriceBatchUpdated(l *Log) *OmniSwapEvent {
|
|
if len(l.Data) < 130 {
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "price_batch_updated",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
BatchCount: decodeWordStr(d, 0),
|
|
Timestamp: decodeWordStr(d, 1),
|
|
}
|
|
}
|
|
|
|
// StrategyOrderCreated(bytes32 indexed strategyId, address indexed trader, uint8 strategy, address tokenIn, address tokenOut, uint256 totalAmount)
|
|
func parseStrategyOrderCreated(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 3 || len(l.Data) < 258 { // 4 words
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "strategy_order_created",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
StrategyID: l.Topics[1],
|
|
Trader: topicAddress(l.Topics[2]),
|
|
Strategy: uint8(decodeWordStr(d, 0).Uint64()),
|
|
TokenIn: wordAddress(d, 1),
|
|
TokenOut: wordAddress(d, 2),
|
|
TotalAmt: decodeWordStr(d, 3),
|
|
}
|
|
}
|
|
|
|
// StrategyOrderExecuted(bytes32 indexed strategyId, uint256 sliceFilled, uint256 slicePrice, uint256 remainingAmount)
|
|
func parseStrategyOrderExecuted(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 2 || len(l.Data) < 194 {
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "strategy_order_executed",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
StrategyID: l.Topics[1],
|
|
SliceFilled: decodeWordStr(d, 0),
|
|
SlicePrice: decodeWordStr(d, 1),
|
|
Remaining: decodeWordStr(d, 2),
|
|
}
|
|
}
|
|
|
|
// MarketMakingStarted(bytes32 indexed mmId, address indexed maker, address token0, address token1, uint256 spread)
|
|
func parseMarketMakingStarted(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 3 || len(l.Data) < 194 {
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "market_making_started",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
MMID: l.Topics[1],
|
|
Maker: topicAddress(l.Topics[2]),
|
|
Token0: wordAddress(d, 0),
|
|
Token1: wordAddress(d, 1),
|
|
Spread: decodeWordStr(d, 2),
|
|
}
|
|
}
|
|
|
|
// MarketMakingQuote(bytes32 indexed mmId, uint256 bidPrice, uint256 bidSize, uint256 askPrice, uint256 askSize)
|
|
func parseMarketMakingQuote(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 2 || len(l.Data) < 258 {
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
return &OmniSwapEvent{
|
|
Event: "market_making_quote",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
MMID: l.Topics[1],
|
|
BidPrice: decodeWordStr(d, 0),
|
|
BidSize: decodeWordStr(d, 1),
|
|
AskPrice: decodeWordStr(d, 2),
|
|
AskSize: decodeWordStr(d, 3),
|
|
}
|
|
}
|
|
|
|
// BridgeInitiated(bytes32 indexed messageId, uint8 indexed protocol, uint256 srcChainId, uint256 dstChainId, address indexed sender, address recipient, address token, uint256 amount)
|
|
func parseBridgeInitiated(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 4 || len(l.Data) < 258 {
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
protocolBig := new(big.Int)
|
|
protocolBig.SetString(strings.TrimPrefix(l.Topics[2], "0x"), 16)
|
|
return &OmniSwapEvent{
|
|
Event: "bridge_initiated",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
MessageID: l.Topics[1],
|
|
Protocol: uint8(protocolBig.Uint64()),
|
|
Sender: topicAddress(l.Topics[3]),
|
|
SrcChainID: decodeWordStr(d, 0),
|
|
DstChainID: decodeWordStr(d, 1),
|
|
Recipient: wordAddress(d, 2),
|
|
Token: wordAddress(d, 3),
|
|
Amount: decodeWordStr(d, 4),
|
|
}
|
|
}
|
|
|
|
// BridgeCompleted(bytes32 indexed messageId, uint8 indexed protocol, address indexed recipient, address token, uint256 amount)
|
|
func parseBridgeCompleted(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 4 || len(l.Data) < 130 {
|
|
return nil
|
|
}
|
|
d := stripHexPrefix(l.Data)
|
|
protocolBig := new(big.Int)
|
|
protocolBig.SetString(strings.TrimPrefix(l.Topics[2], "0x"), 16)
|
|
return &OmniSwapEvent{
|
|
Event: "bridge_completed",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
MessageID: l.Topics[1],
|
|
Protocol: uint8(protocolBig.Uint64()),
|
|
Recipient: topicAddress(l.Topics[3]),
|
|
Token: wordAddress(d, 0),
|
|
Amount: decodeWordStr(d, 1),
|
|
}
|
|
}
|
|
|
|
// BridgeFailed(bytes32 indexed messageId, uint8 indexed protocol, string reason)
|
|
func parseBridgeFailed(l *Log) *OmniSwapEvent {
|
|
if len(l.Topics) < 3 {
|
|
return nil
|
|
}
|
|
protocolBig := new(big.Int)
|
|
protocolBig.SetString(strings.TrimPrefix(l.Topics[2], "0x"), 16)
|
|
return &OmniSwapEvent{
|
|
Event: "bridge_failed",
|
|
Contract: l.Address,
|
|
Block: l.BlockNumber,
|
|
TxHash: l.TxHash,
|
|
MessageID: l.Topics[1],
|
|
Protocol: uint8(protocolBig.Uint64()),
|
|
}
|
|
}
|
|
|
|
// helpers
|
|
|
|
func stripHexPrefix(s string) string {
|
|
if len(s) >= 2 && s[:2] == "0x" {
|
|
return s[2:]
|
|
}
|
|
return s
|
|
}
|
|
|
|
func decodeWordStr(hex string, idx int) *big.Int {
|
|
start := idx * 64
|
|
end := start + 64
|
|
if end > len(hex) {
|
|
return new(big.Int)
|
|
}
|
|
v := new(big.Int)
|
|
v.SetString(hex[start:end], 16)
|
|
return v
|
|
}
|
|
|
|
func wordAddress(hex string, idx int) string {
|
|
start := idx*64 + 24 // skip 12 zero bytes (24 hex chars)
|
|
end := start + 40
|
|
if end > len(hex) {
|
|
return ""
|
|
}
|
|
return "0x" + hex[start:end]
|
|
}
|