From 9672baef2779d420cd16aeca4de7994b5f0927f6 Mon Sep 17 00:00:00 2001 From: Ayman Bouchareb Date: Sat, 14 Oct 2023 10:09:04 +0100 Subject: [PATCH] Fix Antithesis NullPointerException in Evm (#6191) * Copy geth behavior * Add nullable to data returned from createAccessList because it is creating empty data object that shhould not be there --------- Co-authored-by: smartprogrammer --- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 12 ++++++++++++ .../Modules/Eth/EthRpcModule.TransactionExecutor.cs | 13 +++++++++---- .../Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs | 2 +- .../Modules/Eth/EthRpcModuleProxy.cs | 2 +- .../Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs | 2 +- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index 30aba351ebd..8773bf7e244 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -137,6 +137,18 @@ public async Task Eth_call_ok() Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); } + [Test] + public async Task Eth_call_create_tx_with_empty_data() + { + using Context ctx = await Context.Create(); + TransactionForRpc transaction = new(Keccak.Zero, 1L, 1, new Transaction()); + transaction.From = TestItem.AddressA; + + string serialized = + await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); + serialized.Should().BeEquivalentTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32000,\"message\":\"Contract creation without any data provided.\"},\"id\":67}"); + } + [Test] public async Task Eth_call_missing_state_after_fast_sync() { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs index 101ce8e5cb8..b571e34068d 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs @@ -53,6 +53,11 @@ public ResultWrapper ExecuteTx( using CancellationTokenSource cancellationTokenSource = new(_rpcConfig.Timeout); Transaction tx = transactionCall.ToTransaction(_blockchainBridge.GetChainId()); + if (tx.IsContractCreation && tx.DataLength == 0) + { + return ResultWrapper.Fail("Contract creation without any data provided.", + ErrorCodes.InvalidInput); + } return ExecuteTx(header.Clone(), tx, cancellationTokenSource.Token); } @@ -106,7 +111,7 @@ public EstimateGasTxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder bl } } - private class CreateAccessListTxExecutor : TxExecutor + private class CreateAccessListTxExecutor : TxExecutor { private readonly bool _optimize; @@ -116,18 +121,18 @@ public CreateAccessListTxExecutor(IBlockchainBridge blockchainBridge, IBlockFind _optimize = optimize; } - protected override ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, CancellationToken token) + protected override ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, CancellationToken token) { BlockchainBridge.CallOutput result = _blockchainBridge.CreateAccessList(header, tx, token, _optimize); if (result.Error is null) { - return ResultWrapper.Success(new(GetResultAccessList(tx, result), GetResultGas(tx, result))); + return ResultWrapper.Success(new(GetResultAccessList(tx, result), GetResultGas(tx, result))); } return result.InputError ? GetInputError(result) - : ResultWrapper.Fail(result.Error, ErrorCodes.ExecutionError, new AccessListForRpc(GetResultAccessList(tx, result), GetResultGas(tx, result))); + : ResultWrapper.Fail(result.Error, ErrorCodes.ExecutionError, new AccessListForRpc(GetResultAccessList(tx, result), GetResultGas(tx, result))); } private static IEnumerable GetResultAccessList(Transaction tx, BlockchainBridge.CallOutput result) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index 27b56d954b8..89a7561f240 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -342,7 +342,7 @@ public ResultWrapper eth_call(TransactionForRpc transactionCall, BlockPa new EstimateGasTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig) .ExecuteTx(transactionCall, blockParameter); - public ResultWrapper eth_createAccessList(TransactionForRpc transactionCall, BlockParameter? blockParameter = null, bool optimize = true) => + public ResultWrapper eth_createAccessList(TransactionForRpc transactionCall, BlockParameter? blockParameter = null, bool optimize = true) => new CreateAccessListTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig, optimize) .ExecuteTx(transactionCall, blockParameter); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModuleProxy.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModuleProxy.cs index c4bfa1fcbc8..5a3b81023ed 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModuleProxy.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModuleProxy.cs @@ -163,7 +163,7 @@ public ResultWrapper eth_call(TransactionForRpc transactionCall, BlockPa throw new NotSupportedException(); } - public ResultWrapper eth_createAccessList(TransactionForRpc transactionCall, BlockParameter? blockParameter = null, bool optimize = true) + public ResultWrapper eth_createAccessList(TransactionForRpc transactionCall, BlockParameter? blockParameter = null, bool optimize = true) { throw new NotSupportedException(); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs index 79a7ba6f8a0..239965bbace 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs @@ -150,7 +150,7 @@ public interface IEthRpcModule : IRpcModule EdgeCaseHint = "If your transaction has code executed, then you can generate transaction access list with eth_createAccessList. If you send it with your transaction then it will lower your gas cost on Ethereum", IsSharable = false, ExampleResponse = "{\"accessList\":[{\"address\":\"0xfffffffffffffffffffffffffffffffffffffffe\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\"]},{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0xf71b\"}")] - ResultWrapper eth_createAccessList( + ResultWrapper eth_createAccessList( [JsonRpcParameter(Description = "Transaction's details", ExampleValue = "[\"{\"type\":\"0x1\"]")] TransactionForRpc transactionCall, [JsonRpcParameter(Description = "(optional)")]