github.com/status-im/status-go@v1.1.0/services/wallet/common/log_parser.go (about) 1 // Moved here because transactions package depends on accounts package which 2 // depends on appdatabase where this functionality is needed 3 package common 4 5 import ( 6 "encoding/binary" 7 "fmt" 8 "math/big" 9 10 "github.com/ethereum/go-ethereum/common" 11 "github.com/ethereum/go-ethereum/core/types" 12 "github.com/ethereum/go-ethereum/crypto" 13 "github.com/ethereum/go-ethereum/log" 14 ) 15 16 // Type type of transaction 17 type Type string 18 19 // Log Event type 20 type EventType string 21 22 const ( 23 // Transaction types 24 EthTransfer Type = "eth" 25 Erc20Transfer Type = "erc20" 26 Erc721Transfer Type = "erc721" 27 Erc1155Transfer Type = "erc1155" 28 UniswapV2Swap Type = "uniswapV2Swap" 29 UniswapV3Swap Type = "uniswapV3Swap" 30 HopBridgeFrom Type = "HopBridgeFrom" 31 HopBridgeTo Type = "HopBridgeTo" 32 unknownTransaction Type = "unknown" 33 34 // Event types 35 WETHDepositEventType EventType = "wethDepositEvent" 36 WETHWithdrawalEventType EventType = "wethWithdrawalEvent" 37 Erc20TransferEventType EventType = "erc20Event" 38 Erc721TransferEventType EventType = "erc721Event" 39 Erc1155TransferSingleEventType EventType = "erc1155SingleEvent" 40 Erc1155TransferBatchEventType EventType = "erc1155BatchEvent" 41 UniswapV2SwapEventType EventType = "uniswapV2SwapEvent" 42 UniswapV3SwapEventType EventType = "uniswapV3SwapEvent" 43 HopBridgeTransferSentToL2EventType EventType = "hopBridgeTransferSentToL2Event" 44 HopBridgeTransferFromL1CompletedEventType EventType = "hopBridgeTransferFromL1CompletedEvent" 45 HopBridgeWithdrawalBondedEventType EventType = "hopBridgeWithdrawalBondedEvent" 46 HopBridgeTransferSentEventType EventType = "hopBridgeTransferSentEvent" 47 UnknownEventType EventType = "unknownEvent" 48 49 // Deposit (index_topic_1 address dst, uint256 wad) 50 wethDepositEventSignature = "Deposit(address,uint256)" 51 // Withdrawal (index_topic_1 address src, uint256 wad) 52 wethWithdrawalEventSignature = "Withdrawal(address,uint256)" 53 54 // Transfer (index_topic_1 address from, index_topic_2 address to, uint256 value) 55 // Transfer (index_topic_1 address from, index_topic_2 address to, index_topic_3 uint256 tokenId) 56 Erc20_721TransferEventSignature = "Transfer(address,address,uint256)" 57 Erc1155TransferSingleEventSignature = "TransferSingle(address,address,address,uint256,uint256)" // operator, from, to, id, value 58 Erc1155TransferBatchEventSignature = "TransferBatch(address,address,address,uint256[],uint256[])" // operator, from, to, ids, values 59 60 erc20TransferEventIndexedParameters = 3 // signature, from, to 61 erc721TransferEventIndexedParameters = 4 // signature, from, to, tokenId 62 erc1155TransferEventIndexedParameters = 4 // signature, operator, from, to (id, value are not indexed) 63 64 // Swap (index_topic_1 address sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, index_topic_2 address to) 65 uniswapV2SwapEventSignature = "Swap(address,uint256,uint256,uint256,uint256,address)" // also used by SushiSwap 66 // Swap (index_topic_1 address sender, index_topic_2 address recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick) 67 uniswapV3SwapEventSignature = "Swap(address,address,int256,int256,uint160,uint128,int24)" 68 69 // TransferSentToL2 (index_topic_1 uint256 chainId, index_topic_2 address recipient, uint256 amount, uint256 amountOutMin, uint256 deadline, index_topic_3 address relayer, uint256 relayerFee) 70 hopBridgeTransferSentToL2EventSignature = "TransferSentToL2(uint256,address,uint256,uint256,uint256,address,uint256)" 71 // TransferFromL1Completed (index_topic_1 address recipient, uint256 amount, uint256 amountOutMin, uint256 deadline, index_topic_2 address relayer, uint256 relayerFee) 72 HopBridgeTransferFromL1CompletedEventSignature = "TransferFromL1Completed(address,uint256,uint256,uint256,address,uint256)" 73 // WithdrawalBonded (index_topic_1 bytes32 transferID, uint256 amount) 74 hopBridgeWithdrawalBondedEventSignature = "WithdrawalBonded(bytes32,uint256)" 75 // TransferSent (index_topic_1 bytes32 transferID, index_topic_2 uint256 chainId, index_topic_3 address recipient, uint256 amount, bytes32 transferNonce, uint256 bonderFee, uint256 index, uint256 amountOutMin, uint256 deadline) 76 hopBridgeTransferSentEventSignature = "TransferSent(bytes32,uint256,address,uint256,bytes32,uint256,uint256,uint256,uint256)" 77 ) 78 79 var ( 80 // MaxUint256 is the maximum value that can be represented by a uint256. 81 MaxUint256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1) 82 ) 83 84 // Detect event type for a cetain item from the Events Log 85 func GetEventType(log *types.Log) EventType { 86 wethDepositEventSignatureHash := GetEventSignatureHash(wethDepositEventSignature) 87 wethWithdrawalEventSignatureHash := GetEventSignatureHash(wethWithdrawalEventSignature) 88 erc20_721TransferEventSignatureHash := GetEventSignatureHash(Erc20_721TransferEventSignature) 89 erc1155TransferSingleEventSignatureHash := GetEventSignatureHash(Erc1155TransferSingleEventSignature) 90 erc1155TransferBatchEventSignatureHash := GetEventSignatureHash(Erc1155TransferBatchEventSignature) 91 uniswapV2SwapEventSignatureHash := GetEventSignatureHash(uniswapV2SwapEventSignature) 92 uniswapV3SwapEventSignatureHash := GetEventSignatureHash(uniswapV3SwapEventSignature) 93 hopBridgeTransferSentToL2EventSignatureHash := GetEventSignatureHash(hopBridgeTransferSentToL2EventSignature) 94 hopBridgeTransferFromL1CompletedEventSignatureHash := GetEventSignatureHash(HopBridgeTransferFromL1CompletedEventSignature) 95 hopBridgeWithdrawalBondedEventSignatureHash := GetEventSignatureHash(hopBridgeWithdrawalBondedEventSignature) 96 hopBridgeTransferSentEventSignatureHash := GetEventSignatureHash(hopBridgeTransferSentEventSignature) 97 98 if len(log.Topics) > 0 { 99 switch log.Topics[0] { 100 case wethDepositEventSignatureHash: 101 return WETHDepositEventType 102 case wethWithdrawalEventSignatureHash: 103 return WETHWithdrawalEventType 104 case erc20_721TransferEventSignatureHash: 105 switch len(log.Topics) { 106 case erc20TransferEventIndexedParameters: 107 return Erc20TransferEventType 108 case erc721TransferEventIndexedParameters: 109 return Erc721TransferEventType 110 } 111 case erc1155TransferSingleEventSignatureHash: 112 return Erc1155TransferSingleEventType 113 case erc1155TransferBatchEventSignatureHash: 114 return Erc1155TransferBatchEventType 115 case uniswapV2SwapEventSignatureHash: 116 return UniswapV2SwapEventType 117 case uniswapV3SwapEventSignatureHash: 118 return UniswapV3SwapEventType 119 case hopBridgeTransferSentToL2EventSignatureHash: 120 return HopBridgeTransferSentToL2EventType 121 case hopBridgeTransferFromL1CompletedEventSignatureHash: 122 return HopBridgeTransferFromL1CompletedEventType 123 case hopBridgeWithdrawalBondedEventSignatureHash: 124 return HopBridgeWithdrawalBondedEventType 125 case hopBridgeTransferSentEventSignatureHash: 126 return HopBridgeTransferSentEventType 127 } 128 } 129 130 return UnknownEventType 131 } 132 133 func EventTypeToSubtransactionType(eventType EventType) Type { 134 switch eventType { 135 case Erc20TransferEventType: 136 return Erc20Transfer 137 case Erc721TransferEventType: 138 return Erc721Transfer 139 case Erc1155TransferSingleEventType, Erc1155TransferBatchEventType: 140 return Erc1155Transfer 141 case UniswapV2SwapEventType: 142 return UniswapV2Swap 143 case UniswapV3SwapEventType: 144 return UniswapV3Swap 145 case HopBridgeTransferSentToL2EventType, HopBridgeTransferSentEventType: 146 return HopBridgeFrom 147 case HopBridgeTransferFromL1CompletedEventType, HopBridgeWithdrawalBondedEventType: 148 return HopBridgeTo 149 } 150 151 return unknownTransaction 152 } 153 154 func GetFirstEvent(logs []*types.Log) (EventType, *types.Log) { 155 for _, log := range logs { 156 eventType := GetEventType(log) 157 if eventType != UnknownEventType { 158 return eventType, log 159 } 160 } 161 162 return UnknownEventType, nil 163 } 164 165 func IsTokenTransfer(logs []*types.Log) bool { 166 eventType, _ := GetFirstEvent(logs) 167 switch eventType { 168 case Erc20TransferEventType, Erc721TransferEventType, Erc1155TransferSingleEventType, Erc1155TransferBatchEventType: 169 return true 170 } 171 172 return false 173 } 174 175 func ParseWETHDepositLog(ethlog *types.Log) (src common.Address, amount *big.Int) { 176 amount = new(big.Int) 177 178 if len(ethlog.Topics) < 2 { 179 log.Warn("not enough topics for WETH deposit", "topics", ethlog.Topics) 180 return 181 } 182 183 if len(ethlog.Topics[1]) != 32 { 184 log.Warn("second topic is not padded to 32 byte address", "topic", ethlog.Topics[1]) 185 return 186 } 187 copy(src[:], ethlog.Topics[1][12:]) 188 189 if len(ethlog.Data) != 32 { 190 log.Warn("data is not padded to 32 byte big int", "data", ethlog.Data) 191 return 192 } 193 amount.SetBytes(ethlog.Data) 194 195 return 196 } 197 198 func ParseWETHWithdrawLog(ethlog *types.Log) (dst common.Address, amount *big.Int) { 199 amount = new(big.Int) 200 201 if len(ethlog.Topics) < 2 { 202 log.Warn("not enough topics for WETH withdraw", "topics", ethlog.Topics) 203 return 204 } 205 206 if len(ethlog.Topics[1]) != 32 { 207 log.Warn("second topic is not padded to 32 byte address", "topic", ethlog.Topics[1]) 208 return 209 } 210 copy(dst[:], ethlog.Topics[1][12:]) 211 212 if len(ethlog.Data) != 32 { 213 log.Warn("data is not padded to 32 byte big int", "data", ethlog.Data) 214 return 215 } 216 amount.SetBytes(ethlog.Data) 217 218 return 219 } 220 221 func ParseErc20TransferLog(ethlog *types.Log) (from, to common.Address, amount *big.Int) { 222 amount = new(big.Int) 223 if len(ethlog.Topics) < erc20TransferEventIndexedParameters { 224 log.Warn("not enough topics for erc20 transfer", "topics", ethlog.Topics) 225 return 226 } 227 var err error 228 from, to, err = getFromToAddresses(*ethlog) 229 if err != nil { 230 log.Error("log_parser::ParseErc20TransferLog", err) 231 return 232 } 233 234 if len(ethlog.Data) != 32 { 235 log.Warn("data is not padded to 32 byts big int", "data", ethlog.Data) 236 return 237 } 238 amount.SetBytes(ethlog.Data) 239 240 return 241 } 242 243 func ParseErc721TransferLog(ethlog *types.Log) (from, to common.Address, tokenID *big.Int) { 244 tokenID = new(big.Int) 245 if len(ethlog.Topics) < erc721TransferEventIndexedParameters { 246 log.Warn("not enough topics for erc721 transfer", "topics", ethlog.Topics) 247 return 248 } 249 250 var err error 251 from, to, err = getFromToAddresses(*ethlog) 252 if err != nil { 253 log.Error("log_parser::ParseErc721TransferLog", err) 254 return 255 } 256 tokenID.SetBytes(ethlog.Topics[3][:]) 257 258 return 259 } 260 261 func GetLogSubTxID(log types.Log) common.Hash { 262 // Get unique ID by using TxHash and log index 263 index := [4]byte{} 264 binary.BigEndian.PutUint32(index[:], uint32(log.Index)) 265 return crypto.Keccak256Hash(log.TxHash.Bytes(), index[:]) 266 } 267 268 func getLogSubTxIDWithTokenIDIndex(log types.Log, tokenIDIdx uint16) common.Hash { 269 // Get unique ID by using TxHash, log index and extra bytes (token id index for ERC1155 TransferBatch) 270 index := [4]byte{} 271 value := uint32(log.Index&0x0000FFFF) | (uint32(tokenIDIdx) << 16) // log index should not exceed uint16 max value 272 binary.BigEndian.PutUint32(index[:], value) 273 return crypto.Keccak256Hash(log.TxHash.Bytes(), index[:]) 274 } 275 276 func checkTopicsLength(ethlog types.Log, startIdx, endIdx int) (err error) { 277 for i := startIdx; i < endIdx; i++ { 278 if len(ethlog.Topics[i]) != common.HashLength { 279 err = fmt.Errorf("topic %d is not padded to %d byte address, topic=%s", i, common.HashLength, ethlog.Topics[i]) 280 log.Error("log_parser::checkTopicsLength", err) 281 return 282 } 283 } 284 return 285 } 286 287 func getFromToAddresses(ethlog types.Log) (from, to common.Address, err error) { 288 eventType := GetEventType(ðlog) 289 addressIdx := common.HashLength - common.AddressLength 290 switch eventType { 291 case Erc1155TransferSingleEventType, Erc1155TransferBatchEventType: 292 err = checkTopicsLength(ethlog, 2, 4) 293 if err != nil { 294 return 295 } 296 copy(from[:], ethlog.Topics[2][addressIdx:]) 297 copy(to[:], ethlog.Topics[3][addressIdx:]) 298 return 299 300 case Erc20TransferEventType, Erc721TransferEventType, UniswapV2SwapEventType, UniswapV3SwapEventType, HopBridgeTransferFromL1CompletedEventType: 301 err = checkTopicsLength(ethlog, 1, 3) 302 if err != nil { 303 return 304 } 305 copy(from[:], ethlog.Topics[1][addressIdx:]) 306 copy(to[:], ethlog.Topics[2][addressIdx:]) 307 return 308 } 309 310 return from, to, fmt.Errorf("unsupported event type to get from/to adddresses %s", eventType) 311 } 312 func ParseTransferLog(ethlog types.Log) (from, to common.Address, txIDs []common.Hash, tokenIDs, values []*big.Int, err error) { 313 eventType := GetEventType(ðlog) 314 315 switch eventType { 316 case Erc20TransferEventType: 317 var amount *big.Int 318 from, to, amount = ParseErc20TransferLog(ðlog) 319 txIDs = append(txIDs, GetLogSubTxID(ethlog)) 320 values = append(values, amount) 321 return 322 case Erc721TransferEventType: 323 var tokenID *big.Int 324 from, to, tokenID = ParseErc721TransferLog(ðlog) 325 txIDs = append(txIDs, GetLogSubTxID(ethlog)) 326 tokenIDs = append(tokenIDs, tokenID) 327 values = append(values, big.NewInt(1)) 328 return 329 case Erc1155TransferSingleEventType, Erc1155TransferBatchEventType: 330 _, from, to, tokenIDs, values, err = ParseErc1155TransferLog(ðlog, eventType) 331 for i := range tokenIDs { 332 txIDs = append(txIDs, getLogSubTxIDWithTokenIDIndex(ethlog, uint16(i))) 333 } 334 return 335 } 336 337 return from, to, txIDs, tokenIDs, values, fmt.Errorf("unsupported event type in log_parser::ParseTransferLogs %s", eventType) 338 } 339 340 func ParseErc1155TransferLog(ethlog *types.Log, evType EventType) (operator, from, to common.Address, ids, amounts []*big.Int, err error) { 341 if len(ethlog.Topics) < erc1155TransferEventIndexedParameters { 342 err = fmt.Errorf("not enough topics for erc1155 transfer %s, %v", "topics", ethlog.Topics) 343 log.Error("log_parser::ParseErc1155TransferLog", "err", err) 344 return 345 } 346 347 err = checkTopicsLength(*ethlog, 1, erc1155TransferEventIndexedParameters) 348 if err != nil { 349 return 350 } 351 352 addressIdx := common.HashLength - common.AddressLength 353 copy(operator[:], ethlog.Topics[1][addressIdx:]) 354 from, to, err = getFromToAddresses(*ethlog) 355 if err != nil { 356 log.Error("log_parser::ParseErc1155TransferLog", "err", err) 357 return 358 } 359 360 if len(ethlog.Data) == 0 || len(ethlog.Data)%(common.HashLength*2) != 0 { 361 err = fmt.Errorf("data is not padded to 64 bytes %s, %v", "data", ethlog.Data) 362 log.Error("log_parser::ParseErc1155TransferLog", "err", err) 363 return 364 } 365 366 if evType == Erc1155TransferSingleEventType { 367 ids = append(ids, new(big.Int).SetBytes(ethlog.Data[:common.HashLength])) 368 amounts = append(amounts, new(big.Int).SetBytes(ethlog.Data[common.HashLength:])) 369 log.Debug("log_parser::ParseErc1155TransferSingleLog", "ids", ids, "amounts", amounts) 370 } else { 371 // idTypeSize := new(big.Int).SetBytes(ethlog.Data[:common.HashLength]).Uint64() // Left for knowledge 372 // valueTypeSize := new(big.Int).SetBytes(ethlog.Data[common.HashLength : common.HashLength*2]).Uint64() // Left for knowledge 373 idsArraySize := new(big.Int).SetBytes(ethlog.Data[common.HashLength*2 : common.HashLength*2+common.HashLength]).Uint64() 374 375 initialOffset := common.HashLength*2 + common.HashLength 376 for i := 0; i < int(idsArraySize); i++ { 377 ids = append(ids, new(big.Int).SetBytes(ethlog.Data[initialOffset+i*common.HashLength:initialOffset+(i+1)*common.HashLength])) 378 } 379 valuesArraySize := new(big.Int).SetBytes(ethlog.Data[initialOffset+int(idsArraySize)*common.HashLength : initialOffset+int(idsArraySize+1)*common.HashLength]).Uint64() 380 381 if idsArraySize != valuesArraySize { 382 err = fmt.Errorf("ids and values sizes don't match %d, %d", idsArraySize, valuesArraySize) 383 log.Error("log_parser::ParseErc1155TransferBatchLog", "err", err) 384 return 385 } 386 387 initialOffset = initialOffset + int(idsArraySize+1)*common.HashLength 388 for i := 0; i < int(valuesArraySize); i++ { 389 amounts = append(amounts, new(big.Int).SetBytes(ethlog.Data[initialOffset+i*common.HashLength:initialOffset+(i+1)*common.HashLength])) 390 log.Debug("log_parser::ParseErc1155TransferBatchLog", "id", ids[i], "amount", amounts[i]) 391 } 392 } 393 394 return 395 } 396 397 func ParseUniswapV2Log(ethlog *types.Log) (pairAddress common.Address, from common.Address, to common.Address, amount0In *big.Int, amount1In *big.Int, amount0Out *big.Int, amount1Out *big.Int, err error) { 398 amount0In = new(big.Int) 399 amount1In = new(big.Int) 400 amount0Out = new(big.Int) 401 amount1Out = new(big.Int) 402 403 if len(ethlog.Topics) < 3 { 404 err = fmt.Errorf("not enough topics for uniswapV2 swap %s, %v", "topics", ethlog.Topics) 405 return 406 } 407 408 pairAddress = ethlog.Address 409 from, to, err = getFromToAddresses(*ethlog) 410 if err != nil { 411 log.Error("log_parser::ParseUniswapV2Log", err) 412 return 413 } 414 if len(ethlog.Data) != 32*4 { 415 err = fmt.Errorf("data is not padded to 4 * 32 bytes big int %s, %v", "data", ethlog.Data) 416 return 417 } 418 amount0In.SetBytes(ethlog.Data[0:32]) 419 amount1In.SetBytes(ethlog.Data[32:64]) 420 amount0Out.SetBytes(ethlog.Data[64:96]) 421 amount1Out.SetBytes(ethlog.Data[96:128]) 422 423 return 424 } 425 426 func readInt256(b []byte) *big.Int { 427 // big.SetBytes can't tell if a number is negative or positive in itself. 428 // On EVM, if the returned number > max int256, it is negative. 429 // A number is > max int256 if the bit at position 255 is set. 430 ret := new(big.Int).SetBytes(b) 431 if ret.Bit(255) == 1 { 432 ret.Add(MaxUint256, new(big.Int).Neg(ret)) 433 ret.Add(ret, common.Big1) 434 ret.Neg(ret) 435 } 436 return ret 437 } 438 439 func ParseUniswapV3Log(ethlog *types.Log) (poolAddress common.Address, sender common.Address, recipient common.Address, amount0 *big.Int, amount1 *big.Int, err error) { 440 amount0 = new(big.Int) 441 amount1 = new(big.Int) 442 443 if len(ethlog.Topics) < 3 { 444 err = fmt.Errorf("not enough topics for uniswapV3 swap %s, %v", "topics", ethlog.Topics) 445 return 446 } 447 448 poolAddress = ethlog.Address 449 sender, recipient, err = getFromToAddresses(*ethlog) 450 if err != nil { 451 log.Error("log_parser::ParseUniswapV3Log", err) 452 return 453 } 454 if len(ethlog.Data) != 32*5 { 455 err = fmt.Errorf("data is not padded to 5 * 32 bytes big int %s, %v", "data", ethlog.Data) 456 return 457 } 458 amount0 = readInt256(ethlog.Data[0:32]) 459 amount1 = readInt256(ethlog.Data[32:64]) 460 461 return 462 } 463 464 func ParseHopBridgeTransferSentToL2Log(ethlog *types.Log) (chainID uint64, recipient common.Address, relayer common.Address, amount *big.Int, err error) { 465 chainIDInt := new(big.Int) 466 amount = new(big.Int) 467 468 if len(ethlog.Topics) < 4 { 469 err = fmt.Errorf("not enough topics for HopBridgeTransferSentToL2 event %s, %v", "topics", ethlog.Topics) 470 return 471 } 472 473 if len(ethlog.Topics[1]) != 32 { 474 err = fmt.Errorf("second topic is not padded to 32 byte address %s, %v", "topic", ethlog.Topics[1]) 475 return 476 } 477 chainIDInt.SetBytes(ethlog.Topics[1][:]) 478 chainID = chainIDInt.Uint64() 479 480 if len(ethlog.Topics[2]) != 32 { 481 err = fmt.Errorf("third topic is not padded to 32 byte address %s, %v", "topic", ethlog.Topics[2]) 482 return 483 } 484 copy(recipient[:], ethlog.Topics[2][12:]) 485 486 if len(ethlog.Topics[3]) != 32 { 487 err = fmt.Errorf("fourth topic is not padded to 32 byte address %s, %v", "topic", ethlog.Topics[3]) 488 return 489 } 490 copy(relayer[:], ethlog.Topics[3][12:]) 491 492 if len(ethlog.Data) != 32*4 { 493 err = fmt.Errorf("data is not padded to 4 * 32 bytes big int %s, %v", "data", ethlog.Data) 494 return 495 } 496 497 amount.SetBytes(ethlog.Data[0:32]) 498 499 return 500 } 501 502 func ParseHopBridgeTransferFromL1CompletedLog(ethlog *types.Log) (recipient common.Address, relayer common.Address, amount *big.Int, err error) { 503 amount = new(big.Int) 504 505 if len(ethlog.Topics) < 3 { 506 err = fmt.Errorf("not enough topics for HopBridgeTransferFromL1Completed event %s, %v", "topics", ethlog.Topics) 507 return 508 } 509 510 recipient, relayer, err = getFromToAddresses(*ethlog) 511 if err != nil { 512 log.Error("log_parser::ParseHopBridgeTransferFromL1CompletedLog", err) 513 return 514 } 515 516 if len(ethlog.Data) != 32*4 { 517 err = fmt.Errorf("data is not padded to 4 * 32 bytes big int %s, %v", "data", ethlog.Data) 518 return 519 } 520 521 amount.SetBytes(ethlog.Data[0:32]) 522 523 return 524 } 525 526 func ParseHopWithdrawalBondedLog(ethlog *types.Log) (transferID *big.Int, amount *big.Int, err error) { 527 transferID = new(big.Int) 528 amount = new(big.Int) 529 530 if len(ethlog.Topics) < 2 { 531 err = fmt.Errorf("not enough topics for HopWithdrawalBonded event %s, %v", "topics", ethlog.Topics) 532 return 533 } 534 535 if len(ethlog.Topics[1]) != 32 { 536 err = fmt.Errorf("second topic is not padded to 32 byte address %s, %v", "topic", ethlog.Topics[1]) 537 return 538 } 539 transferID.SetBytes(ethlog.Topics[1][:]) 540 541 if len(ethlog.Data) != 32*1 { 542 err = fmt.Errorf("data is not padded to 1 * 32 bytes big int %s, %v", "data", ethlog.Data) 543 return 544 } 545 546 amount.SetBytes(ethlog.Data[0:32]) 547 548 return 549 } 550 551 func ParseHopBridgeTransferSentLog(ethlog *types.Log) (transferID *big.Int, chainID uint64, recipient common.Address, amount *big.Int, transferNonce *big.Int, bonderFee *big.Int, index *big.Int, amountOutMin *big.Int, deadline *big.Int, err error) { 552 transferID = new(big.Int) 553 chainIDInt := new(big.Int) 554 amount = new(big.Int) 555 transferNonce = new(big.Int) 556 bonderFee = new(big.Int) 557 index = new(big.Int) 558 amountOutMin = new(big.Int) 559 deadline = new(big.Int) 560 561 if len(ethlog.Topics) < 4 { 562 err = fmt.Errorf("not enough topics for HopBridgeTransferSent event %s, %v", "topics", ethlog.Topics) 563 return 564 } 565 566 if len(ethlog.Topics[1]) != 32 { 567 err = fmt.Errorf("second topic is not padded to 32 byte big int %s, %v", "topic", ethlog.Topics[1]) 568 return 569 } 570 transferID.SetBytes(ethlog.Topics[1][:]) 571 572 if len(ethlog.Topics[2]) != 32 { 573 err = fmt.Errorf("third topic is not padded to 32 byte big int %s, %v", "topic", ethlog.Topics[2]) 574 return 575 } 576 chainIDInt.SetBytes(ethlog.Topics[2][:]) 577 chainID = chainIDInt.Uint64() 578 579 if len(ethlog.Topics[3]) != 32 { 580 err = fmt.Errorf("fourth topic is not padded to 32 byte address %s, %v", "topic", ethlog.Topics[3]) 581 return 582 } 583 copy(recipient[:], ethlog.Topics[2][12:]) 584 585 if len(ethlog.Data) != 32*6 { 586 err = fmt.Errorf("data is not padded to 6 * 32 bytes big int %s, %v", "data", ethlog.Data) 587 return 588 } 589 590 amount.SetBytes(ethlog.Data[0:32]) 591 transferNonce.SetBytes(ethlog.Data[32:64]) 592 bonderFee.SetBytes(ethlog.Data[64:96]) 593 index.SetBytes(ethlog.Data[96:128]) 594 amountOutMin.SetBytes(ethlog.Data[128:160]) 595 deadline.SetBytes(ethlog.Data[160:192]) 596 597 return 598 } 599 600 func GetEventSignatureHash(signature string) common.Hash { 601 return crypto.Keccak256Hash([]byte(signature)) 602 } 603 604 func ExtractTokenTransferData(dbEntryType Type, log *types.Log, tx *types.Transaction) (correctType Type, tokenAddress *common.Address, txFrom *common.Address, txTo *common.Address) { 605 // erc721 transfers share signature with erc20 ones, so they both used to be categorized as erc20 606 // by the Downloader. We fix this here since they might be mis-categorized in the db. 607 if dbEntryType == Erc20Transfer { 608 eventType := GetEventType(log) 609 correctType = EventTypeToSubtransactionType(eventType) 610 } else { 611 correctType = dbEntryType 612 } 613 614 switch correctType { 615 case Erc20Transfer: 616 tokenAddress = new(common.Address) 617 *tokenAddress = log.Address 618 from, to, _ := ParseErc20TransferLog(log) 619 txFrom = &from 620 txTo = &to 621 case Erc721Transfer: 622 tokenAddress = new(common.Address) 623 *tokenAddress = log.Address 624 from, to, _ := ParseErc721TransferLog(log) 625 txFrom = &from 626 txTo = &to 627 case Erc1155Transfer: 628 tokenAddress = new(common.Address) 629 *tokenAddress = log.Address 630 _, from, to, _, _, err := ParseErc1155TransferLog(log, Erc1155TransferSingleEventType) // from/to extraction is the same for single and batch 631 if err != nil { 632 return 633 } 634 txFrom = &from 635 txTo = &to 636 } 637 638 return 639 } 640 641 func TxDataContainsAddress(txType uint8, txData []byte, address common.Address) bool { 642 // First 4 bytes are related to the methodID 643 const methodIDLen int = 4 644 const paramLen int = 32 645 646 var paramOffset int = 0 647 switch txType { 648 case types.OptimismDepositTxType: 649 // Offset for relayMessage data. 650 // I actually don't know what the 2x32 + 4 bytes mean, but it seems to be constant in all transactions I've 651 // checked. Will update the comment when I find out more about it. 652 paramOffset = 5*32 + 2*32 + 4 653 } 654 655 // Check if address is contained in any 32-byte parameter 656 for paramStart := methodIDLen + paramOffset; paramStart < len(txData); paramStart += paramLen { 657 paramEnd := paramStart + paramLen 658 659 if paramEnd > len(txData) { 660 break 661 } 662 663 // Address bytes should be in the last addressLen positions 664 paramBytes := txData[paramStart:paramEnd] 665 paramAddress := common.BytesToAddress(paramBytes) 666 if address == paramAddress { 667 return true 668 } 669 } 670 return false 671 }