diff --git a/zetaclient/bitcoin/bitcoin_client_test.go b/zetaclient/bitcoin/bitcoin_client_test.go index f92f3a01fd..68cb840e0f 100644 --- a/zetaclient/bitcoin/bitcoin_client_test.go +++ b/zetaclient/bitcoin/bitcoin_client_test.go @@ -24,7 +24,7 @@ import ( func MockBTCClientMainnet() *BTCChainClient { return &BTCChainClient{ chain: common.BtcMainnetChain(), - zetaClient: stub.NewZetaCoreBridge(), + zetaClient: stub.NewMockZetaCoreBridge(), Tss: stub.NewTSSMainnet(), } } diff --git a/zetaclient/evm/evm_client.go b/zetaclient/evm/evm_client.go index 55e3850a44..614964d214 100644 --- a/zetaclient/evm/evm_client.go +++ b/zetaclient/evm/evm_client.go @@ -69,9 +69,9 @@ type Log struct { type ChainClient struct { chain common.Chain evmClient interfaces.EVMRPCClient + evmJSONRPC interfaces.EVMJSONRPCClient zetaClient interfaces.ZetaCoreBridger Tss interfaces.TSSSigner - evmJSONRPC *ethrpc.EthRPC lastBlockScanned uint64 lastBlock uint64 BlockTimeExternalChain uint64 // block time in seconds @@ -81,7 +81,6 @@ type ChainClient struct { outTxPendingTransactions map[string]*ethtypes.Transaction outTXConfirmedReceipts map[string]*ethtypes.Receipt outTXConfirmedTransactions map[string]*ethtypes.Transaction - OutTxChan chan OutTx // send to this channel if you want something back! stop chan struct{} logger Log coreContext *corecontext.ZetaCoreContext @@ -128,7 +127,6 @@ func NewEVMChainClient( ob.outTxPendingTransactions = make(map[string]*ethtypes.Transaction) ob.outTXConfirmedReceipts = make(map[string]*ethtypes.Receipt) ob.outTXConfirmedTransactions = make(map[string]*ethtypes.Transaction) - ob.OutTxChan = make(chan OutTx, 100) ob.logger.ChainLogger.Info().Msgf("Chain %s endpoint %s", ob.chain.ChainName.String(), evmCfg.Endpoint) client, err := ethclient.Dial(evmCfg.Endpoint) @@ -176,13 +174,13 @@ func (ob *ChainClient) WithLogger(logger zerolog.Logger) { } } -func (ob *ChainClient) WithEvmClient(client *ethclient.Client) { +func (ob *ChainClient) WithEvmClient(client interfaces.EVMRPCClient) { ob.Mu.Lock() defer ob.Mu.Unlock() ob.evmClient = client } -func (ob *ChainClient) WithEvmJSONRPC(client *ethrpc.EthRPC) { +func (ob *ChainClient) WithEvmJSONRPC(client interfaces.EVMJSONRPCClient) { ob.Mu.Lock() defer ob.Mu.Unlock() ob.evmJSONRPC = client @@ -946,13 +944,13 @@ func (ob *ChainClient) observeInTX(sampledLogger zerolog.Logger) error { startBlock, toBlock := ob.calcBlockRangeToScan(confirmedBlockNum, lastScanned, config.MaxBlocksPerPeriod) // task 1: query evm chain for zeta sent logs (read at most 100 blocks in one go) - lastScannedZetaSent := ob.observeZetaSent(startBlock, toBlock) + lastScannedZetaSent := ob.ObserveZetaSent(startBlock, toBlock) // task 2: query evm chain for deposited logs (read at most 100 blocks in one go) - lastScannedDeposited := ob.observeERC20Deposited(startBlock, toBlock) + lastScannedDeposited := ob.ObserveERC20Deposited(startBlock, toBlock) // task 3: query the incoming tx to TSS address (read at most 100 blocks in one go) - lastScannedTssRecvd := ob.observerTSSReceive(startBlock, toBlock, flags) + lastScannedTssRecvd := ob.ObserverTSSReceive(startBlock, toBlock, flags) // note: using lowest height for all 3 events is not perfect, but it's simple and good enough lastScannedLowest := lastScannedZetaSent @@ -975,13 +973,13 @@ func (ob *ChainClient) observeInTX(sampledLogger zerolog.Logger) error { return nil } -// observeZetaSent queries the ZetaSent event from the connector contract and posts to zetabridge +// ObserveZetaSent queries the ZetaSent event from the connector contract and posts to zetabridge // returns the last block successfully scanned -func (ob *ChainClient) observeZetaSent(startBlock, toBlock uint64) uint64 { +func (ob *ChainClient) ObserveZetaSent(startBlock, toBlock uint64) uint64 { // filter ZetaSent logs addrConnector, connector, err := ob.GetConnectorContract() if err != nil { - ob.logger.ChainLogger.Warn().Err(err).Msgf("observeZetaSent: GetConnectorContract error:") + ob.logger.ChainLogger.Warn().Err(err).Msgf("ObserveZetaSent: GetConnectorContract error:") return startBlock - 1 // lastScanned } iter, err := connector.FilterZetaSent(&bind.FilterOpts{ @@ -991,7 +989,7 @@ func (ob *ChainClient) observeZetaSent(startBlock, toBlock uint64) uint64 { }, []ethcommon.Address{}, []*big.Int{}) if err != nil { ob.logger.ChainLogger.Warn().Err(err).Msgf( - "observeZetaSent: FilterZetaSent error from block %d to %d for chain %d", startBlock, toBlock, ob.chain.ChainId) + "ObserveZetaSent: FilterZetaSent error from block %d to %d for chain %d", startBlock, toBlock, ob.chain.ChainId) return startBlock - 1 // lastScanned } @@ -1004,7 +1002,7 @@ func (ob *ChainClient) observeZetaSent(startBlock, toBlock uint64) uint64 { events = append(events, iter.Event) continue } - ob.logger.ExternalChainWatcher.Warn().Err(err).Msgf("observeZetaSent: invalid ZetaSent event in tx %s on chain %d at height %d", + ob.logger.ExternalChainWatcher.Warn().Err(err).Msgf("ObserveZetaSent: invalid ZetaSent event in tx %s on chain %d at height %d", iter.Event.Raw.TxHash.Hex(), ob.chain.ChainId, iter.Event.Raw.BlockNumber) } sort.SliceStable(events, func(i, j int) bool { @@ -1030,7 +1028,7 @@ func (ob *ChainClient) observeZetaSent(startBlock, toBlock uint64) uint64 { } // guard against multiple events in the same tx if guard[event.Raw.TxHash.Hex()] { - ob.logger.ExternalChainWatcher.Warn().Msgf("observeZetaSent: multiple remote call events detected in tx %s", event.Raw.TxHash) + ob.logger.ExternalChainWatcher.Warn().Msgf("ObserveZetaSent: multiple remote call events detected in tx %s", event.Raw.TxHash) continue } guard[event.Raw.TxHash.Hex()] = true @@ -1047,13 +1045,13 @@ func (ob *ChainClient) observeZetaSent(startBlock, toBlock uint64) uint64 { return toBlock } -// observeERC20Deposited queries the ERC20CustodyDeposited event from the ERC20Custody contract and posts to zetabridge +// ObserveERC20Deposited queries the ERC20CustodyDeposited event from the ERC20Custody contract and posts to zetabridge // returns the last block successfully scanned -func (ob *ChainClient) observeERC20Deposited(startBlock, toBlock uint64) uint64 { +func (ob *ChainClient) ObserveERC20Deposited(startBlock, toBlock uint64) uint64 { // filter ERC20CustodyDeposited logs addrCustody, erc20custodyContract, err := ob.GetERC20CustodyContract() if err != nil { - ob.logger.ExternalChainWatcher.Warn().Err(err).Msgf("observeERC20Deposited: GetERC20CustodyContract error:") + ob.logger.ExternalChainWatcher.Warn().Err(err).Msgf("ObserveERC20Deposited: GetERC20CustodyContract error:") return startBlock - 1 // lastScanned } iter, err := erc20custodyContract.FilterDeposited(&bind.FilterOpts{ @@ -1063,7 +1061,7 @@ func (ob *ChainClient) observeERC20Deposited(startBlock, toBlock uint64) uint64 }, []ethcommon.Address{}) if err != nil { ob.logger.ExternalChainWatcher.Warn().Err(err).Msgf( - "observeERC20Deposited: FilterDeposited error from block %d to %d for chain %d", startBlock, toBlock, ob.chain.ChainId) + "ObserveERC20Deposited: FilterDeposited error from block %d to %d for chain %d", startBlock, toBlock, ob.chain.ChainId) return startBlock - 1 // lastScanned } @@ -1076,7 +1074,7 @@ func (ob *ChainClient) observeERC20Deposited(startBlock, toBlock uint64) uint64 events = append(events, iter.Event) continue } - ob.logger.ExternalChainWatcher.Warn().Err(err).Msgf("observeERC20Deposited: invalid Deposited event in tx %s on chain %d at height %d", + ob.logger.ExternalChainWatcher.Warn().Err(err).Msgf("ObserveERC20Deposited: invalid Deposited event in tx %s on chain %d at height %d", iter.Event.Raw.TxHash.Hex(), ob.chain.ChainId, iter.Event.Raw.BlockNumber) } sort.SliceStable(events, func(i, j int) bool { @@ -1103,14 +1101,14 @@ func (ob *ChainClient) observeERC20Deposited(startBlock, toBlock uint64) uint64 tx, _, err := ob.TransactionByHash(event.Raw.TxHash.Hex()) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msgf( - "observeERC20Deposited: error getting transaction for intx %s chain %d", event.Raw.TxHash, ob.chain.ChainId) + "ObserveERC20Deposited: error getting transaction for intx %s chain %d", event.Raw.TxHash, ob.chain.ChainId) return beingScanned - 1 // we have to re-scan from this block next time } sender := ethcommon.HexToAddress(tx.From) // guard against multiple events in the same tx if guard[event.Raw.TxHash.Hex()] { - ob.logger.ExternalChainWatcher.Warn().Msgf("observeERC20Deposited: multiple remote call events detected in tx %s", event.Raw.TxHash) + ob.logger.ExternalChainWatcher.Warn().Msgf("ObserveERC20Deposited: multiple remote call events detected in tx %s", event.Raw.TxHash) continue } guard[event.Raw.TxHash.Hex()] = true @@ -1127,9 +1125,9 @@ func (ob *ChainClient) observeERC20Deposited(startBlock, toBlock uint64) uint64 return toBlock } -// observerTSSReceive queries the incoming gas asset to TSS address and posts to zetabridge +// ObserverTSSReceive queries the incoming gas asset to TSS address and posts to zetabridge // returns the last block successfully scanned -func (ob *ChainClient) observerTSSReceive(startBlock, toBlock uint64, flags observertypes.CrosschainFlags) uint64 { +func (ob *ChainClient) ObserverTSSReceive(startBlock, toBlock uint64, flags observertypes.CrosschainFlags) uint64 { if !ob.GetChainParams().IsSupported { return startBlock - 1 // lastScanned } @@ -1147,27 +1145,12 @@ func (ob *ChainClient) observerTSSReceive(startBlock, toBlock uint64, flags obse } } - // TODO: we can track the total number of 'getBlockByNumber' RPC calls made - block, err := ob.GetBlockByNumberCached(bn) + // observe TSS received gas token in block 'bn' + err := ob.ObserveTSSReceiveInBlock(bn) if err != nil { - ob.logger.ExternalChainWatcher.Error().Err(err).Msgf("observerTSSReceive: error getting block %d for chain %d", bn, ob.chain.ChainId) + ob.logger.ExternalChainWatcher.Error().Err(err).Msgf("ObserverTSSReceive: error observing TSS received token in block %d for chain %d", bn, ob.chain.ChainId) return bn - 1 // we have to re-scan from this block next time } - for i := range block.Transactions { - tx := block.Transactions[i] - if ethcommon.HexToAddress(tx.To) == ob.Tss.EVMAddress() { - receipt, err := ob.evmClient.TransactionReceipt(context.Background(), ethcommon.HexToHash(tx.Hash)) - if err != nil { - ob.logger.ExternalChainWatcher.Err(err).Msgf("observerTSSReceive: error getting receipt for intx %s chain %d", tx.Hash, ob.chain.ChainId) - return bn - 1 // we have to re-scan from this block next time - } - _, err = ob.CheckAndVoteInboundTokenGas(&tx, receipt, true) - if err != nil { - ob.logger.ExternalChainWatcher.Err(err).Msgf("observerTSSReceive: error checking and voting inbound gas asset for intx %s chain %d", tx.Hash, ob.chain.ChainId) - return bn - 1 // we have to re-scan this block next time - } - } - } } // successful processed all gas asset deposits in [startBlock, toBlock] return toBlock diff --git a/zetaclient/evm/evm_signer.go b/zetaclient/evm/evm_signer.go index bdeef1b83a..3692dd666e 100644 --- a/zetaclient/evm/evm_signer.go +++ b/zetaclient/evm/evm_signer.go @@ -616,7 +616,7 @@ func getEVMRPC(endpoint string) (interfaces.EVMRPCClient, *big.Int, ethtypes.Sig if endpoint == stub.EVMRPCEnabled { chainID := big.NewInt(common.BscMainnetChain().ChainId) ethSigner := ethtypes.NewEIP155Signer(chainID) - client := stub.EvmClient{} + client := &stub.MockEvmClient{} return client, chainID, ethSigner, nil } diff --git a/zetaclient/evm/evm_signer_test.go b/zetaclient/evm/evm_signer_test.go index 711db544d1..3bbee44279 100644 --- a/zetaclient/evm/evm_signer_test.go +++ b/zetaclient/evm/evm_signer_test.go @@ -56,7 +56,7 @@ func getNewEvmChainClient() (*ChainClient, error) { coreCTX := corecontext.NewZetaCoreContext(cfg) appCTX := appcontext.NewAppContext(coreCTX, cfg) - return NewEVMChainClient(appCTX, stub.NewZetaCoreBridge(), tss, "", logger, evmcfg, ts) + return NewEVMChainClient(appCTX, stub.NewMockZetaCoreBridge(), tss, "", logger, evmcfg, ts) } func getNewOutTxProcessor() *outtxprocessor.Processor { @@ -85,7 +85,7 @@ func TestSigner_TryProcessOutTx(t *testing.T) { mockChainClient, err := getNewEvmChainClient() require.NoError(t, err) - evmSigner.TryProcessOutTx(cctx, processorManager, "123", mockChainClient, stub.NewZetaCoreBridge(), 123) + evmSigner.TryProcessOutTx(cctx, processorManager, "123", mockChainClient, stub.NewMockZetaCoreBridge(), 123) //Check if cctx was signed and broadcasted list := evmSigner.GetReportedTxList() @@ -280,7 +280,7 @@ func TestSigner_BroadcastOutTx(t *testing.T) { tx, err := evmSigner.SignERC20WithdrawTx(txData) require.NoError(t, err) - evmSigner.BroadcastOutTx(tx, cctx, zerolog.Logger{}, sdktypes.AccAddress{}, stub.NewZetaCoreBridge(), txData) + evmSigner.BroadcastOutTx(tx, cctx, zerolog.Logger{}, sdktypes.AccAddress{}, stub.NewMockZetaCoreBridge(), txData) //Check if cctx was signed and broadcasted list := evmSigner.GetReportedTxList() diff --git a/zetaclient/evm/inbounds.go b/zetaclient/evm/inbounds.go index 5cc08f8126..919ba6f9e2 100644 --- a/zetaclient/evm/inbounds.go +++ b/zetaclient/evm/inbounds.go @@ -354,3 +354,25 @@ func (ob *ChainClient) BuildInboundVoteMsgForTokenSentToTSS(tx *ethrpc.Transacti 0, // not a smart contract call ) } + +// ObserveTSSReceiveInBlock queries the incoming gas asset to TSS address in a single block and posts votes +func (ob *ChainClient) ObserveTSSReceiveInBlock(blockNumber uint64) error { + block, err := ob.GetBlockByNumberCached(blockNumber) + if err != nil { + return errors.Wrapf(err, "error getting block %d for chain %d", blockNumber, ob.chain.ChainId) + } + for i := range block.Transactions { + tx := block.Transactions[i] + if ethcommon.HexToAddress(tx.To) == ob.Tss.EVMAddress() { + receipt, err := ob.evmClient.TransactionReceipt(context.Background(), ethcommon.HexToHash(tx.Hash)) + if err != nil { + return errors.Wrapf(err, "error getting receipt for intx %s chain %d", tx.Hash, ob.chain.ChainId) + } + _, err = ob.CheckAndVoteInboundTokenGas(&tx, receipt, true) + if err != nil { + return errors.Wrapf(err, "error checking and voting inbound gas asset for intx %s chain %d", tx.Hash, ob.chain.ChainId) + } + } + } + return nil +} diff --git a/zetaclient/evm/inbounds_test.go b/zetaclient/evm/inbounds_test.go index 472cdc65ae..094e74786c 100644 --- a/zetaclient/evm/inbounds_test.go +++ b/zetaclient/evm/inbounds_test.go @@ -7,6 +7,7 @@ import ( ethcommon "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" + lru "github.com/hashicorp/golang-lru" "github.com/onrik/ethrpc" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/common" @@ -22,6 +23,9 @@ import ( // MockEVMClient creates a mock ChainClient with custom chain, TSS, params etc func MockEVMClient( chain common.Chain, + evmClient interfaces.EVMRPCClient, + evmJSONRPC interfaces.EVMJSONRPCClient, + zetClient interfaces.ZetaCoreBridger, tss interfaces.TSSSigner, lastBlock uint64, params observertypes.ChainParams) *evm.ChainClient { @@ -30,25 +34,36 @@ func MockEVMClient( Mu: &sync.Mutex{}, } client.WithChain(chain) - client.WithZetaClient(stub.NewZetaCoreBridge()) + client.WithEvmClient(evmClient) + client.WithEvmJSONRPC(evmJSONRPC) + if zetClient != nil { + client.WithZetaClient(zetClient) + } else { + client.WithZetaClient(stub.NewMockZetaCoreBridge()) + } client.SetLastBlockHeight(lastBlock) client.SetChainParams(params) + blockCache, _ := lru.New(1000) + client.WithBlockCache(blockCache) + return client } func TestEVM_CheckAndVoteInboundTokenZeta(t *testing.T) { // load archived ZetaSent intx, receipt and cctx // https://etherscan.io/tx/0xf3935200c80f98502d5edc7e871ffc40ca898e134525c42c2ae3cbc5725f9d76 - chainID := int64(1) - intxHash := "0xf3935200c80f98502d5edc7e871ffc40ca898e134525c42c2ae3cbc5725f9d76" + chain := common.EthChain() confirmation := uint64(10) + chainID := chain.ChainId + chainParam := stub.MockChainParams(chain.ChainId, confirmation) + intxHash := "0xf3935200c80f98502d5edc7e871ffc40ca898e134525c42c2ae3cbc5725f9d76" t.Run("should pass for archived intx, receipt and cctx", func(t *testing.T) { tx, receipt, cctx := testutils.LoadEVMIntxNReceiptNCctx(t, chainID, intxHash, common.CoinType_Zeta) require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) ballot, err := ob.CheckAndVoteInboundTokenZeta(tx, receipt, false) require.NoError(t, err) require.Equal(t, cctx.InboundTxParams.InboundTxBallotIndex, ballot) @@ -58,7 +73,7 @@ func TestEVM_CheckAndVoteInboundTokenZeta(t *testing.T) { require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - 1 - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) _, err := ob.CheckAndVoteInboundTokenZeta(tx, receipt, false) require.ErrorContains(t, err, "not been confirmed") }) @@ -68,18 +83,18 @@ func TestEVM_CheckAndVoteInboundTokenZeta(t *testing.T) { require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) ballot, err := ob.CheckAndVoteInboundTokenZeta(tx, receipt, true) require.NoError(t, err) require.Equal(t, "", ballot) }) t.Run("should not act if emitter is not ZetaConnector", func(t *testing.T) { tx, receipt, _ := testutils.LoadEVMIntxNReceiptNCctx(t, chainID, intxHash, common.CoinType_Zeta) - chainID = 56 // use BSC chain connector require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + chainID = 56 // use BSC chain connector + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) _, err := ob.CheckAndVoteInboundTokenZeta(tx, receipt, true) require.ErrorContains(t, err, "emitter address mismatch") }) @@ -88,16 +103,18 @@ func TestEVM_CheckAndVoteInboundTokenZeta(t *testing.T) { func TestEVM_CheckAndVoteInboundTokenERC20(t *testing.T) { // load archived ERC20 intx, receipt and cctx // https://etherscan.io/tx/0x4ea69a0e2ff36f7548ab75791c3b990e076e2a4bffeb616035b239b7d33843da - chainID := int64(1) - intxHash := "0x4ea69a0e2ff36f7548ab75791c3b990e076e2a4bffeb616035b239b7d33843da" + chain := common.EthChain() confirmation := uint64(10) + chainID := chain.ChainId + chainParam := stub.MockChainParams(chain.ChainId, confirmation) + intxHash := "0x4ea69a0e2ff36f7548ab75791c3b990e076e2a4bffeb616035b239b7d33843da" t.Run("should pass for archived intx, receipt and cctx", func(t *testing.T) { tx, receipt, cctx := testutils.LoadEVMIntxNReceiptNCctx(t, chainID, intxHash, common.CoinType_ERC20) require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) ballot, err := ob.CheckAndVoteInboundTokenERC20(tx, receipt, false) require.NoError(t, err) require.Equal(t, cctx.InboundTxParams.InboundTxBallotIndex, ballot) @@ -107,7 +124,7 @@ func TestEVM_CheckAndVoteInboundTokenERC20(t *testing.T) { require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - 1 - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) _, err := ob.CheckAndVoteInboundTokenERC20(tx, receipt, false) require.ErrorContains(t, err, "not been confirmed") }) @@ -117,18 +134,18 @@ func TestEVM_CheckAndVoteInboundTokenERC20(t *testing.T) { require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) ballot, err := ob.CheckAndVoteInboundTokenERC20(tx, receipt, true) require.NoError(t, err) require.Equal(t, "", ballot) }) t.Run("should not act if emitter is not ERC20 Custody", func(t *testing.T) { tx, receipt, _ := testutils.LoadEVMIntxNReceiptNCctx(t, chainID, intxHash, common.CoinType_ERC20) - chainID = 56 // use BSC chain ERC20 custody require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + chainID = 56 // use BSC chain ERC20 custody + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) _, err := ob.CheckAndVoteInboundTokenERC20(tx, receipt, true) require.ErrorContains(t, err, "emitter address mismatch") }) @@ -137,16 +154,18 @@ func TestEVM_CheckAndVoteInboundTokenERC20(t *testing.T) { func TestEVM_CheckAndVoteInboundTokenGas(t *testing.T) { // load archived Gas intx, receipt and cctx // https://etherscan.io/tx/0xeaec67d5dd5d85f27b21bef83e01cbdf59154fd793ea7a22c297f7c3a722c532 - chainID := int64(1) - intxHash := "0xeaec67d5dd5d85f27b21bef83e01cbdf59154fd793ea7a22c297f7c3a722c532" + chain := common.EthChain() confirmation := uint64(10) + chainID := chain.ChainId + chainParam := stub.MockChainParams(chain.ChainId, confirmation) + intxHash := "0xeaec67d5dd5d85f27b21bef83e01cbdf59154fd793ea7a22c297f7c3a722c532" t.Run("should pass for archived intx, receipt and cctx", func(t *testing.T) { tx, receipt, cctx := testutils.LoadEVMIntxNReceiptNCctx(t, chainID, intxHash, common.CoinType_Gas) require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) ballot, err := ob.CheckAndVoteInboundTokenGas(tx, receipt, false) require.NoError(t, err) require.Equal(t, cctx.InboundTxParams.InboundTxBallotIndex, ballot) @@ -156,7 +175,7 @@ func TestEVM_CheckAndVoteInboundTokenGas(t *testing.T) { require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - 1 - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) _, err := ob.CheckAndVoteInboundTokenGas(tx, receipt, false) require.ErrorContains(t, err, "not been confirmed") }) @@ -166,7 +185,7 @@ func TestEVM_CheckAndVoteInboundTokenGas(t *testing.T) { require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) ballot, err := ob.CheckAndVoteInboundTokenGas(tx, receipt, false) require.ErrorContains(t, err, "not TSS address") require.Equal(t, "", ballot) @@ -177,7 +196,7 @@ func TestEVM_CheckAndVoteInboundTokenGas(t *testing.T) { require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) ballot, err := ob.CheckAndVoteInboundTokenGas(tx, receipt, false) require.ErrorContains(t, err, "not a successful tx") require.Equal(t, "", ballot) @@ -188,7 +207,7 @@ func TestEVM_CheckAndVoteInboundTokenGas(t *testing.T) { require.NoError(t, evm.ValidateEvmTransaction(tx)) lastBlock := receipt.BlockNumber.Uint64() + confirmation - ob := MockEVMClient(common.EthChain(), stub.NewTSSMainnet(), lastBlock, stub.MockChainParams(chainID, confirmation)) + ob := MockEVMClient(chain, nil, nil, nil, stub.NewTSSMainnet(), lastBlock, chainParam) ballot, err := ob.CheckAndVoteInboundTokenGas(tx, receipt, false) require.NoError(t, err) require.Equal(t, "", ballot) @@ -199,12 +218,13 @@ func TestEVM_BuildInboundVoteMsgForZetaSentEvent(t *testing.T) { // load archived ZetaSent receipt // https://etherscan.io/tx/0xf3935200c80f98502d5edc7e871ffc40ca898e134525c42c2ae3cbc5725f9d76 chainID := int64(1) + chain := common.EthChain() intxHash := "0xf3935200c80f98502d5edc7e871ffc40ca898e134525c42c2ae3cbc5725f9d76" receipt := testutils.LoadEVMIntxReceipt(t, chainID, intxHash, common.CoinType_Zeta) cctx := testutils.LoadEVMIntxCctx(t, chainID, intxHash, common.CoinType_Zeta) // parse ZetaSent event - ob := MockEVMClient(common.EthChain(), nil, 1, stub.MockChainParams(1, 1)) + ob := MockEVMClient(chain, nil, nil, nil, nil, 1, stub.MockChainParams(1, 1)) connector := stub.MockConnectorNonEth(chainID) event := testutils.ParseReceiptZetaSent(receipt, connector) @@ -244,13 +264,14 @@ func TestEVM_BuildInboundVoteMsgForZetaSentEvent(t *testing.T) { func TestEVM_BuildInboundVoteMsgForDepositedEvent(t *testing.T) { // load archived Deposited receipt // https://etherscan.io/tx/0x4ea69a0e2ff36f7548ab75791c3b990e076e2a4bffeb616035b239b7d33843da - chainID := int64(1) + chain := common.EthChain() + chainID := chain.ChainId intxHash := "0x4ea69a0e2ff36f7548ab75791c3b990e076e2a4bffeb616035b239b7d33843da" tx, receipt := testutils.LoadEVMIntxNReceipt(t, chainID, intxHash, common.CoinType_ERC20) cctx := testutils.LoadEVMIntxCctx(t, chainID, intxHash, common.CoinType_ERC20) // parse Deposited event - ob := MockEVMClient(common.EthChain(), nil, 1, stub.MockChainParams(1, 1)) + ob := MockEVMClient(chain, nil, nil, nil, nil, 1, stub.MockChainParams(1, 1)) custody := stub.MockERC20Custody(chainID) event := testutils.ParseReceiptERC20Deposited(receipt, custody) sender := ethcommon.HexToAddress(tx.From) @@ -288,7 +309,8 @@ func TestEVM_BuildInboundVoteMsgForDepositedEvent(t *testing.T) { func TestEVM_BuildInboundVoteMsgForTokenSentToTSS(t *testing.T) { // load archived gas token transfer to TSS // https://etherscan.io/tx/0xeaec67d5dd5d85f27b21bef83e01cbdf59154fd793ea7a22c297f7c3a722c532 - chainID := int64(1) + chain := common.EthChain() + chainID := chain.ChainId intxHash := "0xeaec67d5dd5d85f27b21bef83e01cbdf59154fd793ea7a22c297f7c3a722c532" tx, receipt := testutils.LoadEVMIntxNReceipt(t, chainID, intxHash, common.CoinType_Gas) require.NoError(t, evm.ValidateEvmTransaction(tx)) @@ -301,7 +323,7 @@ func TestEVM_BuildInboundVoteMsgForTokenSentToTSS(t *testing.T) { require.NoError(t, evm.ValidateEvmTransaction(txDonation)) // create test compliance config - ob := MockEVMClient(common.EthChain(), nil, 1, stub.MockChainParams(1, 1)) + ob := MockEVMClient(chain, nil, nil, nil, nil, 1, stub.MockChainParams(1, 1)) cfg := config.Config{ ComplianceConfig: config.ComplianceConfig{}, } @@ -333,3 +355,59 @@ func TestEVM_BuildInboundVoteMsgForTokenSentToTSS(t *testing.T) { require.Nil(t, msg) }) } + +func TestEVM_ObserveTSSReceiveInBlock(t *testing.T) { + // https://etherscan.io/tx/0xeaec67d5dd5d85f27b21bef83e01cbdf59154fd793ea7a22c297f7c3a722c532 + chain := common.EthChain() + chainID := chain.ChainId + confirmation := uint64(1) + chainParam := stub.MockChainParams(chain.ChainId, confirmation) + intxHash := "0xeaec67d5dd5d85f27b21bef83e01cbdf59154fd793ea7a22c297f7c3a722c532" + + // load archived tx and receipt + tx, receipt := testutils.LoadEVMIntxNReceipt(t, chainID, intxHash, common.CoinType_Gas) + require.NoError(t, evm.ValidateEvmTransaction(tx)) + + // load archived evm block + // https://etherscan.io/block/19363323 + blockNumber := receipt.BlockNumber.Uint64() + block := testutils.LoadEVMBlock(t, chainID, blockNumber, true) + + // create mock client + evmClient := stub.NewMockEvmClient() + evmJSONRPC := stub.NewMockJSONRPCClient() + zetaClient := stub.NewMockZetaCoreBridge() + tss := stub.NewTSSMainnet() + lastBlock := receipt.BlockNumber.Uint64() + confirmation + + t.Run("should observe TSS receive in block", func(t *testing.T) { + ob := MockEVMClient(chain, evmClient, evmJSONRPC, zetaClient, tss, lastBlock, chainParam) + + // feed archived block and receipt + evmJSONRPC.WithBlock(block) + evmClient.WithReceipt(receipt) + err := ob.ObserveTSSReceiveInBlock(blockNumber) + require.NoError(t, err) + }) + t.Run("should not observe on error getting block", func(t *testing.T) { + ob := MockEVMClient(chain, evmClient, evmJSONRPC, zetaClient, tss, lastBlock, chainParam) + err := ob.ObserveTSSReceiveInBlock(blockNumber) + require.ErrorContains(t, err, "error getting block") + }) + t.Run("should not observe on error getting receipt", func(t *testing.T) { + ob := MockEVMClient(chain, evmClient, evmJSONRPC, zetaClient, tss, lastBlock, chainParam) + evmJSONRPC.WithBlock(block) + err := ob.ObserveTSSReceiveInBlock(blockNumber) + require.ErrorContains(t, err, "error getting receipt") + }) + t.Run("should not observe on error posting vote", func(t *testing.T) { + ob := MockEVMClient(chain, evmClient, evmJSONRPC, zetaClient, tss, lastBlock, chainParam) + + // feed archived block and pause zeta bridge + evmJSONRPC.WithBlock(block) + evmClient.WithReceipt(receipt) + zetaClient.Pause() + err := ob.ObserveTSSReceiveInBlock(blockNumber) + require.ErrorContains(t, err, "error checking and voting") + }) +} diff --git a/zetaclient/interfaces/interfaces.go b/zetaclient/interfaces/interfaces.go index 422e36cc59..5d9a40fcc9 100644 --- a/zetaclient/interfaces/interfaces.go +++ b/zetaclient/interfaces/interfaces.go @@ -4,6 +4,7 @@ import ( "context" "math/big" + "github.com/onrik/ethrpc" "github.com/zeta-chain/zetacore/zetaclient/keys" "github.com/zeta-chain/zetacore/zetaclient/outtxprocessor" @@ -137,3 +138,9 @@ type EVMRPCClient interface { TransactionReceipt(ctx context.Context, txHash ethcommon.Hash) (*ethtypes.Receipt, error) TransactionSender(ctx context.Context, tx *ethtypes.Transaction, block ethcommon.Hash, index uint) (ethcommon.Address, error) } + +// EVMJSONRPCClient is the interface for EVM JSON RPC client +type EVMJSONRPCClient interface { + EthGetBlockByNumber(number int, withTransactions bool) (*ethrpc.Block, error) + EthGetTransactionByHash(hash string) (*ethrpc.Transaction, error) +} diff --git a/zetaclient/testdata/evm/chain_1_block_ethrpc_trimmed_19330473.json b/zetaclient/testdata/evm/chain_1_block_ethrpc_trimmed_19330473.json new file mode 100644 index 0000000000..e90f23309d --- /dev/null +++ b/zetaclient/testdata/evm/chain_1_block_ethrpc_trimmed_19330473.json @@ -0,0 +1,2049 @@ +{ + "Number": 19330473, + "Hash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "ParentHash": "0x267d191078b68fbd5be49e0274b6387943c892a4379bbfdedff9fcd45c0626a1", + "Nonce": "0x0000000000000000", + "Sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "LogsBloom": "0x05a54d18e50179d04c029178a3b01da3a2c34a8b5083fa792b2b04a0fc368432c5561425d383204ac138fba5654acb9c8209d0268d6274f01ea36423813eac648588157ac3cd9a7e6f01456f5ea8aaefc4491b11af4c59105c74db798864410c510c682c4e739369a9d157f620914ddd24991e755ab59706861188db541d821eaf0893ea2ced400a65713bec0fb01a761d09d4f10f908428461d154148f024688a87114a73a2bc529ecafcd49c2074bfeca41b2589f0498f87bba86629dd5361f7216c8345145249b246287701aad44931ea1e968758055ccbe5e23f125eff0c22d6ac09b214425a1c2c15acadf39eb0077d9c191178344b3b045b9239d8ac9a", + "TransactionsRoot": "0xd651daaca8c9a603fa2648d474233e8ddc912b9d831716f61f1faf0b4eddeac7", + "StateRoot": "0x29da2506610eee13a06d66c0fe881942da8e8b0413a0b8e19aa425efe6fd77df", + "Miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97", + "Difficulty": 0, + "TotalDifficulty": 58750003716598352816469, + "ExtraData": "0x546974616e2028746974616e6275696c6465722e78797a29", + "Size": 301417, + "GasLimit": 30000000, + "GasUsed": 18209718, + "Timestamp": 1709177027, + "Uncles": [], + "Transactions": [ + { + "Hash": "0x5bee6e0d1b2741badc5a490692a7e4ef118e3ad6736b206805ad6cfe69c18bdb", + "Nonce": 32, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 0, + "From": "0xe667c8621417c53ddea92375ab93d3f5efdeed18", + "To": "0xdef1c0ded9bec7f1a1670819833240f027b25eff", + "Value": 1416723496930938000, + "Gas": 139195, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0x0c13995bfdfcff59aee550461de184ec3a3513d11a06318c816dde72dd15e402", + "Nonce": 865356, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 1, + "From": "0x91aae0aafd9d2d730111b395c6871f248d7bd728", + "To": "0x98c3d3183c4b8a650614ad179a1a98be0a8d6b8e", + "Value": 0, + "Gas": 300011, + "GasPrice": 47548888839, + "Input": "0x" + }, + { + "Hash": "0x341f44ef7a89db8bab64aceb26bf36160f24c123c9d89aaa648573c7389f2eb2", + "Nonce": 719917, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 2, + "From": "0x3527439923a63f8c13cf72b8fe80a77f6e572092", + "To": "0xa0425d71cb1d6fb80e65a5361a04096e0672de03", + "Value": 0, + "Gas": 8000000, + "GasPrice": 52548888839, + "Input": "0x" + }, + { + "Hash": "0x7ba81db5dd1235a979179a9db318262771ac566fe87b0649b0536987ac150657", + "Nonce": 1914, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 3, + "From": "0xd93d10900f53a4f445a88d62efff803edfe20980", + "To": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49", + "Value": 0, + "Gas": 543760, + "GasPrice": 67558888839, + "Input": "0x" + }, + { + "Hash": "0x31ef5d0d7269b243280b7eb2263e2cdedbd3fa34c071759cf15e7c9447960710", + "Nonce": 77, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 4, + "From": "0xf1dfe5db0f757e6af9be2cc2e31725369e0088d5", + "To": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49", + "Value": 0, + "Gas": 543760, + "GasPrice": 67558888839, + "Input": "0x" + }, + { + "Hash": "0x167eac47b20fe4d1c1aafd9d4d384c047a49a0cdb52b11ae595c1de6b57616a5", + "Nonce": 1287, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 5, + "From": "0x270f4ceead65439c717fdcab0b7d0be6aff90589", + "To": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49", + "Value": 0, + "Gas": 543760, + "GasPrice": 67558888839, + "Input": "0x" + }, + { + "Hash": "0xeb5ad997da4b3ec54c0e32caf572f7fd177fc9491f898315bcd51698d3a8f95d", + "Nonce": 92, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 6, + "From": "0x8f640bd5a7e64743bb465fda991e8fdc0ceb4424", + "To": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49", + "Value": 0, + "Gas": 514568, + "GasPrice": 63548888839, + "Input": "0x" + }, + { + "Hash": "0x7e02193f398e276599a5aaad7d4de81009db3cde92dafe5e4ad35e29cd153663", + "Nonce": 227, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 7, + "From": "0xba405e4c0a416881e866e3486538706dd741fcca", + "To": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49", + "Value": 0, + "Gas": 514568, + "GasPrice": 63548888839, + "Input": "0x" + }, + { + "Hash": "0x2657838b6fe700fe08dd71761324e598106fcf8bc7929f6b3b92e433519c01c7", + "Nonce": 69120, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 8, + "From": "0x337a81113f934b8522459f0ca207eee7aa0f4545", + "To": "0xf8a16864d8de145a266a534174305f881ee2315e", + "Value": 0, + "Gas": 6000000, + "GasPrice": 50548888839, + "Input": "0x" + }, + { + "Hash": "0x252053df6a32c67a82d9298a65acd206ed3ef0be89b78c457bbb120d0de52186", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 9, + "From": "0xcad722685782b3d90470307ebbeca202d62c3b8a", + "To": "0xd523794c879d9ec028960a231f866758e405be34", + "Value": 980107655962837556, + "Gas": 248628, + "GasPrice": 60420315297, + "Input": "0x" + }, + { + "Hash": "0xa1a70772bf216b08883e2d5eedac69ddab262926d2a5dc51128d039eba802e77", + "Nonce": 48, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 10, + "From": "0x6c002142bd8ec3f20a7636e7973ca41888b42f7f", + "To": "0xdef1c0ded9bec7f1a1670819833240f027b25eff", + "Value": 0, + "Gas": 194442, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0x5b9c8b8b86c5735e4f851471cc233a3dec798f56e9daca8dfc178619c9990913", + "Nonce": 8664, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 11, + "From": "0xee28beaa11e31d10581ee7cfdcb9e95c8d05c53c", + "To": "0xfbeedcfe378866dab6abbafd8b2986f5c1768737", + "Value": 19330473, + "Gas": 450000, + "GasPrice": 47548888839, + "Input": "0x" + }, + { + "Hash": "0x398e5ab7943bbdc985d4d0b40450f4f10688d140d23db996e54ad67fa2bbeef6", + "Nonce": 1776, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 12, + "From": "0x768f1621f176b2010647be124f1f252ca849d6a7", + "To": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49", + "Value": 0, + "Gas": 587469, + "GasPrice": 57548888839, + "Input": "0x" + }, + { + "Hash": "0x9f7e0e7066c9cebb0523e698ddb26e063220f884b76d0f68fe07ff92fbaa1749", + "Nonce": 1091522, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 13, + "From": "0x6887246668a3b87f54deb3b94ba47a6f63f32985", + "To": "0xff00000000000000000000000000000000000010", + "Value": 0, + "Gas": 1695116, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x0f2a572995704d8d87419258f9d798c8ffd819550865412c21ab2a39fd070c79", + "Nonce": 76, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 14, + "From": "0x11ba386d08b622ca75f15d1ed6e716727aa27cdb", + "To": "0x6c42f24f2619d3de71a72a02a5fc2aa0cde667da", + "Value": 0, + "Gas": 679011, + "GasPrice": 51900000000, + "Input": "0x" + }, + { + "Hash": "0xa4ad716ce930d71f5c99c9fa0f26451f42cf93b16f1cb8e3509a56179bf20602", + "Nonce": 8381, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 15, + "From": "0x1e01eb96bafa7815d90b790329f1ceabed868181", + "To": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49", + "Value": 0, + "Gas": 513906, + "GasPrice": 52548888839, + "Input": "0x" + }, + { + "Hash": "0xcdd852efd3dbf10190b567eded010bf3ac46555aac1b47aebee90ea828a132d4", + "Nonce": 2444, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 16, + "From": "0xc8d5cf84e1aa38ffa9e5e532fc97b2f6e1c4740c", + "To": "0x1111111254eeb25477b68fb85ed929f73a960582", + "Value": 0, + "Gas": 166301, + "GasPrice": 54324000000, + "Input": "0x" + }, + { + "Hash": "0x23d5604ef20576c43e63d3e1b07e7dbcf81b5629bd968498b5f6bd6f04bc6aee", + "Nonce": 36197, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 17, + "From": "0x051acf8d69a18d6a6e4dd063b39501e69704ac50", + "To": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "Value": 0, + "Gas": 250000, + "GasPrice": 62000000000, + "Input": "0x" + }, + { + "Hash": "0x2c80a8a3bb3e48012a347c621bfb5edb4ab8f3b3f8dfa294c220b79d3907bca4", + "Nonce": 5951, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 18, + "From": "0x70ad6a24abd247fce9b87b2e85972049cc0170ad", + "To": "0xb62bdeda5d1e7a03a615b793e949c19d158c6b46", + "Value": 0, + "Gas": 425000, + "GasPrice": 50048888839, + "Input": "0x" + }, + { + "Hash": "0x9d9e3abb9b5bdb46b0518db5f46ff9dfd19bad2a78677de22286216582b85d76", + "Nonce": 43954, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 19, + "From": "0xc1e2a676c2cf7c8120e927396642324b4a3c0e75", + "To": "0x000000000dfde7deaf24138722987c9a6991e2d4", + "Value": 0, + "Gas": 600000, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0xe74f94622c7a2e46631394dc64777f6c8c65610202d7a81d9e0f5995ccd85354", + "Nonce": 122, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 20, + "From": "0xd54ec19313e39293dec6b86adad6713e4aaa11d0", + "To": "0x663dc15d3c1ac63ff12e45ab68fea3f0a883c251", + "Value": 1000000000000000, + "Gas": 361252, + "GasPrice": 49948888839, + "Input": "0x" + }, + { + "Hash": "0xc0b383d4e0735054415ee6e43c7b02d4f3daae50192dd8a3c3e2b2092cd3bddf", + "Nonce": 12005, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 21, + "From": "0x5acf4e865604ab620fb84acc047b990f2d2856fd", + "To": "0xf3f04555f8fda510bfc77820fd6eb8446f59e72d", + "Value": 0, + "Gas": 384855, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0xc9986543cd16efe7c8721a952c22ae682438092e0d695631de8d80e276997c74", + "Nonce": 82954, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 22, + "From": "0x2a4a7afa40a9d03b425752fb4cfd5f0ff5b3964c", + "To": "0x478238a1c8b862498c74d0647329aef9ea6819ed", + "Value": 0, + "Gas": 740000, + "GasPrice": 48912763532, + "Input": "0x" + }, + { + "Hash": "0xd01b0102d2aaebff16b0948286bff2e3e608527b1f9374d10b33cefd952db4cf", + "Nonce": 458436, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 23, + "From": "0x477b8d5ef7c2c42db84deb555419cd817c336b6f", + "To": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "Value": 0, + "Gas": 96082, + "GasPrice": 54473432550, + "Input": "0x" + }, + { + "Hash": "0x0b25476c3d3ddec226669cfcad1569c5d16f8c3e44e16bba9462f01758acf168", + "Nonce": 151971, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 24, + "From": "0x1ab4973a48dc892cd9971ece8e01dcc7688f8f23", + "To": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "Value": 0, + "Gas": 100000, + "GasPrice": 53336252238, + "Input": "0x" + }, + { + "Hash": "0x29a099996fd425797f48b4efbc521d23eb5b27baa8c1ed863d1089592839557e", + "Nonce": 9928, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 25, + "From": "0x147b12c06d9e8e3837280f783fd8070848d4412e", + "To": "0x5c7bcd6e7de5423a257d81b442095a1a6ced35c5", + "Value": 0, + "Gas": 115204, + "GasPrice": 50031355791, + "Input": "0x" + }, + { + "Hash": "0x49dbad8af7ea4dd6e05bbf0b1bdd4eef3c90f1876b0bf902cf4dfdfb35786488", + "Nonce": 266, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 26, + "From": "0x6f1e9f00c32d11a366405a1811389a088f7bc46b", + "To": "0x72c60bfffef18dca51db32b52b819a951b6ddbed", + "Value": 0, + "Gas": 120000, + "GasPrice": 52548888839, + "Input": "0x" + }, + { + "Hash": "0x1e29f0736e1e26d28373e05f0eeb3b7da5cb808372979693cbb26d9ba56942e2", + "Nonce": 43, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 27, + "From": "0xf319661f8a3d9055acd7465ef81583440194f91c", + "To": "0xa397a8c2086c554b531c02e29f3291c9704b00c7", + "Value": 0, + "Gas": 274471, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x5482b876b39ba649e1e762f015baacaa61d8278d63be31e894a23fbc3b189eab", + "Nonce": 2134, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 28, + "From": "0xc645677ce475e6bb1d14a42d0be45da24b636c99", + "To": "0x00000000000000adc04c56bf30ac9d3c0aaf14dc", + "Value": 350000000000000000, + "Gas": 210218, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xc8b9ad09aa7fc266bb7c25929f77e4df2afb9869f7a030e88a6309f7d5e1e808", + "Nonce": 24, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 29, + "From": "0x059f2909875a4d309e9750361eaae03e14fe3d58", + "To": "0x72c60bfffef18dca51db32b52b819a951b6ddbed", + "Value": 0, + "Gas": 56421, + "GasPrice": 50548888839, + "Input": "0x" + }, + { + "Hash": "0x63e93a33f662ba39aa5ee3caa63b9e56d6fa4b4b1e0fbbe5ceac0b74e7b6895e", + "Nonce": 2502215, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 30, + "From": "0xf89d7b9c864f589bbf53a82105107622b35eaa40", + "To": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "Value": 0, + "Gas": 90000, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0x2ba11f551f8130d19869d1e749016e61d5487e9d66f67d52e39f7d84f7f88191", + "Nonce": 9077862, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 31, + "From": "0x28c6c06298d514db089934071355e5743bf21d60", + "To": "0x6de037ef9ad2725eb40118bb1702ebb27e4aeb24", + "Value": 0, + "Gas": 207128, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0xcc4413ee408069d6d9d50c8e1f17df8e5d483cda50de6128bc941c7942fcc99c", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 32, + "From": "0x341468f2b13155c4c0ff4c6f727189821e09f1cb", + "To": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "Value": 0, + "Gas": 59533, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0x0db56ba3ff4ba73b12d7abae6c63add8ad47133094dd2c3950511586ccdfe67e", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 33, + "From": "0x14aff39623f752f9a190d6cf0140bbd7d8754e6b", + "To": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "Value": 0, + "Gas": 59533, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0xbf6f3a77df707bfdeb7dbb40a41f8cc895609a2e053e593745d2c36ecd19a689", + "Nonce": 2, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 34, + "From": "0xdb8250f7be41362bd7245c2f8a200a62ebc2489a", + "To": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "Value": 0, + "Gas": 59533, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0x5681005e4a6a3538761efa55dcbb7f2a3f82dfcb9bb597aba7ace344b81a88c0", + "Nonce": 1, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 35, + "From": "0xbcda3d2714c7a16752610a1a639c31024cc2eb77", + "To": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "Value": 0, + "Gas": 59533, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0x24d7f9fe3de7e6ab5a812eaf9e0fbc8e9d8a52ca5546f27132ae288ae176b7ae", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 36, + "From": "0x457fefbde35d635f198cde14a9bc31ae1c62fa28", + "To": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "Value": 0, + "Gas": 59533, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0x82d81463b5074deca126bff83beef3722d04afb5b310cfaded1509cf3927cc51", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 37, + "From": "0x3f8934cbb4584f4d1f0d723f532920d916da2384", + "To": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "Value": 0, + "Gas": 59533, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0x7990fda5113774b18a34279fb025d50e97b6997b6f98b5756006625f21473688", + "Nonce": 1, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 38, + "From": "0xf3cb1448109eb769bbe3a254c47f6c5054fed057", + "To": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "Value": 0, + "Gas": 84000, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xe01c7a56342f619e8007904f15af64e67a1d29ad6877abadb2e8b888884e6bc7", + "Nonce": 29402, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 39, + "From": "0x13307b8854a95946b54a904100afd0767a7a577b", + "To": "0x06450dee7fd2fb8e39061434babcfc05599a6fb8", + "Value": 0, + "Gas": 50948, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0x5a82e744641c74badff4df9bceb1ca00c920af42a8ef011504a07b9bf8924532", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 40, + "From": "0x75a7d1cf30156157e2d68be10f3fc4479b3c8606", + "To": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "Value": 0, + "Gas": 64000, + "GasPrice": 48336252238, + "Input": "0x" + }, + { + "Hash": "0xf421f19c805272d9b4395ebc5265d6da785d3f21610473738ee18572608b7ccc", + "Nonce": 18944, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 41, + "From": "0x22a82147a80747cfb1562e0f72f6be39f18b5f76", + "To": "0x40864568f679c10ac9e72211500096a5130770fa", + "Value": 0, + "Gas": 11000000, + "GasPrice": 47648888839, + "Input": "0x" + }, + { + "Hash": "0xacf927dd81243412a557e43be957841e9fe5d933331acfed537e67c17594385b", + "Nonce": 1441, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 42, + "From": "0x6fb3dbc55cf59a1e5eb71ae973900768ff83258d", + "To": "0x6b175474e89094c44da98b954eedeac495271d0f", + "Value": 0, + "Gas": 62196, + "GasPrice": 48000000000, + "Input": "0x" + }, + { + "Hash": "0x56a989c393b60418e8dcad21861fb173f26cbd9ace6c38fe37338548b1b530a0", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 43, + "From": "0xf99f7a261ace91f73d0c675c538420c680b5185a", + "To": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "Value": 0, + "Gas": 46085, + "GasPrice": 48050284419, + "Input": "0x" + }, + { + "Hash": "0x977625bfecff53b416d41bbc45121f207c48083226c92515269a146005428560", + "Nonce": 1071, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 44, + "From": "0xe916778c679adda1d506d1783c7a5a3e49bc6056", + "To": "0x0df596ad12f927e41ec317af7dd666ca3574845f", + "Value": 0, + "Gas": 64000, + "GasPrice": 48336252238, + "Input": "0x" + }, + { + "Hash": "0xf8194e8f3b2a6b173e70490df4b4557e8d34d80440fd3b9c931fda269419378d", + "Nonce": 30, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 45, + "From": "0xd7ed1433ad6fcf2cd393fd5e72b63c4e5fc6f3aa", + "To": "0xd1d2eb1b1e90b638588728b4130137d262c87cae", + "Value": 0, + "Gas": 55000, + "GasPrice": 48000000000, + "Input": "0x" + }, + { + "Hash": "0x5ef4e7fe0c62cae78f2a05d859f2f028db31c62023e51110749f5089ac7a4e97", + "Nonce": 199, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 46, + "From": "0x7154b682e8fdb4207c035d2f037ad6448bbb8581", + "To": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", + "Value": 0, + "Gas": 356240, + "GasPrice": 47648888839, + "Input": "0x" + }, + { + "Hash": "0x9a1b2c12715ddc52fd81535f2bfa98a65b2774b0a9ef9753523968beeb33266b", + "Nonce": 2, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 47, + "From": "0xbad22e79a5b9309114a1ca3fcfc9cfe11474241a", + "To": "0x253553366da8546fc250f225fe3d25d0c782303b", + "Value": 1492833416759225, + "Gas": 588404, + "GasPrice": 47598888839, + "Input": "0x" + }, + { + "Hash": "0xf1d7bdc606994fd5fbc5c9b29b86080ae2cba8d0027797b5e78396edd9cd25f2", + "Nonce": 15, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 48, + "From": "0xd29297fbc7717ae056742bff56c76a231e232e05", + "To": "0x00000000ede6d8d217c60f93191c060747324bca", + "Value": 0, + "Gas": 1013974, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x8dc1cf3dfe14fb2594bce70cdc98ccbaf60a4cded5add1c050106a1908d340da", + "Nonce": 18, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 49, + "From": "0x17bbf977991336100f444d97e39cfb4f13a213f9", + "To": "0x68b429161ec09a6c1d65ba70727ab1faa5bc4026", + "Value": 0, + "Gas": 68026, + "GasPrice": 47628888839, + "Input": "0x" + }, + { + "Hash": "0x4e8460b89fd983c06e5303105f0a228be7f64a5c21ffb4c3bb15fbacabe71478", + "Nonce": 1, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 50, + "From": "0x36bb3e0a7823f39826b79a3f1f4d2bf1bb3c5767", + "To": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "Value": 0, + "Gas": 50000, + "GasPrice": 47648888839, + "Input": "0x" + }, + { + "Hash": "0x59d0f7e63988e79724b45b673e52844ba7f5764a9301a9e2eae40e7df45790f2", + "Nonce": 6, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 51, + "From": "0x10ee730e8c4f19dce08d4548b3de8045e8b87e9f", + "To": "0x808507121b80c02388fad14726482e061b8da827", + "Value": 0, + "Gas": 60664, + "GasPrice": 47628888839, + "Input": "0x" + }, + { + "Hash": "0x09c2cab6cf4a951a55e1af620e7a1478520f60bc5ad9493da639247dbba80b92", + "Nonce": 6, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 52, + "From": "0x5cf88277ac14867a1e21e319db3f7a2691dab6d3", + "To": "0x13f4ea83d0bd40e75c8222255bc855a974568dd4", + "Value": 0, + "Gas": 271485, + "GasPrice": 47562888595, + "Input": "0x" + }, + { + "Hash": "0xfa5b3a5ca053e1c13afc665443f96b30a0709dbc3003f1a6e1bb862983c2fd48", + "Nonce": 25, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 53, + "From": "0xa34f5b8c3493e710bc27fccf071e6b021ca18a08", + "To": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", + "Value": 0, + "Gas": 258530, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x72439934df548b919204bc6eaee2955bda5ef72573163469f435eda159767762", + "Nonce": 18, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 54, + "From": "0xbde1f1dac1e001a272cb083962179d8a152c551b", + "To": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "Value": 0, + "Gas": 85067, + "GasPrice": 47598888839, + "Input": "0x" + }, + { + "Hash": "0xe2ca844813c39450eb4d6a29f18e949a9d1410977e96a9a885f1de60b682e210", + "Nonce": 802, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 55, + "From": "0x334022d77bfc9e8aa5b34907873457c545d9faf2", + "To": "0x1a0ad011913a150f69f6a19df447a0cfd9551054", + "Value": 0, + "Gas": 958579, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x8a0bb204842e7ee03022614256e441ed333c6a74acbb1407672fb888c150ae33", + "Nonce": 326, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 56, + "From": "0x63126fdc6111f874ada547b9d7deb607503463a7", + "To": "0x500bfddf51e77da46ce7c8ca00ef153335420fb4", + "Value": 0, + "Gas": 44955, + "GasPrice": 47647888839, + "Input": "0x" + }, + { + "Hash": "0x67ae0da37ee873c8b58c6556b0a7c56fa93c2ba31b91b781c2712b9d86435962", + "Nonce": 43, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 57, + "From": "0x8d40a76ad48f05b8041f58430d3e903afb49dd44", + "To": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", + "Value": 0, + "Gas": 210315, + "GasPrice": 47562888595, + "Input": "0x" + }, + { + "Hash": "0x48136ab67c5d2a4e7a04168cceb9b32a35601b82e947bc94e276f9783a42d9b7", + "Nonce": 2199, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 58, + "From": "0xd605b8c680c34f15d7aaf597494fd839f75eba18", + "To": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", + "Value": 0, + "Gas": 226411, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0xc31582514217131df5ecfa98f6a1c109f099d060d493699b6bc6e86297c602b3", + "Nonce": 4174, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 59, + "From": "0x7a6b049d83554da1175d65be3f6264a74a05ae17", + "To": "0x29469395eaf6f95920e59f858042f0e28d98a20b", + "Value": 0, + "Gas": 161687, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0xc18b766e65a6ee620f377b7164dccd1510852d5027fc37f568ad8e59b459f5a6", + "Nonce": 1, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 60, + "From": "0x65ea5ecbe773e1ac344727d2534d9402e29cb8f5", + "To": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", + "Value": 250000000000000000, + "Gas": 208940, + "GasPrice": 47563634797, + "Input": "0x" + }, + { + "Hash": "0x1eaa0f39ba31d67be255e7d3af73b8697018cf3195afbf163b8eb8e4a964b70d", + "Nonce": 1500, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 61, + "From": "0x54c04155f5ffda3e6bf81ae76bf8fc6ebd6a2c05", + "To": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", + "Value": 6000000000000000000, + "Gas": 212673, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x9c37ea5b81385211d034f26714bee77380a3e014460a7bba2b935131fc392b5b", + "Nonce": 579, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 62, + "From": "0xa14368e5a732611adc565f3cad488f30d0023166", + "To": "0xb2ecfe4e4d61f8790bbb9de2d1259b9e2410cea5", + "Value": 0, + "Gas": 152191, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x88638b75a3078b51330670ba7ee25f6704fe8fb6366e6725c107632bd7358b33", + "Nonce": 94, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 63, + "From": "0xf2215488e721386d93d764cb63dae81ffa85989a", + "To": "0xec2432a227440139ddf1044c3fea7ae03203933e", + "Value": 0, + "Gas": 129878, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x2a84c9bbfc12a16d075ae9c0e7e7d5632c9af8114560eeaf5415e6b3830d1d8d", + "Nonce": 4091, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 64, + "From": "0xe14b4585795befea1b08a4317b46ca218000ac93", + "To": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", + "Value": 500000000000000000, + "Gas": 180666, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x9b60ea1aeb4a7eeda09663e9f4299ee6829fa22168c1bd17d7e67dbf56d005d3", + "Nonce": 1365, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 65, + "From": "0x0028109b8b6ca54e7e1c372cfc2a68b7e477cd43", + "To": "0x3bdca51226202fc2a64211aa35a8d95d61c6ca99", + "Value": 0, + "Gas": 206076, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0xaf40f5ec304afc4e472dcfb0092e414f3e54b1f87c5a99b61a63efbe17da7399", + "Nonce": 9209, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 66, + "From": "0x24a9ee0ee55f08813924734cd703ab41c045c643", + "To": "0x1111111254eeb25477b68fb85ed929f73a960582", + "Value": 0, + "Gas": 157232, + "GasPrice": 47563634797, + "Input": "0x" + }, + { + "Hash": "0x899e838f75dd574d44f088db7bc0f118cdd7e7176b0f8031b6cab1c25d92be6f", + "Nonce": 9, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 67, + "From": "0xc16822f9109ea30a58d3572d02a6de2c80ac02d1", + "To": "0x5f6ae08b8aeb7078cf2f96afb089d7c9f51da47d", + "Value": 900000000000000000, + "Gas": 125810, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0xde8f572e197f11e6837b5f6c6a5e673aa7251f7855a4848d79af10c7ca13127e", + "Nonce": 7273, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 68, + "From": "0xdda42f12b8b2ccc6717c053a2b772bad24b08cbd", + "To": "0x9d39a5de30e57443bff2a8307a4256c8797a3497", + "Value": 0, + "Gas": 145800, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x9719a79d81ab3a15bc7d88c96c4edf4f52d9dbea98351e259dbad342bec55594", + "Nonce": 53, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 69, + "From": "0xdf0f1ef01bb8b994efbadec67f1a4eab05651fe7", + "To": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49", + "Value": 120000000000000000, + "Gas": 3000000, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x57f11c80b1e1f06c483f61f107005bbc9f09e8404e2c7954668f4a39c69303b0", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 70, + "From": "0x306c113ba7c60121bec46d170628796607ca2410", + "To": "0xe03f81bcb9f7876a1a64f9ece379df1e189ebdc8", + "Value": 7322726194273998, + "Gas": 21000, + "GasPrice": 56582707735, + "Input": "0x" + }, + { + "Hash": "0x03636251efc508996a2ebd590ed8736e3bbe0a3ff9c499b8c2ab924a8ed66350", + "Nonce": 8, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 71, + "From": "0xb83a8df4b68d18e3d85e6d708244f3d09e995899", + "To": "0xa5fc7bc086a0c07688f09ffea3917052b83d3a2e", + "Value": 48456575324369561, + "Gas": 25200, + "GasPrice": 50375597873, + "Input": "0x" + }, + { + "Hash": "0x689e68d62fd6645b107189e439e7539e2babce2d69deeb595b83dedda9cf1ee4", + "Nonce": 15, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 72, + "From": "0xecaa84f671320b817832d69004f9408ee46642d1", + "To": "0x808d0aee8db7e7c74faf4b264333afe8c9ccdba4", + "Value": 998959473334381000, + "Gas": 21000, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0x5ab8572fda8661d6627ac76e05a46808aa2efb922e6061c750c0488f9154d31b", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 73, + "From": "0x20e7fb230e12f1a1e51e986fb9b7c613c3904494", + "To": "0x808d0aee8db7e7c74faf4b264333afe8c9ccdba4", + "Value": 55670053334381000, + "Gas": 21000, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0x2da537de7f841c6bc9dd185d522a1160090147a51ce434b36bac5dbd1f8869ce", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 74, + "From": "0x38d43560972227d51c5c6394234a7f24c7b10b42", + "To": "0x808d0aee8db7e7c74faf4b264333afe8c9ccdba4", + "Value": 11890263334381000, + "Gas": 21000, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0x1efdc55822942555bdac56c955f6b5689a72d89b8d0c7f144c0c3caff341a1a6", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 75, + "From": "0xac7459107f545d0fc131199f360f4635af3a79df", + "To": "0x808d0aee8db7e7c74faf4b264333afe8c9ccdba4", + "Value": 83809303334381000, + "Gas": 21000, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0xb9012da1b2c7df70c2511ea0326eacd38e5ee98114ef0ac4173b165fe6b6e82c", + "Nonce": 6231082, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 76, + "From": "0x56eddb7aa87536c09ccc2793473599fd21a8b17f", + "To": "0x9b935c8336b825970a9434c3f78df91f6b5f8d50", + "Value": 1768895550000000000, + "Gas": 207128, + "GasPrice": 49548888839, + "Input": "0x" + }, + { + "Hash": "0xa86f930e7a2a63bd1243db9af08c34dc0f509b23fe250a1530bde1d6b1eb1d48", + "Nonce": 1864, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 77, + "From": "0xb6f30f6fff1fbc6597c6e32a8865b1bccfe84c5d", + "To": "0xb0999731f7c2581844658a9d2ced1be0077b7397", + "Value": 10000000000000000, + "Gas": 53793, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0x60d2cbe80d21bfa0cac4f5c79b484c33c42f4f46fd0529575cd70431d04851ee", + "Nonce": 24223, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 78, + "From": "0xe795d3de925c970cbef7c691f9c39505202afaca", + "To": "0x76da499494e8f6abcf0f664447b4ad28b17d535a", + "Value": 50270000000000000, + "Gas": 21000, + "GasPrice": 49000000000, + "Input": "0x" + }, + { + "Hash": "0x61f05f0c8a97fd5e17767c5d253a844a239f066e86f695d274ebcb43a103bee6", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 79, + "From": "0x0c521549dda8e9f615061a300314f9327ff10a75", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 462768287051891733, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x7756d1e8d4b884047d190758c52f75a91b1e11ba3ee272897be0414e7e05cc21", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 80, + "From": "0xed5d47f643dbcd64096e4399b486a5448af8a9c9", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 776842068302016208, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x8e2bd179ee3bdd484342b4ba3eb4780e448bbcd2b7ca8f351f5000f7273250a5", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 81, + "From": "0x01aa8a859d6b3dfdfc3f63d7062dfb3f338569c9", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 3707370000000000, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x792a13933220d317b3426eff47b61fdef525610ac865c9379ba6668140db805b", + "Nonce": 1132, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 82, + "From": "0xec129edf84da5b5f08646287094382a1ba2be81d", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 2691841796684382, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x479efae546660b04b64931e63049a1f5df7fa7bcc4225a03a19bf272ede60e7e", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 83, + "From": "0x66a7ce4255ec75a3df27a5158ab4107dc42902fa", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 12058320359425533, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x74b6d1968d9c98f20a6e8b148f11d21bc3ea85f27481bdfd51c2f35d697ad250", + "Nonce": 35, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 84, + "From": "0x03c8bd4e8b328d351d2683e20f1ac4ad40722837", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 2198094609990875520, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x84c46064dfeb21a91b7a56ace478a15c5a0dd43f8ff803b56bf2315f2763e6a7", + "Nonce": 2, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 85, + "From": "0x50085d3cc268a7054ae1ded2e956ec5193d261ec", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 2150976788762877156, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x21b0e4dc76491ca3c31f9d926b8b6afaaa84f2370fba645a6884a602b8b46efc", + "Nonce": 4, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 86, + "From": "0xce237f7fb5aebf96972780f6e79a0db11f50fbfc", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 16578017150183975, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x515db3b4bab7fa0788df13f8eb913a4034cb0fcb37f2d4f42d28907666b694cf", + "Nonce": 22, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 87, + "From": "0x86ef12fbece63a18d80f2eabd81a4706d7e35071", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 42529768051405192, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xe0ecbb0f7c5b2fcfca8c91a5a3346a3aad979f79c5ebf40d842cc1960dec42f5", + "Nonce": 83, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 88, + "From": "0x2b992826fe89d44fc7f07b9f8c00ed8044232a47", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 8411773680572080, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xb1c99449c28e8ec77d2b702867c1eb9a5ab14dca6b33101a412c0e935a241bdc", + "Nonce": 1, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 89, + "From": "0x9122ab4d401274136117d6d5636d40edbb235b4f", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 3999077726144250130, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xbe84ac778a8918852741f26b0254c280c7a0f7fc2e5ebaebebccf0b8c0ae71ac", + "Nonce": 12, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 90, + "From": "0xc87785da0dd6226809e6b715d70710436b9013b5", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 21742364570290170, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xc27253ed1ca9495b9e4057c7b6cdc0ee60306776601d465d2faa0785216cd49a", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 91, + "From": "0xff06ab0d2ff3d7fb0a9bb2fed17404ba90734568", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 26972374121195485, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x0e41f1276c56987ad0b66361614bd066d878de214bb7f08bee818542b5514609", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 92, + "From": "0x30a1344d200e4c0e048d6dba93cc786a867514f8", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 7634516628410000, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xfe945134cad8513e751db4dc712c187f696bdbd2a39ea97f4f79b70cf55379cb", + "Nonce": 1, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 93, + "From": "0xb1d24bf0f6d54b8527231a1a1fe812f92523505f", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 7524752371580930, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xe466533d07d274fcbc1205ec840a52a1bed23a9bb66a55e9acca53055b250673", + "Nonce": 6, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 94, + "From": "0xb3568635218c1efac483a1bdec41aed08fc15de5", + "To": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43", + "Value": 498828636624236675, + "Gas": 23300, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x215e1cd032cbec84e5549cd955e6d8cf44f483df4f3668f450b00e384068580e", + "Nonce": 960462, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 95, + "From": "0x6081258689a75d253d87ce902a8de3887239fe80", + "To": "0x25a8e4634ab19a6c49d3cf1a0ff1b5e20e3e8834", + "Value": 1760689100000000, + "Gas": 21000, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xd5ebb2dbe96fe6d97d344bd70355a756f691f518f14493b33e92738778a7d350", + "Nonce": 6882, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 96, + "From": "0x01b7a710bab5fe81564feed292b631896c7f0a53", + "To": "0x108ab2f19995b00dbc7f279296dd14448da8328d", + "Value": 3573262641172520, + "Gas": 21000, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x5b59d52bcd79e4632c22e74b911bc61285d9afe54418563f7b199dafa238c626", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 97, + "From": "0x56fec52ef29ce01b7d29698b96c94e5906a6c69c", + "To": "0x95a9bd206ae52c4ba8eecfc93d18eacdd41c88cc", + "Value": 569988216421831016, + "Gas": 21000, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0x2a1113bd1a869f52ec4d1bbcf811b94581a038430b6806e75b8c09f5d14581fd", + "Nonce": 1, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 98, + "From": "0x821c0e818ab6fb03f9f54d536c705f554f07b340", + "To": "0x95a9bd206ae52c4ba8eecfc93d18eacdd41c88cc", + "Value": 34633538809596195, + "Gas": 21000, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xf64cd1a3890cbf0edcc5f732fd34ff9896d2334282f5f943c5ff4a3d67c853d4", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 99, + "From": "0x2e7bb229a8174f705aefd619fcf4f09f5e32a015", + "To": "0x95a9bd206ae52c4ba8eecfc93d18eacdd41c88cc", + "Value": 5757192435004000, + "Gas": 21000, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xc6c44bd646f6882b3921cb1a9480abb30b61e7d0f27be8847cf0e286a4631f7b", + "Nonce": 8, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 100, + "From": "0xf2d3600dbc36a3d5bb8edb497b9d1b5a72040f8b", + "To": "0x95a9bd206ae52c4ba8eecfc93d18eacdd41c88cc", + "Value": 379756371914635899, + "Gas": 21000, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xe2cffea80d923c4f28dcc4a8e3e0ed1ea8e9a4f06ab4d6f83df0e51cc82fd2bc", + "Nonce": 12, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 101, + "From": "0x5038ee2d5fd2f0882d93de981e0d1948e925d41f", + "To": "0x95a9bd206ae52c4ba8eecfc93d18eacdd41c88cc", + "Value": 55855263972735000, + "Gas": 21000, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xbcd296d46802e367ea89cc8325387cb478e21a6d41e68c3ed71e562a1aa17ef9", + "Nonce": 4, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 102, + "From": "0x2a392e4d9612b2dd13bcdead01553bfb2da31e07", + "To": "0x95a9bd206ae52c4ba8eecfc93d18eacdd41c88cc", + "Value": 22022413995598520, + "Gas": 21000, + "GasPrice": 48548888839, + "Input": "0x" + }, + { + "Hash": "0xff4d706971881b6d796b08fc9b483ae0fe7c062a822c365ddd900b5a054e6ac4", + "Nonce": 13, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 103, + "From": "0x6ec5c96b2d142dbe089e0695d855a139129e9ee7", + "To": "0x5a7d87c42bc19993cde05fe9283431af7cb60735", + "Value": 150000000000000000, + "Gas": 21000, + "GasPrice": 48048888839, + "Input": "0x" + }, + { + "Hash": "0x30a61ee639a59645616969912d9a301df1d7d949d9b83d9f1e4cc0bb46088c81", + "Nonce": 39, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 104, + "From": "0x3168c5cb525998fca7780efa73c5769495faa813", + "To": "0x4e69e175f8a21a3ab9e1fa99f36c45734cf8600b", + "Value": 5000000000000000, + "Gas": 21000, + "GasPrice": 48048888839, + "Input": "0x" + }, + { + "Hash": "0x0d7495e7ce3b09aeb56d157e98899bc655f1813a1cd3831870aacbfbff4a04c9", + "Nonce": 15, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 105, + "From": "0x8418a8ed7fa1ded5882cf94aff001c7904a7be5c", + "To": "0xaf5323a542651a844be3b2c0d52e4f0f0dfe086d", + "Value": 1616741584510527773, + "Gas": 21000, + "GasPrice": 48048888839, + "Input": "0x" + }, + { + "Hash": "0x3c005eeaa9e7984f552dab48edcee960bab3a7ad43ce99bd31e935ca7914dc56", + "Nonce": 1013320, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 106, + "From": "0xa4e5961b58dbe487639929643dcb1dc3848daf5e", + "To": "0x61ee5aaced0063c06ded69ce4325af5c571ae752", + "Value": 5424350000000000, + "Gas": 22000, + "GasPrice": 48000000000, + "Input": "0x" + }, + { + "Hash": "0xd28184c4005790955d76746ba263f058e9cfc1dc25b166befd7d67ce23832a10", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 107, + "From": "0x254493aedff08427c23f1d1b836c6eae8a744461", + "To": "0x077d360f11d220e4d5d831430c81c26c9be7c4a4", + "Value": 28329090000000000, + "Gas": 22000, + "GasPrice": 48000000000, + "Input": "0x" + }, + { + "Hash": "0xfad63a744af9d33038825461d0f6e84640cbdbfd11cab5b1ef1eb9a88a7f71dc", + "Nonce": 1043002, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 108, + "From": "0x077d360f11d220e4d5d831430c81c26c9be7c4a4", + "To": "0xee9fda27eab28306ac66685a4d4c3a1208d35653", + "Value": 166210860000000000, + "Gas": 60000, + "GasPrice": 48000000000, + "Input": "0x" + }, + { + "Hash": "0x8d39bd123d74eaccde632fbe78138b4e7f8fe0448a9d980a2513bc94b800035c", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 109, + "From": "0x432b2637e3bbe8333e90e03191664d7547f29d80", + "To": "0x077d360f11d220e4d5d831430c81c26c9be7c4a4", + "Value": 28943990000000000, + "Gas": 22000, + "GasPrice": 48000000000, + "Input": "0x" + }, + { + "Hash": "0xce377e372d440c9363e481e447afd74afb4fe20a58e6943ceab8d7e944e48e48", + "Nonce": 2004683, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 110, + "From": "0xa7efae728d2936e78bda97dc267687568dd593f3", + "To": "0x68210ab6751e22e6da1ef0f2775e0cf24605f2c0", + "Value": 10300000000000000, + "Gas": 210000, + "GasPrice": 47648888839, + "Input": "0x" + }, + { + "Hash": "0x6060290431252299f0b1d6c5cea973963695dbb11f39ceb84f77026c47ca638f", + "Nonce": 1049017, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 111, + "From": "0xf7858da8a6617f7c6d0ff2bcafdb6d2eedf64840", + "To": "0x5615c4420a748dfab816444525c42e712f7c4d21", + "Value": 942231000000000000, + "Gas": 210000, + "GasPrice": 47648888839, + "Input": "0x" + }, + { + "Hash": "0x4617b64e1978ae7971848ddab6e96f235345622bd259521d09ee99ca744a127d", + "Nonce": 2, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 112, + "From": "0x5f7feb96ff866ddcf7d8ee66b28871f1471f40cd", + "To": "0x5f6ae08b8aeb7078cf2f96afb089d7c9f51da47d", + "Value": 20000000000000000, + "Gas": 102242, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0xfbf3a065ec8501850a1a3e4621c430db75f0546badff8ff2d82330864323eec0", + "Nonce": 889, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 113, + "From": "0x40e4587954c57ade62f3753a970e26eec6330831", + "To": "0xa0c68c638235ee32657e8f720a23cec1bfc77c77", + "Value": 185874839935350428, + "Gas": 111592, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x756305e0f8bbb11ba297dd031ee5cd081cfd09466cb5b9b8c6f2b8e603f50b0e", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 114, + "From": "0x9b05eaf9bcf2140bd28ecdfb9110c541cc7dbf69", + "To": "0xa7606281f7808167b5faf89f4d898685a8b87549", + "Value": 0, + "Gas": 47659, + "GasPrice": 47564242815, + "Input": "0x" + }, + { + "Hash": "0xd1496bdf94edb7b1f6792c9af5505dffeae43906dfc298480df9b88b98770714", + "Nonce": 13, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 115, + "From": "0x40594aee4f3bad820236dfca99b6e1dafa66e45d", + "To": "0xd9a442856c234a39a81a089c06451ebaa4306a72", + "Value": 0, + "Gas": 51760, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x7075039ec476e9be1623f356c2fc4545428e01da851749804b7e74d4c73a53d7", + "Nonce": 128, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 116, + "From": "0x0847cc113a7899eca102964a6be39f3874fdc84e", + "To": "0xff3f8227c3b0241848e1420ec77d61aee2ad5f67", + "Value": 0, + "Gas": 46546, + "GasPrice": 47563634797, + "Input": "0x" + }, + { + "Hash": "0x5c80539bf17c55d82179ce4501ff61215422067c4ba1424c087dfc167e72c1fe", + "Nonce": 3, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 117, + "From": "0x1e601320e64e0edde73e136911fffd04767bddd8", + "To": "0x4c9edd5852cd905f086c759e8383e09bff1e68b3", + "Value": 0, + "Gas": 70464, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x8d897b787c1f419bef334c0947d32c86960bdf6775460faecee751bb38ca5caf", + "Nonce": 807, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 118, + "From": "0x1bccea07ae47ae3c5f8207e253fcf733d19412ed", + "To": "0xfaba6f8e4a5e8ab82f62fe7c39859fa577269be3", + "Value": 0, + "Gas": 46976, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x898b8023a05933eb967f4caeb56b78ff12c162231c0a7368ba8e7bce0580ecf0", + "Nonce": 38, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 119, + "From": "0x7f1652e05388a237a4ff2125c2a5e497ed83ecc4", + "To": "0x72c60bfffef18dca51db32b52b819a951b6ddbed", + "Value": 0, + "Gas": 46957, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x832d821aee6b370c7f7f236d02bdf51301ae3658e21ec85339a7be748d6c4582", + "Nonce": 907, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 120, + "From": "0x0db858b5ea8ce6cb34344d3db780e7bcbc9aa2bf", + "To": "0xfc6ccc11c91577842c4843a335eac4a586ba6ae0", + "Value": 0, + "Gas": 46318, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0xec34e6ba055c320d73ef36362fadf8db7842fc2a056673502d863380e026456b", + "Nonce": 238, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 121, + "From": "0x0e19f9d69c46a9f49389d6a427e04c97097f992c", + "To": "0x72c60bfffef18dca51db32b52b819a951b6ddbed", + "Value": 0, + "Gas": 47017, + "GasPrice": 47558888839, + "Input": "0x" + }, + { + "Hash": "0x35e665990950b0355d79be7290c719aeff7cd092dbd64efc5fec49152bb78927", + "Nonce": 123, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 122, + "From": "0x108613c231792bb14f041719ecbf7b18789926ca", + "To": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", + "Value": 0, + "Gas": 426890, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0x370d7de27634e11a9365ca1acb5738cbdff2bacc85bc0bbe01493c1952201816", + "Nonce": 38, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 123, + "From": "0x4095e294a12a0d8d98fc602fcd3e0fb3b96c477a", + "To": "0x5e809a85aa182a9921edd10a4163745bb3e36284", + "Value": 10150000000000002, + "Gas": 21000, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x446a45102acd665e95de4a498feb9e71a31f843143a687de8878b440878d3a6f", + "Nonce": 224, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 124, + "From": "0xce0135aef6c807f822d5de6ca3ffd6bcc170d941", + "To": "0x58e2cacfa2322acaa56682eeba09a47a028840c8", + "Value": 200000000000000000, + "Gas": 21000, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0xcee22c01572d92df51e6a3b5022f92a0b458ee4a4f339b7f8e8bb3da3e365265", + "Nonce": 271, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 125, + "From": "0xd435aa3217020db4b9fa3a6ddd7edaadee9cadca", + "To": "0xb2692e4d0a5333d20b08182aefc9a2e956a719c2", + "Value": 29372543721031329, + "Gas": 21000, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0xb9e70e0882d81f80e9d4f3dd031081598822f77e23d5f18562520b5b11981eb4", + "Nonce": 10379, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 126, + "From": "0x006f0537ed493f7f84340dc6c417a8381c6b1035", + "To": "0x7e8139f246776bcfa2cc9a77111ed98d3a08560e", + "Value": 11407000000000000, + "Gas": 21000, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x2d33465c8fd4ea2ce1ce4c0a35a0331e5152f8301a06079e1c2dd9d8e537943d", + "Nonce": 2, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 127, + "From": "0xe06d48db6fe0f6fe53cf6a5ac4705afe27c44489", + "To": "0x2501111b3a5bb30608a06b1b8c182e777f7e6c1a", + "Value": 46739280024215673, + "Gas": 21000, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x3991d63319b2e541058ceca5038e755237663cce54979a057354dbd2b97df6b8", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 128, + "From": "0xc318c7f0060447674584ec3c013da9387f6f8f8e", + "To": "0x6507337007e9779cdd49b369108f722cfe5190e5", + "Value": 1000000000000000000, + "Gas": 21000, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0x00c7d3846f5d9d1e6e862bcf837107096dd4ab1a43db63082f203437ee24a0a1", + "Nonce": 66, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 129, + "From": "0x2c7a652f55dc40983e914e0fd638479ace6a1f75", + "To": "0x7ef265e7c167891fe20b1bffd0e5076d8484b264", + "Value": 50000000000000000, + "Gas": 21000, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0xeaec67d5dd5d85f27b21bef83e01cbdf59154fd793ea7a22c297f7c3a722c532", + "Nonce": 18, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 130, + "From": "0xf829fa7069680b8c37a8086b37d4a24697e5003b", + "To": "0x70e967acfcc17c3941e87562161406d41676fd83", + "Value": 4000000000000000, + "Gas": 21000, + "GasPrice": 47562901998, + "Input": "0x" + }, + { + "Hash": "0xa32fa55ad570ee943de6a69681f85809cff9611bb489dc59620c6c9634278860", + "Nonce": 6, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 131, + "From": "0x1a301f7e9c7f4372cb886dafc32c03505ae8a347", + "To": "0xdef1c0ded9bec7f1a1670819833240f027b25eff", + "Value": 5853241671568000, + "Gas": 225269, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0x68498ef50ae339f64f587508686d2070beb59a4fd704824abefbb3b846692bfe", + "Nonce": 36, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 132, + "From": "0xd9026bf9bccf9865c1b7ef3890e88141adc96b04", + "To": "0xdef1c0ded9bec7f1a1670819833240f027b25eff", + "Value": 58663498837720000, + "Gas": 153186, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0xac5f5cbe533cd6d42f4562f08aa306ce0433ab4e6df5ea4356d09eef65efdc78", + "Nonce": 95, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 133, + "From": "0xbf0ecd6003e6fe86254b4e432578e47fbffd0c79", + "To": "0xdef1c0ded9bec7f1a1670819833240f027b25eff", + "Value": 24052034523465200, + "Gas": 156789, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0x29bd93d2ee05bd9e2abfe0b4fd52e5374516e64665b4560966b013495f335bd5", + "Nonce": 46, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 134, + "From": "0x65327701f0fde489341e7825d42ab727ba24a141", + "To": "0xdef1c0ded9bec7f1a1670819833240f027b25eff", + "Value": 14665874709430000, + "Gas": 151857, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0xcd576979151ddf22017c3ed40169c41b08057ee34853e790c78e0503599ffb66", + "Nonce": 27, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 135, + "From": "0xd437ab1447edfe0cd8d3b6427efd7b29216c557d", + "To": "0x5946aeaab44e65eb370ffaa6a7ef2218cff9b47d", + "Value": 0, + "Gas": 76658, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0x2352fddc3824473acdc0cb61256fb56c32db0fd1db41244b42b4ad1bb7d7dadc", + "Nonce": 17332, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 136, + "From": "0xa0d55532fa467db182780b6adaf34817ee99054d", + "To": "0x5db209f7f4cbd7011b486b8d99e5ae616947a138", + "Value": 0, + "Gas": 181540, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0x9ae881cb9e534096347f0a937a16342fb6626885dd385f55f64f461a9913b3cb", + "Nonce": 349, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 137, + "From": "0xeb85679cdf6182f3531e6bd260acaabc84945837", + "To": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + "Value": 0, + "Gas": 39792, + "GasPrice": 47549888842, + "Input": "0x" + }, + { + "Hash": "0x1ef9ed16e2e0b41ab18042a4bdaeaf726a71776687a0c242577146e21c62514c", + "Nonce": 22337, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 138, + "From": "0x42f5e0a60685a75b4a63bb2bb971193fd23f5869", + "To": "0x42f5e0a60685a75b4a63bb2bb971193fd23f5869", + "Value": 0, + "Gas": 400000, + "GasPrice": 47549998839, + "Input": "0x" + }, + { + "Hash": "0x24177294b901a1b673a6df33837e2b0006190bff20f9392c836b8ca46e26d052", + "Nonce": 0, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 139, + "From": "0xba8e558bd0677ac300489420138785cc3a37a223", + "To": "0x13e0a14da2ff4e2aa3c911c485ef56d29cbd7e1c", + "Value": 5866349883772000, + "Gas": 21000, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0xfb04f84490fd405f0150eccda7080425d9196a65d71a46574aa88cebe235f146", + "Nonce": 1, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 140, + "From": "0x31524adb04b2482291a0ffe376ff5c60dc16ab7e", + "To": "0x4908fd52a3fd7344675abf143f3922bb7b26a77c", + "Value": 1975540117349000, + "Gas": 21000, + "GasPrice": 47549888839, + "Input": "0x" + }, + { + "Hash": "0x18ad5408e52be20570b1f4ec929425f3f09d7ea8231e5dda5407defa11916997", + "Nonce": 29403, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 141, + "From": "0x13307b8854a95946b54a904100afd0767a7a577b", + "To": "0x0800394f6e23dd539929c8b77a3d45c96f76aefc", + "Value": 0, + "Gas": 50456, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0x8b21c64aa243aeaaabcc0810a837099c0ba65b33cffa0e7d232191717c094898", + "Nonce": 29404, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 142, + "From": "0x13307b8854a95946b54a904100afd0767a7a577b", + "To": "0x0c572544a4ee47904d54aaa6a970af96b6f00e1b", + "Value": 0, + "Gas": 59302, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0xe6a766bff4149b232e7b86cdb49d21d81d5dee485642f241f1315be86e19adf1", + "Nonce": 29405, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 143, + "From": "0x13307b8854a95946b54a904100afd0767a7a577b", + "To": "0x26c8afbbfe1ebaca03c2bb082e69d0476bffe099", + "Value": 0, + "Gas": 50847, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0xe482f176072f558851718fb8c53e8165d2e5b7f37da8bd38d9d7066e4850d531", + "Nonce": 29406, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 144, + "From": "0x13307b8854a95946b54a904100afd0767a7a577b", + "To": "0x34be5b8c30ee4fde069dc878989686abe9884470", + "Value": 0, + "Gas": 50683, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0x92295ce76ba313185935046487d1a324c5e35ee35e4b3130ccb499b0f31ef57e", + "Nonce": 29407, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 145, + "From": "0x13307b8854a95946b54a904100afd0767a7a577b", + "To": "0x38e382f74dfb84608f3c1f10187f6bef5951de93", + "Value": 0, + "Gas": 50456, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0x26adefddd3ce81f98b531a485703b22111945b95947d45f5ba4b578c595aa0be", + "Nonce": 29408, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 146, + "From": "0x13307b8854a95946b54a904100afd0767a7a577b", + "To": "0x41545f8b9472d758bb669ed8eaeeecd7a9c4ec29", + "Value": 0, + "Gas": 62306, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0x9fc91528d534ce6d97fd06216334f91c4555ccbb39fe1dfcbe3dfaf1ad76caaa", + "Nonce": 29409, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 147, + "From": "0x13307b8854a95946b54a904100afd0767a7a577b", + "To": "0x42baf1f659d765c65ade5bb7e08eb2c680360d9d", + "Value": 0, + "Gas": 74354, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0xe7825e407a5e4bac4ccbfee2650b1c7450fb2e52b14a7763a442123a48ee1ce7", + "Nonce": 29410, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 148, + "From": "0x13307b8854a95946b54a904100afd0767a7a577b", + "To": "0x476c5e26a75bd202a9683ffd34359c0cc15be0ff", + "Value": 0, + "Gas": 52932, + "GasPrice": 49048888839, + "Input": "0x" + }, + { + "Hash": "0x6f58d988f08ab702a26a9956a42d6ad13292f6a806ad457b5446ac8efef565f9", + "Nonce": 1043003, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 149, + "From": "0x077d360f11d220e4d5d831430c81c26c9be7c4a4", + "To": "0xefa63e9b5177fbafb2e587ab9d12fdf37870922a", + "Value": 164375120000000000, + "Gas": 60000, + "GasPrice": 49000000000, + "Input": "0x" + }, + { + "Hash": "0x17c01eaedf2642baa1ca4350378d56fbbc7a7315171d10a2cefb72bba8848ec8", + "Nonce": 1043004, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 150, + "From": "0x077d360f11d220e4d5d831430c81c26c9be7c4a4", + "To": "0x21d688bf078f68ee2f9e6b52817d9e2a8469998f", + "Value": 38413030000000000, + "Gas": 60000, + "GasPrice": 49000000000, + "Input": "0x" + }, + { + "Hash": "0xfe58a80dd77a06efdf25fbb4529ce7c6f4343e200704a88d6e288b832f526d5c", + "Nonce": 1013321, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 151, + "From": "0xa4e5961b58dbe487639929643dcb1dc3848daf5e", + "To": "0x839a35b9468007d8cb3a5bc9af31ead7242b916e", + "Value": 5424350000000000, + "Gas": 22000, + "GasPrice": 48000000000, + "Input": "0x" + }, + { + "Hash": "0x2e0ac6c2af639e879774284835b815b051de19c36cfaa3153e558e88bcf5db95", + "Nonce": 19, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 152, + "From": "0xbde1f1dac1e001a272cb083962179d8a152c551b", + "To": "0x1111111254eeb25477b68fb85ed929f73a960582", + "Value": 0, + "Gas": 275732, + "GasPrice": 47598888839, + "Input": "0x" + }, + { + "Hash": "0xb8a3727333b506b64769aed2e9b0e7c29637a8c333744e8f159abae458e33d3c", + "Nonce": 18945, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 153, + "From": "0x22a82147a80747cfb1562e0f72f6be39f18b5f76", + "To": "0x40864568f679c10ac9e72211500096a5130770fa", + "Value": 0, + "Gas": 11000000, + "GasPrice": 47648888839, + "Input": "0x" + }, + { + "Hash": "0x076b0ef1e4482f2b85f7f6c36152686281041191099bb1597e692ddfe6477b05", + "Nonce": 7, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 154, + "From": "0x10ee730e8c4f19dce08d4548b3de8045e8b87e9f", + "To": "0xdef1c0ded9bec7f1a1670819833240f027b25eff", + "Value": 0, + "Gas": 161459, + "GasPrice": 47628888839, + "Input": "0x" + }, + { + "Hash": "0xef85516883c377de4a7671d372b0e5d7721af7a9bb6e42ba97a0c88d3db58720", + "Nonce": 224600, + "BlockHash": "0x5f30ff0388dff58fd28c666b6eecdd7642c9b1adfbd943caeb2ae7a6d8ce9eba", + "BlockNumber": 19330473, + "TransactionIndex": 155, + "From": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97", + "To": "0x388c818ca8b9251b393131c08a736a67ccb19297", + "Value": 81116746339497983, + "Gas": 22111, + "GasPrice": 47548888839, + "Input": "0x" + } + ] +} diff --git a/zetaclient/testutils/stub/core_bridge.go b/zetaclient/testutils/stub/core_bridge.go index 1bf06be84b..d9172636c3 100644 --- a/zetaclient/testutils/stub/core_bridge.go +++ b/zetaclient/testutils/stub/core_bridge.go @@ -1,6 +1,7 @@ package stub import ( + "errors" "math/big" "cosmossdk.io/math" @@ -14,118 +15,189 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/testutils" ) -var _ interfaces.ZetaCoreBridger = &ZetaCoreBridge{} +const ErrMsgPaused = "zeta core bridge is paused" -type ZetaCoreBridge struct { +var _ interfaces.ZetaCoreBridger = &MockZetaCoreBridge{} + +type MockZetaCoreBridge struct { + paused bool zetaChain common.Chain } -func (z ZetaCoreBridge) PostVoteInbound(_, _ uint64, _ *cctxtypes.MsgVoteOnObservedInboundTx) (string, string, error) { +func NewMockZetaCoreBridge() *MockZetaCoreBridge { + zetaChain, err := common.ZetaChainFromChainID("zetachain_7000-1") + if err != nil { + panic(err) + } + return &MockZetaCoreBridge{ + paused: false, + zetaChain: zetaChain, + } +} + +func (z *MockZetaCoreBridge) PostVoteInbound(_, _ uint64, _ *cctxtypes.MsgVoteOnObservedInboundTx) (string, string, error) { + if z.paused { + return "", "", errors.New(ErrMsgPaused) + } return "", "", nil } -func (z ZetaCoreBridge) PostVoteOutbound(_ string, _ string, _ uint64, _ uint64, _ *big.Int, _ uint64, _ *big.Int, _ common.ReceiveStatus, _ common.Chain, _ uint64, _ common.CoinType) (string, string, error) { +func (z *MockZetaCoreBridge) PostVoteOutbound(_ string, _ string, _ uint64, _ uint64, _ *big.Int, _ uint64, _ *big.Int, _ common.ReceiveStatus, _ common.Chain, _ uint64, _ common.CoinType) (string, string, error) { + if z.paused { + return "", "", errors.New(ErrMsgPaused) + } return "", "", nil } -func (z ZetaCoreBridge) PostGasPrice(_ common.Chain, _ uint64, _ string, _ uint64) (string, error) { +func (z *MockZetaCoreBridge) PostGasPrice(_ common.Chain, _ uint64, _ string, _ uint64) (string, error) { + if z.paused { + return "", errors.New(ErrMsgPaused) + } return "", nil } -func (z ZetaCoreBridge) PostAddBlockHeader(_ int64, _ []byte, _ int64, _ common.HeaderData) (string, error) { +func (z *MockZetaCoreBridge) PostAddBlockHeader(_ int64, _ []byte, _ int64, _ common.HeaderData) (string, error) { + if z.paused { + return "", errors.New(ErrMsgPaused) + } return "", nil } -func (z ZetaCoreBridge) GetBlockHeaderStateByChain(_ int64) (observerTypes.QueryGetBlockHeaderStateResponse, error) { +func (z *MockZetaCoreBridge) GetBlockHeaderStateByChain(_ int64) (observerTypes.QueryGetBlockHeaderStateResponse, error) { + if z.paused { + return observerTypes.QueryGetBlockHeaderStateResponse{}, errors.New(ErrMsgPaused) + } return observerTypes.QueryGetBlockHeaderStateResponse{}, nil } -func (z ZetaCoreBridge) PostBlameData(_ *blame.Blame, _ int64, _ string) (string, error) { +func (z *MockZetaCoreBridge) PostBlameData(_ *blame.Blame, _ int64, _ string) (string, error) { + if z.paused { + return "", errors.New(ErrMsgPaused) + } return "", nil } -func (z ZetaCoreBridge) AddTxHashToOutTxTracker(_ int64, _ uint64, _ string, _ *common.Proof, _ string, _ int64) (string, error) { +func (z *MockZetaCoreBridge) AddTxHashToOutTxTracker(_ int64, _ uint64, _ string, _ *common.Proof, _ string, _ int64) (string, error) { + if z.paused { + return "", errors.New(ErrMsgPaused) + } return "", nil } -func (z ZetaCoreBridge) GetKeys() *keys.Keys { +func (z *MockZetaCoreBridge) GetKeys() *keys.Keys { return &keys.Keys{} } -func (z ZetaCoreBridge) GetBlockHeight() (int64, error) { +func (z *MockZetaCoreBridge) GetBlockHeight() (int64, error) { + if z.paused { + return 0, errors.New(ErrMsgPaused) + } return 0, nil } -func (z ZetaCoreBridge) GetZetaBlockHeight() (int64, error) { +func (z *MockZetaCoreBridge) GetZetaBlockHeight() (int64, error) { + if z.paused { + return 0, errors.New(ErrMsgPaused) + } return 0, nil } -func (z ZetaCoreBridge) GetLastBlockHeightByChain(_ common.Chain) (*cctxtypes.LastBlockHeight, error) { +func (z *MockZetaCoreBridge) GetLastBlockHeightByChain(_ common.Chain) (*cctxtypes.LastBlockHeight, error) { + if z.paused { + return nil, errors.New(ErrMsgPaused) + } return &cctxtypes.LastBlockHeight{}, nil } -func (z ZetaCoreBridge) ListPendingCctx(_ int64) ([]*cctxtypes.CrossChainTx, uint64, error) { +func (z *MockZetaCoreBridge) ListPendingCctx(_ int64) ([]*cctxtypes.CrossChainTx, uint64, error) { + if z.paused { + return nil, 0, errors.New(ErrMsgPaused) + } return []*cctxtypes.CrossChainTx{}, 0, nil } -func (z ZetaCoreBridge) GetPendingNoncesByChain(_ int64) (observerTypes.PendingNonces, error) { +func (z *MockZetaCoreBridge) GetPendingNoncesByChain(_ int64) (observerTypes.PendingNonces, error) { + if z.paused { + return observerTypes.PendingNonces{}, errors.New(ErrMsgPaused) + } return observerTypes.PendingNonces{}, nil } -func (z ZetaCoreBridge) GetCctxByNonce(_ int64, _ uint64) (*cctxtypes.CrossChainTx, error) { +func (z *MockZetaCoreBridge) GetCctxByNonce(_ int64, _ uint64) (*cctxtypes.CrossChainTx, error) { + if z.paused { + return nil, errors.New(ErrMsgPaused) + } return &cctxtypes.CrossChainTx{}, nil } -func (z ZetaCoreBridge) GetOutTxTracker(_ common.Chain, _ uint64) (*cctxtypes.OutTxTracker, error) { +func (z *MockZetaCoreBridge) GetOutTxTracker(_ common.Chain, _ uint64) (*cctxtypes.OutTxTracker, error) { + if z.paused { + return nil, errors.New(ErrMsgPaused) + } return &cctxtypes.OutTxTracker{}, nil } -func (z ZetaCoreBridge) GetAllOutTxTrackerByChain(_ int64, _ interfaces.Order) ([]cctxtypes.OutTxTracker, error) { +func (z *MockZetaCoreBridge) GetAllOutTxTrackerByChain(_ int64, _ interfaces.Order) ([]cctxtypes.OutTxTracker, error) { + if z.paused { + return nil, errors.New(ErrMsgPaused) + } return []cctxtypes.OutTxTracker{}, nil } -func (z ZetaCoreBridge) GetCrosschainFlags() (observerTypes.CrosschainFlags, error) { +func (z *MockZetaCoreBridge) GetCrosschainFlags() (observerTypes.CrosschainFlags, error) { + if z.paused { + return observerTypes.CrosschainFlags{}, errors.New(ErrMsgPaused) + } return observerTypes.CrosschainFlags{}, nil } -func (z ZetaCoreBridge) GetObserverList() ([]string, error) { +func (z *MockZetaCoreBridge) GetObserverList() ([]string, error) { + if z.paused { + return nil, errors.New(ErrMsgPaused) + } return []string{}, nil } -func (z ZetaCoreBridge) GetKeyGen() (*observerTypes.Keygen, error) { +func (z *MockZetaCoreBridge) GetKeyGen() (*observerTypes.Keygen, error) { + if z.paused { + return nil, errors.New(ErrMsgPaused) + } return &observerTypes.Keygen{}, nil } -func (z ZetaCoreBridge) GetBtcTssAddress(_ int64) (string, error) { +func (z *MockZetaCoreBridge) GetBtcTssAddress(_ int64) (string, error) { + if z.paused { + return "", errors.New(ErrMsgPaused) + } return testutils.TSSAddressBTCMainnet, nil } -func (z ZetaCoreBridge) GetInboundTrackersForChain(_ int64) ([]cctxtypes.InTxTracker, error) { +func (z *MockZetaCoreBridge) GetInboundTrackersForChain(_ int64) ([]cctxtypes.InTxTracker, error) { + if z.paused { + return nil, errors.New(ErrMsgPaused) + } return []cctxtypes.InTxTracker{}, nil } -func (z ZetaCoreBridge) GetLogger() *zerolog.Logger { +func (z *MockZetaCoreBridge) GetLogger() *zerolog.Logger { return nil } -func (z ZetaCoreBridge) ZetaChain() common.Chain { +func (z *MockZetaCoreBridge) ZetaChain() common.Chain { return z.zetaChain } -func (z ZetaCoreBridge) Pause() { -} - -func (z ZetaCoreBridge) Unpause() { +func (z *MockZetaCoreBridge) Pause() { + z.paused = true } -func (z ZetaCoreBridge) GetZetaHotKeyBalance() (math.Int, error) { - return math.NewInt(0), nil +func (z *MockZetaCoreBridge) Unpause() { + z.paused = false } -func NewZetaCoreBridge() *ZetaCoreBridge { - zetaChain, err := common.ZetaChainFromChainID("zetachain_7000-1") - if err != nil { - panic(err) +func (z *MockZetaCoreBridge) GetZetaHotKeyBalance() (math.Int, error) { + if z.paused { + return math.NewInt(0), errors.New(ErrMsgPaused) } - return &ZetaCoreBridge{zetaChain: zetaChain} + return math.NewInt(0), nil } diff --git a/zetaclient/testutils/stub/evm_json_rpc.go b/zetaclient/testutils/stub/evm_json_rpc.go new file mode 100644 index 0000000000..cd80966660 --- /dev/null +++ b/zetaclient/testutils/stub/evm_json_rpc.go @@ -0,0 +1,75 @@ +package stub + +import ( + "errors" + + "github.com/onrik/ethrpc" + "github.com/zeta-chain/zetacore/zetaclient/interfaces" +) + +// EvmClient interface +var _ interfaces.EVMJSONRPCClient = &MockJSONRPCClient{} + +// MockJSONRPCClient is a mock implementation of the EVMJSONRPCClient interface +type MockJSONRPCClient struct { + Blocks []*ethrpc.Block + Transactions []*ethrpc.Transaction +} + +// NewMockJSONRPCClient creates a new mock JSON RPC client +func NewMockJSONRPCClient() *MockJSONRPCClient { + client := &MockJSONRPCClient{} + return client.Reset() +} + +// EthGetBlockByNumber returns a pre-loaded block or nil +func (e *MockJSONRPCClient) EthGetBlockByNumber(_ int, _ bool) (*ethrpc.Block, error) { + // pop a block from the list + if len(e.Blocks) > 0 { + block := e.Blocks[len(e.Blocks)-1] + e.Blocks = e.Blocks[:len(e.Blocks)-1] + return block, nil + } + return nil, errors.New("no block found") +} + +// EthGetTransactionByHash returns a pre-loaded transaction or nil +func (e *MockJSONRPCClient) EthGetTransactionByHash(_ string) (*ethrpc.Transaction, error) { + // pop a transaction from the list + if len(e.Transactions) > 0 { + tx := e.Transactions[len(e.Transactions)-1] + e.Transactions = e.Transactions[:len(e.Transactions)-1] + return tx, nil + } + return nil, errors.New("no transaction found") +} + +// Reset clears the mock data +func (e *MockJSONRPCClient) Reset() *MockJSONRPCClient { + e.Blocks = []*ethrpc.Block{} + e.Transactions = []*ethrpc.Transaction{} + return e +} + +// ---------------------------------------------------------------------------- +// Feed data to the mock JSON RPC client for testing +// ---------------------------------------------------------------------------- +func (e *MockJSONRPCClient) WithBlock(block *ethrpc.Block) *MockJSONRPCClient { + e.Blocks = append(e.Blocks, block) + return e +} + +func (e *MockJSONRPCClient) WithBlocks(blocks []*ethrpc.Block) *MockJSONRPCClient { + e.Blocks = append(e.Blocks, blocks...) + return e +} + +func (e *MockJSONRPCClient) WithTransaction(tx *ethrpc.Transaction) *MockJSONRPCClient { + e.Transactions = append(e.Transactions, tx) + return e +} + +func (e *MockJSONRPCClient) WithTransactions(txs []*ethrpc.Transaction) *MockJSONRPCClient { + e.Transactions = append(e.Transactions, txs...) + return e +} diff --git a/zetaclient/testutils/stub/evm_rpc.go b/zetaclient/testutils/stub/evm_rpc.go index 05f14fc59b..dd1fd5fedf 100644 --- a/zetaclient/testutils/stub/evm_rpc.go +++ b/zetaclient/testutils/stub/evm_rpc.go @@ -1,6 +1,7 @@ package stub import ( + "errors" "math/big" "github.com/ethereum/go-ethereum" @@ -26,73 +27,103 @@ func (s subscription) Err() <-chan error { } // EvmClient interface -var _ interfaces.EVMRPCClient = EvmClient{} +var _ interfaces.EVMRPCClient = &MockEvmClient{} -type EvmClient struct { +type MockEvmClient struct { + Receipts []*ethtypes.Receipt } -func (e EvmClient) SubscribeFilterLogs(_ context.Context, _ ethereum.FilterQuery, _ chan<- ethtypes.Log) (ethereum.Subscription, error) { +func NewMockEvmClient() *MockEvmClient { + client := &MockEvmClient{} + return client.Reset() +} + +func (e *MockEvmClient) SubscribeFilterLogs(_ context.Context, _ ethereum.FilterQuery, _ chan<- ethtypes.Log) (ethereum.Subscription, error) { return subscription{}, nil } -func (e EvmClient) CodeAt(_ context.Context, _ ethcommon.Address, _ *big.Int) ([]byte, error) { +func (e *MockEvmClient) CodeAt(_ context.Context, _ ethcommon.Address, _ *big.Int) ([]byte, error) { return []byte{}, nil } -func (e EvmClient) CallContract(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) { +func (e *MockEvmClient) CallContract(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) { return []byte{}, nil } -func (e EvmClient) HeaderByNumber(_ context.Context, _ *big.Int) (*ethtypes.Header, error) { +func (e *MockEvmClient) HeaderByNumber(_ context.Context, _ *big.Int) (*ethtypes.Header, error) { return ðtypes.Header{}, nil } -func (e EvmClient) PendingCodeAt(_ context.Context, _ ethcommon.Address) ([]byte, error) { +func (e *MockEvmClient) PendingCodeAt(_ context.Context, _ ethcommon.Address) ([]byte, error) { return []byte{}, nil } -func (e EvmClient) PendingNonceAt(_ context.Context, _ ethcommon.Address) (uint64, error) { +func (e *MockEvmClient) PendingNonceAt(_ context.Context, _ ethcommon.Address) (uint64, error) { return 0, nil } -func (e EvmClient) SuggestGasPrice(_ context.Context) (*big.Int, error) { +func (e *MockEvmClient) SuggestGasPrice(_ context.Context) (*big.Int, error) { return big.NewInt(0), nil } -func (e EvmClient) SuggestGasTipCap(_ context.Context) (*big.Int, error) { +func (e *MockEvmClient) SuggestGasTipCap(_ context.Context) (*big.Int, error) { return big.NewInt(0), nil } -func (e EvmClient) EstimateGas(_ context.Context, _ ethereum.CallMsg) (gas uint64, err error) { +func (e *MockEvmClient) EstimateGas(_ context.Context, _ ethereum.CallMsg) (gas uint64, err error) { gas = 0 err = nil return } -func (e EvmClient) SendTransaction(_ context.Context, _ *ethtypes.Transaction) error { +func (e *MockEvmClient) SendTransaction(_ context.Context, _ *ethtypes.Transaction) error { return nil } -func (e EvmClient) FilterLogs(_ context.Context, _ ethereum.FilterQuery) ([]ethtypes.Log, error) { +func (e *MockEvmClient) FilterLogs(_ context.Context, _ ethereum.FilterQuery) ([]ethtypes.Log, error) { return []ethtypes.Log{}, nil } -func (e EvmClient) BlockNumber(_ context.Context) (uint64, error) { +func (e *MockEvmClient) BlockNumber(_ context.Context) (uint64, error) { return 0, nil } -func (e EvmClient) BlockByNumber(_ context.Context, _ *big.Int) (*ethtypes.Block, error) { +func (e *MockEvmClient) BlockByNumber(_ context.Context, _ *big.Int) (*ethtypes.Block, error) { return ðtypes.Block{}, nil } -func (e EvmClient) TransactionByHash(_ context.Context, _ ethcommon.Hash) (tx *ethtypes.Transaction, isPending bool, err error) { +func (e *MockEvmClient) TransactionByHash(_ context.Context, _ ethcommon.Hash) (tx *ethtypes.Transaction, isPending bool, err error) { return ðtypes.Transaction{}, false, nil } -func (e EvmClient) TransactionReceipt(_ context.Context, _ ethcommon.Hash) (*ethtypes.Receipt, error) { - return ðtypes.Receipt{}, nil +func (e *MockEvmClient) TransactionReceipt(_ context.Context, _ ethcommon.Hash) (*ethtypes.Receipt, error) { + // pop a receipt from the list + if len(e.Receipts) > 0 { + receipt := e.Receipts[len(e.Receipts)-1] + e.Receipts = e.Receipts[:len(e.Receipts)-1] + return receipt, nil + } + return nil, errors.New("no receipt found") } -func (e EvmClient) TransactionSender(_ context.Context, _ *ethtypes.Transaction, _ ethcommon.Hash, _ uint) (ethcommon.Address, error) { +func (e *MockEvmClient) TransactionSender(_ context.Context, _ *ethtypes.Transaction, _ ethcommon.Hash, _ uint) (ethcommon.Address, error) { return ethcommon.Address{}, nil } + +func (e *MockEvmClient) Reset() *MockEvmClient { + e.Receipts = []*ethtypes.Receipt{} + return e +} + +// ---------------------------------------------------------------------------- +// Feed data to the mock evm client for testing +// ---------------------------------------------------------------------------- +func (e *MockEvmClient) WithReceipt(receipt *ethtypes.Receipt) *MockEvmClient { + e.Receipts = append(e.Receipts, receipt) + return e +} + +func (e *MockEvmClient) WithReceipts(receipts []*ethtypes.Receipt) *MockEvmClient { + e.Receipts = append(e.Receipts, receipts...) + return e +}