github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/test/e2e/debug_test.go (about) 1 package e2e 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "math/big" 8 "strings" 9 "testing" 10 11 "github.com/0xPolygon/supernets2-node/hex" 12 "github.com/0xPolygon/supernets2-node/jsonrpc/client" 13 "github.com/0xPolygon/supernets2-node/jsonrpc/types" 14 "github.com/0xPolygon/supernets2-node/log" 15 "github.com/0xPolygon/supernets2-node/test/operations" 16 "github.com/ethereum/go-ethereum" 17 "github.com/ethereum/go-ethereum/accounts/abi/bind" 18 "github.com/ethereum/go-ethereum/common" 19 ethTypes "github.com/ethereum/go-ethereum/core/types" 20 "github.com/ethereum/go-ethereum/crypto" 21 "github.com/ethereum/go-ethereum/ethclient" 22 "github.com/stretchr/testify/require" 23 ) 24 25 func TestDebugTraceTransactionNotFoundTx(t *testing.T) { 26 if testing.Short() { 27 t.Skip() 28 } 29 30 const l2NetworkURL = "http://localhost:8124" 31 const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" 32 33 var err error 34 err = operations.Teardown() 35 require.NoError(t, err) 36 37 defer func() { 38 require.NoError(t, operations.Teardown()) 39 require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) 40 }() 41 42 ctx := context.Background() 43 opsCfg := operations.GetDefaultOperationsConfig() 44 opsMan, err := operations.NewManager(ctx, opsCfg) 45 require.NoError(t, err) 46 err = opsMan.Setup() 47 require.NoError(t, err) 48 49 err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) 50 require.NoError(t, err) 51 52 const l1NetworkName, l2NetworkName = "Local L1", "Local L2" 53 54 networks := []struct { 55 Name string 56 URL string 57 WebSocketURL string 58 ChainID uint64 59 PrivateKey string 60 }{ 61 { 62 Name: l1NetworkName, 63 URL: operations.DefaultL1NetworkURL, 64 ChainID: operations.DefaultL1ChainID, 65 PrivateKey: operations.DefaultSequencerPrivateKey, 66 }, 67 { 68 Name: l2NetworkName, 69 URL: l2NetworkURL, 70 ChainID: operations.DefaultL2ChainID, 71 PrivateKey: operations.DefaultSequencerPrivateKey, 72 }, 73 } 74 75 for _, network := range networks { 76 log.Debugf(network.Name) 77 tx := ethTypes.NewTx(ðTypes.LegacyTx{ 78 Nonce: 10, 79 }) 80 81 response, err := client.JSONRPCCall(network.URL, "debug_traceTransaction", tx.Hash().String()) 82 require.NoError(t, err) 83 require.Nil(t, response.Result) 84 require.NotNil(t, response.Error) 85 86 require.Equal(t, -32000, response.Error.Code) 87 require.Equal(t, "transaction not found", response.Error.Message) 88 require.Nil(t, response.Error.Data) 89 } 90 } 91 92 func TestDebugTraceBlockByNumberNotFoundTx(t *testing.T) { 93 if testing.Short() { 94 t.Skip() 95 } 96 97 const l2NetworkURL = "http://localhost:8124" 98 const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" 99 100 var err error 101 err = operations.Teardown() 102 require.NoError(t, err) 103 104 defer func() { 105 require.NoError(t, operations.Teardown()) 106 require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) 107 }() 108 109 ctx := context.Background() 110 opsCfg := operations.GetDefaultOperationsConfig() 111 opsMan, err := operations.NewManager(ctx, opsCfg) 112 require.NoError(t, err) 113 err = opsMan.Setup() 114 require.NoError(t, err) 115 116 err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) 117 require.NoError(t, err) 118 119 const l1NetworkName, l2NetworkName = "Local L1", "Local L2" 120 121 networks := []struct { 122 Name string 123 URL string 124 WebSocketURL string 125 ChainID uint64 126 PrivateKey string 127 }{ 128 { 129 Name: l1NetworkName, 130 URL: operations.DefaultL1NetworkURL, 131 ChainID: operations.DefaultL1ChainID, 132 PrivateKey: operations.DefaultSequencerPrivateKey, 133 }, 134 { 135 Name: l2NetworkName, 136 URL: l2NetworkURL, 137 ChainID: operations.DefaultL2ChainID, 138 PrivateKey: operations.DefaultSequencerPrivateKey, 139 }, 140 } 141 142 for _, network := range networks { 143 log.Debugf(network.Name) 144 145 response, err := client.JSONRPCCall(network.URL, "debug_traceBlockByNumber", hex.EncodeBig(big.NewInt(999999999999))) 146 require.NoError(t, err) 147 require.Nil(t, response.Result) 148 require.NotNil(t, response.Error) 149 150 require.Equal(t, -32000, response.Error.Code) 151 require.Equal(t, "block #999999999999 not found", response.Error.Message) 152 require.Nil(t, response.Error.Data) 153 } 154 } 155 156 func TestDebugTraceBlockByHashNotFoundTx(t *testing.T) { 157 if testing.Short() { 158 t.Skip() 159 } 160 161 const l2NetworkURL = "http://localhost:8124" 162 const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" 163 164 var err error 165 err = operations.Teardown() 166 require.NoError(t, err) 167 168 defer func() { 169 require.NoError(t, operations.Teardown()) 170 require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) 171 }() 172 173 ctx := context.Background() 174 opsCfg := operations.GetDefaultOperationsConfig() 175 opsMan, err := operations.NewManager(ctx, opsCfg) 176 require.NoError(t, err) 177 err = opsMan.Setup() 178 require.NoError(t, err) 179 180 err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) 181 require.NoError(t, err) 182 183 const l1NetworkName, l2NetworkName = "Local L1", "Local L2" 184 185 networks := []struct { 186 Name string 187 URL string 188 WebSocketURL string 189 ChainID uint64 190 PrivateKey string 191 }{ 192 { 193 Name: l1NetworkName, 194 URL: operations.DefaultL1NetworkURL, 195 ChainID: operations.DefaultL1ChainID, 196 PrivateKey: operations.DefaultSequencerPrivateKey, 197 }, 198 { 199 Name: l2NetworkName, 200 URL: l2NetworkURL, 201 ChainID: operations.DefaultL2ChainID, 202 PrivateKey: operations.DefaultSequencerPrivateKey, 203 }, 204 } 205 206 for _, network := range networks { 207 log.Debugf(network.Name) 208 209 response, err := client.JSONRPCCall(network.URL, "debug_traceBlockByHash", common.Hash{}.String()) 210 require.NoError(t, err) 211 require.Nil(t, response.Result) 212 require.NotNil(t, response.Error) 213 214 require.Equal(t, -32000, response.Error.Code) 215 require.Equal(t, "block 0x0000000000000000000000000000000000000000000000000000000000000000 not found", response.Error.Message) 216 require.Nil(t, response.Error.Data) 217 } 218 } 219 220 func TestDebugTraceTransaction(t *testing.T) { 221 if testing.Short() { 222 t.Skip() 223 } 224 225 const l2NetworkURL = "http://localhost:8124" 226 const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" 227 228 var err error 229 err = operations.Teardown() 230 require.NoError(t, err) 231 232 defer func() { 233 require.NoError(t, operations.Teardown()) 234 require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) 235 }() 236 237 ctx := context.Background() 238 opsCfg := operations.GetDefaultOperationsConfig() 239 opsMan, err := operations.NewManager(ctx, opsCfg) 240 require.NoError(t, err) 241 err = opsMan.Setup() 242 require.NoError(t, err) 243 244 err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) 245 require.NoError(t, err) 246 247 const l1NetworkName, l2NetworkName = "Local L1", "Local L2" 248 249 networks := []struct { 250 Name string 251 URL string 252 WebSocketURL string 253 ChainID uint64 254 PrivateKey string 255 }{ 256 { 257 Name: l1NetworkName, 258 URL: operations.DefaultL1NetworkURL, 259 ChainID: operations.DefaultL1ChainID, 260 PrivateKey: operations.DefaultSequencerPrivateKey, 261 }, 262 { 263 Name: l2NetworkName, 264 URL: l2NetworkURL, 265 ChainID: operations.DefaultL2ChainID, 266 PrivateKey: operations.DefaultSequencerPrivateKey, 267 }, 268 } 269 270 results := map[string]json.RawMessage{} 271 272 type testCase struct { 273 name string 274 prepare func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) 275 createSignedTx func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) 276 } 277 testCases := []testCase{ 278 // successful transactions 279 {name: "eth transfer", createSignedTx: createEthTransferSignedTx}, 280 {name: "sc deployment", createSignedTx: createScDeploySignedTx}, 281 {name: "sc call", prepare: prepareScCall, createSignedTx: createScCallSignedTx}, 282 {name: "erc20 transfer", prepare: prepareERC20Transfer, createSignedTx: createERC20TransferSignedTx}, 283 {name: "create", prepare: prepareCreate, createSignedTx: createCreateSignedTx}, 284 {name: "create2", prepare: prepareCreate, createSignedTx: createCreate2SignedTx}, 285 {name: "call", prepare: prepareCalls, createSignedTx: createCallSignedTx}, 286 {name: "delegate call", prepare: prepareCalls, createSignedTx: createDelegateCallSignedTx}, 287 {name: "multi call", prepare: prepareCalls, createSignedTx: createMultiCallSignedTx}, 288 {name: "pre ecrecover 0", prepare: prepareCalls, createSignedTx: createPreEcrecover0SignedTx}, 289 {name: "chain call", prepare: prepareChainCalls, createSignedTx: createChainCallSignedTx}, 290 291 // failed transactions 292 {name: "sc deployment reverted", createSignedTx: createScDeployRevertedSignedTx}, 293 {name: "sc call reverted", prepare: prepareScCallReverted, createSignedTx: createScCallRevertedSignedTx}, 294 {name: "erc20 transfer reverted", prepare: prepareERC20TransferReverted, createSignedTx: createERC20TransferRevertedSignedTx}, 295 } 296 297 privateKey, err := crypto.GenerateKey() 298 require.NoError(t, err) 299 for _, network := range networks { 300 auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(0).SetUint64(network.ChainID)) 301 require.NoError(t, err) 302 303 ethereumClient := operations.MustGetClient(network.URL) 304 sourceAuth := operations.MustGetAuth(network.PrivateKey, network.ChainID) 305 306 nonce, err := ethereumClient.NonceAt(ctx, sourceAuth.From, nil) 307 require.NoError(t, err) 308 309 balance, err := ethereumClient.BalanceAt(ctx, sourceAuth.From, nil) 310 require.NoError(t, err) 311 312 gasPrice, err := ethereumClient.SuggestGasPrice(ctx) 313 require.NoError(t, err) 314 315 value := big.NewInt(0).Quo(balance, big.NewInt(2)) 316 317 gas, err := ethereumClient.EstimateGas(ctx, ethereum.CallMsg{ 318 From: sourceAuth.From, 319 To: &auth.From, 320 GasPrice: gasPrice, 321 Value: value, 322 }) 323 require.NoError(t, err) 324 325 tx := ethTypes.NewTx(ðTypes.LegacyTx{ 326 To: &auth.From, 327 Nonce: nonce, 328 GasPrice: gasPrice, 329 Value: value, 330 Gas: gas, 331 }) 332 333 signedTx, err := sourceAuth.Signer(sourceAuth.From, tx) 334 require.NoError(t, err) 335 336 err = ethereumClient.SendTransaction(ctx, signedTx) 337 require.NoError(t, err) 338 339 err = operations.WaitTxToBeMined(ctx, ethereumClient, signedTx, operations.DefaultTimeoutTxToBeMined) 340 require.NoError(t, err) 341 } 342 343 for _, tc := range testCases { 344 t.Run(tc.name, func(t *testing.T) { 345 log.Debug("************************ ", tc.name, " ************************") 346 347 for _, network := range networks { 348 log.Debug("------------------------ ", network.Name, " ------------------------") 349 ethereumClient := operations.MustGetClient(network.URL) 350 auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(0).SetUint64(network.ChainID)) 351 require.NoError(t, err) 352 353 var customData map[string]interface{} 354 if tc.prepare != nil { 355 customData, err = tc.prepare(t, ctx, auth, ethereumClient) 356 require.NoError(t, err) 357 } 358 359 signedTx, err := tc.createSignedTx(t, ctx, auth, ethereumClient, customData) 360 require.NoError(t, err) 361 362 balance, err := ethereumClient.BalanceAt(ctx, auth.From, nil) 363 require.NoError(t, err) 364 365 log.Debugf("balance of %v: %v", auth.From, balance.String()) 366 367 err = ethereumClient.SendTransaction(ctx, signedTx) 368 require.NoError(t, err) 369 370 log.Debugf("tx sent: %v", signedTx.Hash().String()) 371 372 err = operations.WaitTxToBeMined(ctx, ethereumClient, signedTx, operations.DefaultTimeoutTxToBeMined) 373 if err != nil && !strings.HasPrefix(err.Error(), "transaction has failed, reason:") { 374 require.NoError(t, err) 375 } 376 377 debugOptions := map[string]interface{}{ 378 "disableStorage": false, 379 "disableStack": false, 380 "enableMemory": true, 381 "enableReturnData": true, 382 } 383 384 response, err := client.JSONRPCCall(network.URL, "debug_traceTransaction", signedTx.Hash().String(), debugOptions) 385 require.NoError(t, err) 386 require.Nil(t, response.Error) 387 require.NotNil(t, response.Result) 388 389 results[network.Name] = response.Result 390 391 saveTraceResultToFile(t, tc.name, network.Name, signedTx, response.Result, true) 392 } 393 394 referenceValueMap := map[string]interface{}{} 395 err = json.Unmarshal(results[l1NetworkName], &referenceValueMap) 396 require.NoError(t, err) 397 398 referenceStructLogsMap := referenceValueMap["structLogs"].([]interface{}) 399 400 for networkName, result := range results { 401 if networkName == l1NetworkName { 402 continue 403 } 404 405 resultMap := map[string]interface{}{} 406 err = json.Unmarshal(result, &resultMap) 407 require.NoError(t, err) 408 409 require.Equal(t, referenceValueMap["failed"], resultMap["failed"], fmt.Sprintf("invalid `failed` for network %s", networkName)) 410 411 resultStructLogsMap := resultMap["structLogs"].([]interface{}) 412 require.Equal(t, len(referenceStructLogsMap), len(resultStructLogsMap)) 413 414 for structLogIndex := range referenceStructLogsMap { 415 referenceStructLogMap := referenceStructLogsMap[structLogIndex].(map[string]interface{}) 416 resultStructLogMap := resultStructLogsMap[structLogIndex].(map[string]interface{}) 417 418 require.Equal(t, referenceStructLogMap["pc"], resultStructLogMap["pc"], fmt.Sprintf("invalid struct log pc for network %s", networkName)) 419 require.Equal(t, referenceStructLogMap["op"], resultStructLogMap["op"], fmt.Sprintf("invalid struct log op for network %s", networkName)) 420 require.Equal(t, referenceStructLogMap["depth"], resultStructLogMap["depth"], fmt.Sprintf("invalid struct log depth for network %s", networkName)) 421 422 pc := referenceStructLogMap["pc"] 423 op := referenceStructLogMap["op"] 424 425 referenceStack, found := referenceStructLogMap["stack"].([]interface{}) 426 if found { 427 resultStack := resultStructLogMap["stack"].([]interface{}) 428 429 require.Equal(t, len(referenceStack), len(resultStack), fmt.Sprintf("stack size doesn't match for pc %v op %v", pc, op)) 430 for stackIndex := range referenceStack { 431 require.Equal(t, referenceStack[stackIndex], resultStack[stackIndex], fmt.Sprintf("stack index %v doesn't match for pc %v op %v", stackIndex, pc, op)) 432 } 433 } 434 435 referenceMemory, found := referenceStructLogMap["memory"].([]interface{}) 436 if found { 437 resultMemory := resultStructLogMap["memory"].([]interface{}) 438 439 require.Equal(t, len(referenceMemory), len(resultMemory), fmt.Sprintf("memory size doesn't match for pc %v op %v", pc, op)) 440 for memoryIndex := range referenceMemory { 441 require.Equal(t, referenceMemory[memoryIndex], resultMemory[memoryIndex], fmt.Sprintf("memory index %v doesn't match for pc %v op %v", memoryIndex, pc, op)) 442 } 443 } 444 445 referenceStorage, found := referenceStructLogMap["storage"].(map[string]interface{}) 446 if found { 447 resultStorage := resultStructLogMap["storage"].(map[string]interface{}) 448 449 require.Equal(t, len(referenceStorage), len(resultStorage), fmt.Sprintf("storage size doesn't match for pc %v op %v", pc, op)) 450 for storageKey, referenceStorageValue := range referenceStorage { 451 resultStorageValue, found := resultStorage[storageKey] 452 require.True(t, found, "storage address not found") 453 require.Equal(t, referenceStorageValue, resultStorageValue, fmt.Sprintf("storage value doesn't match for address %v for pc %v op %v", storageKey, pc, op)) 454 } 455 } 456 } 457 } 458 }) 459 } 460 } 461 462 func TestDebugTraceBlock(t *testing.T) { 463 if testing.Short() { 464 t.Skip() 465 } 466 467 const l2NetworkURL = "http://localhost:8124" 468 const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" 469 470 var err error 471 err = operations.Teardown() 472 require.NoError(t, err) 473 474 defer func() { 475 require.NoError(t, operations.Teardown()) 476 require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) 477 }() 478 479 ctx := context.Background() 480 opsCfg := operations.GetDefaultOperationsConfig() 481 opsMan, err := operations.NewManager(ctx, opsCfg) 482 require.NoError(t, err) 483 err = opsMan.Setup() 484 require.NoError(t, err) 485 486 err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) 487 require.NoError(t, err) 488 489 const l1NetworkName, l2NetworkName = "Local L1", "Local L2" 490 491 networks := []struct { 492 Name string 493 URL string 494 WebSocketURL string 495 ChainID uint64 496 PrivateKey string 497 }{ 498 { 499 Name: l1NetworkName, 500 URL: operations.DefaultL1NetworkURL, 501 ChainID: operations.DefaultL1ChainID, 502 PrivateKey: operations.DefaultSequencerPrivateKey, 503 }, 504 { 505 Name: l2NetworkName, 506 URL: l2NetworkURL, 507 ChainID: operations.DefaultL2ChainID, 508 PrivateKey: operations.DefaultSequencerPrivateKey, 509 }, 510 } 511 512 results := map[string]json.RawMessage{} 513 514 type testCase struct { 515 name string 516 blockNumberOrHash string 517 prepare func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) 518 createSignedTx func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) 519 } 520 testCases := []testCase{ 521 // successful transactions 522 // by block number 523 {name: "eth transfer by number", blockNumberOrHash: "number", createSignedTx: createEthTransferSignedTx}, 524 {name: "sc deployment by number", blockNumberOrHash: "number", createSignedTx: createScDeploySignedTx}, 525 {name: "sc call by number", blockNumberOrHash: "number", prepare: prepareScCall, createSignedTx: createScCallSignedTx}, 526 {name: "erc20 transfer by number", blockNumberOrHash: "number", prepare: prepareERC20Transfer, createSignedTx: createERC20TransferSignedTx}, 527 // by block hash 528 {name: "eth transfer by hash", blockNumberOrHash: "hash", createSignedTx: createEthTransferSignedTx}, 529 {name: "sc deployment by hash", blockNumberOrHash: "hash", createSignedTx: createScDeploySignedTx}, 530 {name: "sc call by hash", blockNumberOrHash: "hash", prepare: prepareScCall, createSignedTx: createScCallSignedTx}, 531 {name: "erc20 transfer by hash", blockNumberOrHash: "hash", prepare: prepareERC20Transfer, createSignedTx: createERC20TransferSignedTx}, 532 533 // failed transactions 534 // by block number 535 {name: "sc deployment reverted by number", blockNumberOrHash: "number", createSignedTx: createScDeployRevertedSignedTx}, 536 {name: "sc call reverted by number", blockNumberOrHash: "number", prepare: prepareScCallReverted, createSignedTx: createScCallRevertedSignedTx}, 537 {name: "erc20 transfer reverted by number", blockNumberOrHash: "number", prepare: prepareERC20TransferReverted, createSignedTx: createERC20TransferRevertedSignedTx}, 538 // by block hash 539 {name: "sc deployment reverted by hash", blockNumberOrHash: "hash", createSignedTx: createScDeployRevertedSignedTx}, 540 {name: "sc call reverted by hash", blockNumberOrHash: "hash", prepare: prepareScCallReverted, createSignedTx: createScCallRevertedSignedTx}, 541 {name: "erc20 transfer reverted by hash", blockNumberOrHash: "hash", prepare: prepareERC20TransferReverted, createSignedTx: createERC20TransferRevertedSignedTx}, 542 } 543 544 for _, tc := range testCases { 545 t.Run(tc.name, func(t *testing.T) { 546 log.Debug("************************ ", tc.name, " ************************") 547 548 for _, network := range networks { 549 log.Debug("------------------------ ", network.Name, " ------------------------") 550 ethereumClient := operations.MustGetClient(network.URL) 551 auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) 552 553 var customData map[string]interface{} 554 if tc.prepare != nil { 555 customData, err = tc.prepare(t, ctx, auth, ethereumClient) 556 require.NoError(t, err) 557 } 558 559 signedTx, err := tc.createSignedTx(t, ctx, auth, ethereumClient, customData) 560 require.NoError(t, err) 561 562 err = ethereumClient.SendTransaction(ctx, signedTx) 563 require.NoError(t, err) 564 565 log.Debugf("tx sent: %v", signedTx.Hash().String()) 566 567 err = operations.WaitTxToBeMined(ctx, ethereumClient, signedTx, operations.DefaultTimeoutTxToBeMined) 568 if err != nil && !strings.HasPrefix(err.Error(), "transaction has failed, reason:") { 569 require.NoError(t, err) 570 } 571 572 receipt, err := ethereumClient.TransactionReceipt(ctx, signedTx.Hash()) 573 require.NoError(t, err) 574 575 debugOptions := map[string]interface{}{ 576 "disableStorage": false, 577 "disableStack": false, 578 "enableMemory": true, 579 "enableReturnData": true, 580 } 581 582 var response types.Response 583 if tc.blockNumberOrHash == "number" { 584 response, err = client.JSONRPCCall(network.URL, "debug_traceBlockByNumber", hex.EncodeBig(receipt.BlockNumber), debugOptions) 585 } else { 586 response, err = client.JSONRPCCall(network.URL, "debug_traceBlockByHash", receipt.BlockHash.String(), debugOptions) 587 } 588 require.NoError(t, err) 589 require.Nil(t, response.Error) 590 require.NotNil(t, response.Result) 591 592 results[network.Name] = response.Result 593 } 594 595 referenceTransactions := []interface{}{} 596 err = json.Unmarshal(results[l1NetworkName], &referenceTransactions) 597 require.NoError(t, err) 598 599 for networkName, result := range results { 600 if networkName == l1NetworkName { 601 continue 602 } 603 604 resultTransactions := []interface{}{} 605 err = json.Unmarshal(result, &resultTransactions) 606 require.NoError(t, err) 607 608 for transactionIndex := range referenceTransactions { 609 referenceTransactionMap := referenceTransactions[transactionIndex].(map[string]interface{}) 610 referenceResultMap := referenceTransactionMap["result"].(map[string]interface{}) 611 referenceStructLogsMap := referenceResultMap["structLogs"].([]interface{}) 612 613 resultTransactionMap := resultTransactions[transactionIndex].(map[string]interface{}) 614 resultResultMap := resultTransactionMap["result"].(map[string]interface{}) 615 resultStructLogsMap := resultResultMap["structLogs"].([]interface{}) 616 617 require.Equal(t, len(referenceStructLogsMap), len(resultStructLogsMap)) 618 619 for structLogIndex := range referenceStructLogsMap { 620 referenceStructLogMap := referenceStructLogsMap[structLogIndex].(map[string]interface{}) 621 resultStructLogMap := resultStructLogsMap[structLogIndex].(map[string]interface{}) 622 623 require.Equal(t, referenceStructLogMap["pc"], resultStructLogMap["pc"], fmt.Sprintf("invalid struct log pc for network %s", networkName)) 624 require.Equal(t, referenceStructLogMap["op"], resultStructLogMap["op"], fmt.Sprintf("invalid struct log op for network %s", networkName)) 625 require.Equal(t, referenceStructLogMap["depth"], resultStructLogMap["depth"], fmt.Sprintf("invalid struct log depth for network %s", networkName)) 626 627 pc := referenceStructLogMap["pc"] 628 op := referenceStructLogMap["op"] 629 630 referenceStack, found := referenceStructLogMap["stack"].([]interface{}) 631 if found { 632 resultStack := resultStructLogMap["stack"].([]interface{}) 633 634 require.Equal(t, len(referenceStack), len(resultStack), fmt.Sprintf("stack size doesn't match for pc %v op %v", pc, op)) 635 for stackIndex := range referenceStack { 636 require.Equal(t, referenceStack[stackIndex], resultStack[stackIndex], fmt.Sprintf("stack index %v doesn't match for pc %v op %v", stackIndex, pc, op)) 637 } 638 } 639 640 referenceMemory, found := referenceStructLogMap["memory"].([]interface{}) 641 if found { 642 resultMemory := resultStructLogMap["memory"].([]interface{}) 643 644 require.Equal(t, len(referenceMemory), len(resultMemory), fmt.Sprintf("memory size doesn't match for pc %v op %v", pc, op)) 645 for memoryIndex := range referenceMemory { 646 require.Equal(t, referenceMemory[memoryIndex], resultMemory[memoryIndex], fmt.Sprintf("memory index %v doesn't match for pc %v op %v", memoryIndex, pc, op)) 647 } 648 } 649 650 referenceStorage, found := referenceStructLogMap["storage"].(map[string]interface{}) 651 if found { 652 resultStorage := resultStructLogMap["storage"].(map[string]interface{}) 653 654 require.Equal(t, len(referenceStorage), len(resultStorage), fmt.Sprintf("storage size doesn't match for pc %v op %v", pc, op)) 655 for storageKey, referenceStorageValue := range referenceStorage { 656 resultStorageValue, found := resultStorage[storageKey] 657 require.True(t, found, "storage address not found") 658 require.Equal(t, referenceStorageValue, resultStorageValue, fmt.Sprintf("storage value doesn't match for address %v for pc %v op %v", storageKey, pc, op)) 659 } 660 } 661 } 662 } 663 } 664 }) 665 } 666 }