diff --git a/e2e-polybft/e2e/jsonrpc_test.go b/e2e-polybft/e2e/jsonrpc_test.go index 4ece515fce..6735904dec 100644 --- a/e2e-polybft/e2e/jsonrpc_test.go +++ b/e2e-polybft/e2e/jsonrpc_test.go @@ -13,6 +13,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" "github.com/0xPolygon/polygon-edge/helper/hex" + "github.com/0xPolygon/polygon-edge/state" "github.com/0xPolygon/polygon-edge/types" ) @@ -126,6 +127,40 @@ func TestE2E_JsonRPC(t *testing.T) { require.Equal(t, uint64(0x56a3), resp) }) + t.Run("eth_estimateGas by zero-balance account - simple value transfer", func(t *testing.T) { + acctZeroBalance, err := wallet.GenerateKey() + require.NoError(t, err) + + fundedAccountAddress := acct.Address() + nonFundedAccountAddress := acctZeroBalance.Address() + + estimateGasFn := func(value *big.Int) { + resp, err := client.EstimateGas(ðgo.CallMsg{ + From: nonFundedAccountAddress, + To: &fundedAccountAddress, + Value: value, + }) + + require.NoError(t, err) + require.Equal(t, state.TxGas, resp) + } + + estimateGasFn(ethgo.Gwei(1)) + + // transfer some funds to zero balance account + valueTransferTxn := cluster.SendTxn(t, acct, ðgo.Transaction{ + From: fundedAccountAddress, + To: &nonFundedAccountAddress, + Value: ethgo.Gwei(10), + }) + + require.NoError(t, valueTransferTxn.Wait()) + require.True(t, valueTransferTxn.Succeed()) + + // now call estimate gas again for the now funded account + estimateGasFn(ethgo.Gwei(1)) + }) + t.Run("eth_getBalance", func(t *testing.T) { key1, err := wallet.GenerateKey() require.NoError(t, err) diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index c035683722..455d5d94ba 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -553,7 +553,7 @@ func (e *Eth) EstimateGas(arg *txnArgs, rawNum *BlockNumber) (interface{}, error forksInTime := e.store.GetForksInTime(header.Number) - if transaction.IsValueTransfer() || transaction.IsContractCreation() { + if transaction.IsValueTransfer() { // if it is a simple value transfer or a contract creation, // we already know what is the transaction gas cost, no need to apply transaction gasCost, err := state.TransactionGasCost(transaction, forksInTime.Homestead, forksInTime.Istanbul) @@ -569,13 +569,20 @@ func (e *Eth) EstimateGas(arg *txnArgs, rawNum *BlockNumber) (interface{}, error return nil, err } + var standardGas uint64 + if transaction.IsContractCreation() && forksInTime.Homestead { + standardGas = state.TxGasContractCreation + } else { + standardGas = state.TxGas + } + var ( - lowEnd = state.TxGas + lowEnd = standardGas highEnd uint64 ) // If the gas limit was passed in, use it as a ceiling - if transaction.Gas != 0 && transaction.Gas >= lowEnd { + if transaction.Gas != 0 && transaction.Gas >= standardGas { highEnd = transaction.Gas } else { // If not, use the referenced block number diff --git a/types/transaction.go b/types/transaction.go index 53f8380ac8..87dbea350a 100644 --- a/types/transaction.go +++ b/types/transaction.go @@ -77,7 +77,7 @@ func (t *Transaction) IsContractCreation() bool { // IsValueTransfer checks if tx is a value transfer func (t *Transaction) IsValueTransfer() bool { return t.Value != nil && - t.Value.Sign() != 0 && + t.Value.Sign() > 0 && len(t.Input) == 0 && !t.IsContractCreation() }