Skip to content

Commit

Permalink
Fix/unspent gas 7623 master (#8017)
Browse files Browse the repository at this point in the history
Co-authored-by: Tanishq Jasoria <[email protected]>
  • Loading branch information
Marchhill and tanishqjasoria authored Jan 7, 2025
1 parent 480f5f6 commit 4c6f6e8
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using Grpc.Core;
using Nethermind.Core;
using Nethermind.Core.Extensions;
using Nethermind.Core.Specs;
using Nethermind.Core.Test.Builders;
using Nethermind.Crypto;
using Nethermind.Db;
using Nethermind.Evm.Tracing;
using Nethermind.Evm.TransactionProcessing;
using Nethermind.Facade;
using Nethermind.Int256;
using Nethermind.Logging;
using Nethermind.Specs;
using Nethermind.Specs.Forks;
using Nethermind.State;
using Nethermind.Trie.Pruning;
using NUnit.Framework;

namespace Nethermind.Evm.Test;

public class TransactionProcessorEip7623Tests
{
private ISpecProvider _specProvider;
private IEthereumEcdsa _ethereumEcdsa;
private TransactionProcessor _transactionProcessor;
private IWorldState _stateProvider;

[SetUp]
public void Setup()
{
MemDb stateDb = new();
_specProvider = new TestSpecProvider(Prague.Instance);
TrieStore trieStore = new(stateDb, LimboLogs.Instance);
_stateProvider = new WorldState(trieStore, new MemDb(), LimboLogs.Instance);
CodeInfoRepository codeInfoRepository = new();
VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, codeInfoRepository, LimboLogs.Instance);
_transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance);
_ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId);
}

[TestCase(21006, true, TestName = "GasLimit=IntrinsicGas")]
[TestCase(21010, false, TestName = "GasLimit=FloorGas")]

public void transaction_validation_intrinsic_below_floor(long gasLimit, bool isFail)
{
_stateProvider.CreateAccount(TestItem.AddressA, 1.Ether());
_stateProvider.Commit(_specProvider.GenesisSpec);
_stateProvider.CommitTree(0);

Transaction tx = Build.A.Transaction
.WithData([0])
.WithGasPrice(1)
.WithMaxFeePerGas(1)
.WithTo(TestItem.AddressB)
.WithValue(100.GWei())
.WithGasLimit(gasLimit)
.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA)
.TestObject;

Block block = Build.A.Block.WithNumber(long.MaxValue)
.WithTimestamp(MainnetSpecProvider.PragueBlockTimestamp)
.WithTransactions(tx)
.WithGasLimit(10000000).TestObject;

TransactionResult result = _transactionProcessor.Execute(tx, block.Header, NullTxTracer.Instance);
Assert.That(result.Fail, Is.EqualTo(isFail));
}

[Test]
public void balance_validation_intrinsic_below_floor()
{
_stateProvider.CreateAccount(TestItem.AddressA, 1.Ether());
_stateProvider.Commit(_specProvider.GenesisSpec);
_stateProvider.CommitTree(0);

Transaction tx = Build.A.Transaction
.WithData([0])
.WithGasPrice(1)
.WithMaxFeePerGas(1)
.WithTo(TestItem.AddressB)
.WithValue(100.GWei())
.WithGasLimit(21010)
.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA)
.TestObject;

Block block = Build.A.Block.WithNumber(long.MaxValue)
.WithTimestamp(MainnetSpecProvider.PragueBlockTimestamp)
.WithTransactions(tx)
.WithGasLimit(10000000).TestObject;

_transactionProcessor.Execute(tx, block.Header, NullTxTracer.Instance);

UInt256 balance = _stateProvider.GetBalance(TestItem.AddressA);
Assert.That(balance, Is.EqualTo(1.Ether() - 100.GWei() - 21010));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -763,17 +763,20 @@ protected virtual GasConsumed Refund(Transaction tx, BlockHeader header, IReleas
spentGas -= unspentGas;
operationGas -= unspentGas;
spentGas = Math.Max(spentGas, floorGas);
// As per eip-7623, the spent gas is updated to the maximum of the actual gas used or the floor gas,
// now we need to recalculate the unspent gas that should be refunded.
var unspentGasRefund = tx.GasLimit - spentGas;

long totalToRefund = codeInsertRefund;
if (!substate.ShouldRevert)
totalToRefund += substate.Refund + substate.DestroyList.Count * RefundOf.Destroy(spec.IsEip3529Enabled);
long actualRefund = RefundHelper.CalculateClaimableRefund(spentGas, totalToRefund, spec);

if (Logger.IsTrace)
Logger.Trace("Refunding unused gas of " + unspentGas + " and refund of " + actualRefund);
Logger.Trace("Refunding unused gas of " + unspentGasRefund + " and refund of " + actualRefund);
// If noValidation we didn't charge for gas, so do not refund
if (!opts.HasFlag(ExecutionOptions.SkipValidation))
WorldState.AddToBalance(tx.SenderAddress!, (ulong)(unspentGas + actualRefund) * gasPrice, spec);
WorldState.AddToBalance(tx.SenderAddress!, (ulong)(unspentGasRefund + actualRefund) * gasPrice, spec);
spentGas -= actualRefund;
operationGas -= actualRefund;
}
Expand Down

0 comments on commit 4c6f6e8

Please sign in to comment.