package proxy_test import ( "io" "math/big" "net/http" "net/http/httptest" "github.com/brianvoe/gofakeit/v6" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/lmittmann/w3/module/eth" . "github.com/stretchr/testify/assert" "github.com/synapsecns/sanguine/ethergo/chain/client" "github.com/synapsecns/sanguine/services/omnirpc/proxy" ) // checkRequest is a helper method for checking requests. // TODO: checkReq can be replaced w/ a confirmable call, we should do this once we're complete. func (p *ProxySuite) checkRequest(makeReq func(client client.EVMClient), checkReq func(body []byte)) { doneChan := make(chan bool) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) Nil(p.T(), err) checkReq(body) go func() { doneChan <- true }() })) defer server.Close() evmClient, err := client.NewClientFromChainID(p.GetTestContext(), server.URL, big.NewInt(1)) Nil(p.T(), err) makeReq(evmClient) <-doneChan } // Test parsing. // //nolint:maintidx func (p *ProxySuite) TestParseRPCPayload() { /* CHECK BLOCKS */ // check latest block, should not be confirmable since // rpcs might be on different latest heights p.checkRequest(func(client client.EVMClient) { _, _ = client.BlockByNumber(p.GetTestContext(), nil) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) // check non-latest block, should be confirmable p.checkRequest(func(client client.EVMClient) { _, _ = client.BlockByNumber(p.GetTestContext(), new(big.Int).SetUint64(gofakeit.Uint64())) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) /* CHECK HEADERS */ // do the same thing, but check headers this time p.checkRequest(func(client client.EVMClient) { _, _ = client.HeaderByNumber(p.GetTestContext(), nil) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) // check non-latest block, should be confirmable p.checkRequest(func(client client.EVMClient) { _, _ = client.HeaderByNumber(p.GetTestContext(), new(big.Int).SetUint64(gofakeit.Uint64())) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) // eth_blockNumber should not be confirmable, can differ based on rpc p.checkRequest(func(client client.EVMClient) { _, _ = client.BlockNumber(p.GetTestContext()) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) /* CHECK Transaction Methods */ p.checkRequest(func(client client.EVMClient) { _, _, _ = client.TransactionByHash(p.GetTestContext(), common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64()))) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.TransactionCount(p.GetTestContext(), common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64()))) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.PendingTransactionCount(p.GetTestContext()) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.TransactionInBlock(p.GetTestContext(), common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64())), 1) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.TransactionReceipt(p.GetTestContext(), common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64()))) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) /* Sync Methods */ p.checkRequest(func(client client.EVMClient) { _, _ = client.SyncProgress(p.GetTestContext()) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.NetworkID(p.GetTestContext()) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) /* Accessor Methods */ // latest block, should not be confirmable p.checkRequest(func(client client.EVMClient) { _, _ = client.BalanceAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64())), nil) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) // pending p.checkRequest(func(client client.EVMClient) { _, _ = client.PendingBalanceAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64()))) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) // non-latest block p.checkRequest(func(client client.EVMClient) { _, _ = client.BalanceAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64())), new(big.Int).SetUint64(gofakeit.Uint64())) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) // latest block, should not be confirmable p.checkRequest(func(client client.EVMClient) { _, _ = client.StorageAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64())), common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64())), nil) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.PendingStorageAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64())), common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64()))) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) // non-latest block p.checkRequest(func(client client.EVMClient) { _, _ = client.StorageAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64())), common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64())), new(big.Int).SetUint64(gofakeit.Uint64())) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.CodeAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64())), nil) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.PendingCodeAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64()))) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) // non-latest block p.checkRequest(func(client client.EVMClient) { _, _ = client.CodeAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64())), new(big.Int).SetUint64(gofakeit.Uint64())) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) // storage: p.checkRequest(func(client client.EVMClient) { _, _ = client.NonceAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64())), nil) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.PendingNonceAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64()))) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) // non-latest block p.checkRequest(func(client client.EVMClient) { _, _ = client.NonceAt(p.GetTestContext(), common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64())), new(big.Int).SetUint64(gofakeit.Uint64())) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) /* Filter Logs */ // this one's a bit more complicated. It should only return true if fromblock is set and toblock is not set if blockhash is not set p.checkRequest(func(client client.EVMClient) { _, _ = client.FilterLogs(p.GetTestContext(), ethereum.FilterQuery{ FromBlock: nil, ToBlock: nil, Addresses: []common.Address{common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64()))}, Topics: [][]common.Hash{{common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64()))}}, }) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) // set just to block p.checkRequest(func(client client.EVMClient) { _, _ = client.FilterLogs(p.GetTestContext(), ethereum.FilterQuery{ FromBlock: nil, ToBlock: big.NewInt(1), Addresses: []common.Address{common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64()))}, Topics: [][]common.Hash{{common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64()))}}, }) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) // set only block hash p.checkRequest(func(client client.EVMClient) { bhash := common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64())) _, _ = client.FilterLogs(p.GetTestContext(), ethereum.FilterQuery{ BlockHash: &bhash, Addresses: []common.Address{common.BigToAddress(new(big.Int).SetUint64(gofakeit.Uint64()))}, Topics: [][]common.Hash{{common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64()))}}, }) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) /* Call Contract */ p.checkRequest(func(client client.EVMClient) { _, _ = client.CallContract(p.GetTestContext(), ethereum.CallMsg{}, nil) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.CallContract(p.GetTestContext(), ethereum.CallMsg{}, big.NewInt(1)) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.PendingCallContract(p.GetTestContext(), ethereum.CallMsg{}) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) /* Gas Pricing */ p.checkRequest(func(client client.EVMClient) { _, _ = client.SuggestGasPrice(p.GetTestContext()) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.SuggestGasTipCap(p.GetTestContext()) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) p.checkRequest(func(client client.EVMClient) { _, _ = client.EstimateGas(p.GetTestContext(), ethereum.CallMsg{}) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) // try a confirmable batch p.checkRequest(func(client client.EVMClient) { _ = client.BatchContext(p.GetTestContext(), eth.ChainID().Returns(nil)) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) True(p.T(), confirmable) }) // try a non-confirmable batch // try a confirmable batch p.checkRequest(func(client client.EVMClient) { _ = client.BatchContext(p.GetTestContext(), eth.ChainID().Returns(nil), eth.BlockNumber().Returns(nil)) }, func(body []byte) { confirmable, err := proxy.IsConfirmable(body) Nil(p.T(), err) False(p.T(), confirmable) }) }