Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1a40187
feat: EIP-7954 increase max contract size to 64 KiB (devnet-6)
Marchhill Jun 22, 2026
8efe06a
feat: schedule EIP-2780 and EIP-8246 into Amsterdam (devnet-6)
Marchhill Jun 22, 2026
de79428
feat: EIP-8038 state-access reprice with final values (devnet-6)
Marchhill Jun 22, 2026
159aebf
feat: align EIP-2780 intrinsic gas to devnet-6 spec
Marchhill Jun 22, 2026
d78e652
feat: EIP-8038 SSTORE write cost (STORAGE_WRITE)
Marchhill Jun 22, 2026
ac177ae
feat: EIP-8038 SSTORE access folds in warm cost; drop net-metered charge
Marchhill Jun 22, 2026
dc56e32
feat: EIP-8038 SSTORE source-based refunds
Marchhill Jun 22, 2026
e5ab63f
feat: EIP-8038 EIP-7702 per-authorization regular cost
Marchhill Jun 22, 2026
a130032
feat: EIP-2780 intrinsic charges delegated-recipient target touch
Marchhill Jun 22, 2026
79289a2
feat: EIP-2780/8037 top-frame NEW_ACCOUNT charge for new-account tran…
Marchhill Jun 22, 2026
cd1610b
feat: EIP-8038 CALL value/new-account reprice
Marchhill Jun 22, 2026
611e7fb
feat: EIP-2780/8037 top-frame delegation-target touch in execution
Marchhill Jun 22, 2026
c3a2aab
fix: EIP-7778/8037 block gas excludes the calldata floor
Marchhill Jun 22, 2026
20bfdb9
fix: EIP-8038 EIP-7702 existing-authority regular ACCOUNT_WRITE refund
Marchhill Jun 22, 2026
27b5809
feat: EIP-8038 SELFDESTRUCT beneficiary ACCOUNT_WRITE charge
Marchhill Jun 23, 2026
811b031
feat: EIP-8038 CREATE/CREATE2 opcode account cost (CREATE_ACCESS)
Marchhill Jun 23, 2026
72ce469
fix: EIP-8038 refund full auth state/regular gas for invalid authoriz…
Marchhill Jun 23, 2026
4fd85c2
fix: EIP-2780 top-frame delegation touch uses post-authorization state
Marchhill Jun 23, 2026
357a5be
test: pin EIP-8038 constants to devnet-6 repriced values
Marchhill Jun 23, 2026
2281bc0
fix: segregate standalone EIP-2780 gas model from EIP-8038 reprice
Marchhill Jun 23, 2026
300de2b
fix: EIP-8037 refund NEW_ACCOUNT on successful CREATE to a pre-existi…
Marchhill Jun 23, 2026
431d3ea
fix: EIP-8037 refund NEW_ACCOUNT on successful top-level CREATE tx to…
Marchhill Jun 24, 2026
90cb4f7
fix: EIP-8037 refund NEW_ACCOUNT when value CALL cannot proceed
Marchhill Jun 24, 2026
09afb9d
test: update intrinsic/EIP-8037/EIP-8038 unit tests to devnet-6 gas m…
Marchhill Jun 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions src/Nethermind/Nethermind.Core.Test/Eip8038ConstantsTests.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
// SPDX-FileCopyrightText: 2026 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using Nethermind.Core;

Check warning on line 4 in src/Nethermind/Nethermind.Core.Test/Eip8038ConstantsTests.cs

View workflow job for this annotation

GitHub Actions / Check code lint

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005) [/home/runner/work/nethermind/nethermind/src/Nethermind/Nethermind.Core.Test/Nethermind.Core.Test.csproj]
using NUnit.Framework;

namespace Nethermind.Core.Test;

/// <summary>
/// Pins the EIP-8038 gas parameters to the spec's derivation formulas. The base values are
/// placeholders equal to the current (pre-8038) costs while the EIP is a Draft; these tests
/// guard the relationships so the derived values stay correct when the final figures land.
/// Pins the EIP-8038 gas parameters to the final repriced values scheduled in Amsterdam by
/// glamsterdam-devnet-6, and guards the derivation relationships so the derived values stay
/// consistent with the base parameters.
/// </summary>
public class Eip8038ConstantsTests
{
[Test]
public void Base_parameters_match_their_current_placeholder_values()
public void Base_parameters_match_the_devnet6_repriced_values()
{
long coldAccountAccess = Eip8038Constants.ColdAccountAccess;
long warmAccess = Eip8038Constants.WarmAccess;
Expand All @@ -25,21 +25,24 @@

Assert.Multiple(() =>
{
Assert.That(coldAccountAccess, Is.EqualTo(2600));
Assert.That(coldAccountAccess, Is.EqualTo(3000));
Assert.That(warmAccess, Is.EqualTo(100));
Assert.That(coldStorageAccess, Is.EqualTo(2100));
Assert.That(accountWrite, Is.EqualTo(6700));
Assert.That(storageWrite, Is.EqualTo(2800));
Assert.That(coldStorageAccess, Is.EqualTo(3000));
Assert.That(accountWrite, Is.EqualTo(8000));
Assert.That(storageWrite, Is.EqualTo(10000));
Assert.That(callStipend, Is.EqualTo(2300));
});
}

[Test]
public void Account_write_is_call_value_minus_stipend()
{
long accountWrite = Eip8038Constants.AccountWrite;
Assert.That(accountWrite, Is.EqualTo(GasCostOf.CallValue - GasCostOf.CallStipend));
}
public void Derived_parameters_match_the_devnet6_repriced_values() =>
Assert.Multiple(() =>
{
Assert.That(Eip8038Constants.CallValue, Is.EqualTo(10300));
Assert.That(Eip8038Constants.CreateAccess, Is.EqualTo(11000));
Assert.That(Eip8038Constants.StorageClearRefund, Is.EqualTo(12480));
Assert.That(Eip8038Constants.PerAuthBaseRegular, Is.EqualTo(15816));
});

[Test]
public void Call_value_is_account_write_plus_stipend()
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Core/CodeSizeConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ namespace Nethermind.Core;
public static class CodeSizeConstants
{
public const int MaxCodeSizeEip170 = 24_576; // 24KiB
public const int MaxCodeSizeEip7954 = 32_768; // 32KiB
public const int MaxCodeSizeEip7954 = 65_536; // 64KiB
}
41 changes: 23 additions & 18 deletions src/Nethermind/Nethermind.Core/Eip8038Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,52 @@ namespace Nethermind.Core;
/// (regular + state) gas model.
/// </summary>
/// <remarks>
/// The EIP is a Draft: the final repriced values are still <c>TBD</c>. The base parameters below are
/// therefore placeholders equal to the current (pre-8038) costs, so that enabling the EIP is a no-op
/// for the base constants until the final figures land. The derived parameters are expressed via the
/// EIP's derivation formulas so they recompute automatically once the base values are finalized.
/// Scheduled in Amsterdam by glamsterdam-devnet-6 with the final repriced values below. The derived
/// parameters are expressed via the EIP's derivation formulas so they recompute from the base values.
/// </remarks>
public static class Eip8038Constants
{
// Base parameters (placeholders == current values; final values TBD).
// Base parameters (final values per EIP-8038, glamsterdam-devnet-6).

/// <summary>Cold account-touch cost (EIP-2929 <c>COLD_ACCOUNT_ACCESS</c>).</summary>
public const long ColdAccountAccess = GasCostOf.ColdAccountAccess; // 2600
/// <summary>Cold account-touch cost (<c>COLD_ACCOUNT_ACCESS</c>).</summary>
public const long ColdAccountAccess = 3000; // was 2600 (EIP-2929)

/// <summary>Warm state-access cost (EIP-2929 <c>WARM_ACCESS</c>).</summary>
public const long WarmAccess = GasCostOf.WarmStateRead; // 100
/// <summary>Warm state-access cost (<c>WARM_ACCESS</c>).</summary>
public const long WarmAccess = GasCostOf.WarmStateRead; // 100 (unchanged)

/// <summary>Cold storage-slot access cost (EIP-2929 <c>COLD_STORAGE_ACCESS</c>).</summary>
public const long ColdStorageAccess = GasCostOf.ColdSLoad; // 2100
/// <summary>Cold storage-slot access cost (<c>COLD_STORAGE_ACCESS</c>).</summary>
public const long ColdStorageAccess = 3000; // was 2100 (EIP-2929)

/// <summary>The account-write component of value-bearing <c>*CALL</c>s (<c>CALL_VALUE - CALL_STIPEND</c>).</summary>
public const long AccountWrite = GasCostOf.CallValue - GasCostOf.CallStipend; // 6700
public const long AccountWrite = 8000;

/// <summary>The regular-gas write component of <c>SSTORE</c> (<c>GAS_STORAGE_UPDATE - COLD_STORAGE_ACCESS - WARM_ACCESS</c>).</summary>
public const long StorageWrite = GasCostOf.SReset - ColdStorageAccess - WarmAccess; // 2800
/// <summary>The regular-gas write component of <c>SSTORE</c> (<c>STORAGE_WRITE</c>).</summary>
public const long StorageWrite = 10000;

/// <summary>Stipend forwarded with a value-bearing call (unchanged from EIP-2929).</summary>
public const long CallStipend = GasCostOf.CallStipend; // 2300

// Derived parameters (EIP-8038 derivation formulas; recompute from the base values above).

/// <summary><c>CALL_VALUE = ACCOUNT_WRITE + CALL_STIPEND</c>.</summary>
public const long CallValue = AccountWrite + CallStipend; // 9000
public const long CallValue = AccountWrite + CallStipend; // 10300

/// <summary><c>CREATE_ACCESS = ACCOUNT_WRITE + COLD_STORAGE_ACCESS</c>, charged in regular gas by CREATE/CREATE2.</summary>
public const long CreateAccess = AccountWrite + ColdStorageAccess;

/// <summary>Access-list address entry cost, redefined to <c>COLD_ACCOUNT_ACCESS</c>.</summary>
public const long AccessListAddressCost = ColdAccountAccess; // 2600 (was 2400)
public const long AccessListAddressCost = ColdAccountAccess; // 3000 (was 2400)

/// <summary>Access-list storage-key entry cost, redefined to <c>COLD_STORAGE_ACCESS</c>.</summary>
public const long AccessListStorageKeyCost = ColdStorageAccess; // 2100 (was 1900)
public const long AccessListStorageKeyCost = ColdStorageAccess; // 3000 (was 1900)

/// <summary><c>STORAGE_CLEAR_REFUND = (STORAGE_WRITE + COLD_STORAGE_ACCESS) * 4800 / 5000</c>.</summary>
public const long StorageClearRefund = (StorageWrite + ColdStorageAccess) * 4800 / 5000;
public const long StorageClearRefund = (StorageWrite + ColdStorageAccess) * 4800 / 5000; // 12480

/// <summary>
/// EIP-7702 per-authorization regular gas: <c>ACCOUNT_WRITE + REGULAR_PER_AUTH_BASE_COST</c>, where
/// the latter is the auth-tuple calldata floor (101 bytes × 16), an ECRECOVER (3000), a cold account
/// touch, and two warm accesses.
/// </summary>
public const long PerAuthBaseRegular = AccountWrite + (101 * 16 + 3000 + ColdAccountAccess + 2 * WarmAccess); // 15816
}
3 changes: 2 additions & 1 deletion src/Nethermind/Nethermind.Core/GasCostOf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ public static class GasCostOf
public const long MinModExpEip7883 = 500; // eip-7883

// eip-2780: reduce intrinsic transaction gas and reprice state-touching primitives.
public const long TransactionEip2780 = 4500; // TX_BASE_COST = 3000 ECRECOVER + 1000 STATE_UPDATE + 500 sender cold no-code
public const long TransactionEip2780 = 12000; // TX_BASE_COST: ECDSA recovery + sender account access + sender account write
public const long TxValueCostEip2780 = 4244; // recipient balance write for a value-bearing transfer (non-create)
public const long StateUpdateEip2780 = 1000; // one account-leaf write (nonce/balance coalesced)
public const long ColdAccountAccessNoCodeEip2780 = 500; // cold touch of an account known to have no code
public const long TransferLogEip2780 = 1756; // eip-7708 LOG3 transfer event: 375 + 3*375 + 32*8
Expand Down
13 changes: 9 additions & 4 deletions src/Nethermind/Nethermind.Core/Specs/SpecGasCosts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ public SpecGasCosts(IReleaseSpec spec)
? GasCostOf.SReset - GasCostOf.ColdSLoad
: GasCostOf.SReset;

// EIP-8038 folds the warm-access charge into the SSTORE access cost itself (see
// ConsumeStorageAccessGas), so no separate net-metered charge is added on top.
long netMeteredSStoreCost = NetMeteredSStoreCost =
hotCold ? GasCostOf.WarmStateRead
spec.IsEip8038Enabled ? GasCostOf.Free
: hotCold ? GasCostOf.WarmStateRead
: netIstanbul ? GasCostOf.SStoreNetMeteredEip2200
: netConstantinople ? GasCostOf.SStoreNetMeteredEip1283
: GasCostOf.Free;
Expand Down Expand Up @@ -108,9 +111,11 @@ public SpecGasCosts(IReleaseSpec spec)
? GasCostOf.TotalCostFloorPerTokenEip7623
: GasCostOf.Free;

SClearRefund = spec.IsEip3529Enabled
? RefundOf.SClearAfterEip3529
: RefundOf.SClearBeforeEip3529;
SClearRefund = spec.IsEip8038Enabled
? Eip8038Constants.StorageClearRefund // 12480
: spec.IsEip3529Enabled
? RefundOf.SClearAfterEip3529
: RefundOf.SClearBeforeEip3529;

DestroyRefund = spec.IsEip3529Enabled
? RefundOf.DestroyAfterEip3529
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Evm.Test/Eip2780Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using Nethermind.Core;
using Nethermind.Core.Specs;
using Nethermind.Core.Test.Blockchain;
using Nethermind.Core.Extensions;

Check warning on line 8 in src/Nethermind/Nethermind.Evm.Test/Eip2780Tests.cs

View workflow job for this annotation

GitHub Actions / Check code lint

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005) [/home/runner/work/nethermind/nethermind/src/Nethermind/Nethermind.Evm.Test/Nethermind.Evm.Test.csproj]
using Nethermind.Core.Test.Builders;
using Nethermind.Evm.GasPolicy;
using Nethermind.Int256;
Expand All @@ -29,7 +29,7 @@
private static long ChargeCallValue(bool isSelfCall, bool recipientEmpty)
{
EthereumGasPolicy gas = EthereumGasPolicy.FromLong(1_000_000);
Assert.That(EthereumGasPolicy.ConsumeCallValueTransferEip2780(ref gas, isSelfCall, recipientEmpty), Is.True);
Assert.That(EthereumGasPolicy.ConsumeCallValueTransferEip2780(ref gas, isSelfCall, recipientEmpty, Eip2780Spec), Is.True);
return 1_000_000 - EthereumGasPolicy.GetRemainingGas(in gas);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,34 +184,34 @@ public void Calculate_block_regular_gas_keeps_valid_transcripts_non_negative()
long stateGasSpill = random.Next(0, (int)Math.Min(spentRegular, int.MaxValue));
long stateGasSpillReclassified = random.Next(0, (int)Math.Min(stateGasSpill, int.MaxValue));
long remainingRegular = initialRegular - spentRegular;
long floorGas = random.Next(21_000, 200_000);

long executionRegularGasUsed = initialRegular - remainingRegular - stateGasSpill + stateGasSpillReclassified;
long blockRegularGas = Eip8037BlockGasInclusionCheck.CalculateBlockRegularGas(
intrinsicRegular,
initialRegular,
remainingRegular,
stateGasSpill,
stateGasSpillReclassified,
floorGas);
stateGasSpillReclassified);

Assert.That(executionRegularGasUsed, Is.GreaterThanOrEqualTo(0L));
Assert.That(blockRegularGas, Is.EqualTo(Math.Max(intrinsicRegular + executionRegularGasUsed, floorGas)));
Assert.That(blockRegularGas, Is.EqualTo(intrinsicRegular + executionRegularGasUsed));
}
}

[TestCase(300L, 100L, TestName = "Calculate_block_regular_gas_floor_clamps_low_regular_gas")]
[TestCase(0L, 0L, TestName = "Calculate_block_regular_gas_allows_negative_execution_intermediate")]
public void Calculate_block_regular_gas_clamps_to_floor(long initialRegular, long remainingRegular)
[Test]
public void Calculate_block_regular_gas_ignores_calldata_floor()
{
// Regression: the EIP-7623/7976 calldata floor is a minimum charge on the sender
// (tx_gas_used / receipts) only and must NOT inflate the block's regular-gas dimension.
// Here the actual regular gas consumed (21_000) is far below any plausible floor, yet the
// block regular gas must report the consumed amount, not a floor-clamped value.
long blockRegularGas = Eip8037BlockGasInclusionCheck.CalculateBlockRegularGas(
intrinsicRegularGas: 21_000,
initialRegularGas: initialRegular,
remainingRegularGas: remainingRegular,
stateGasSpill: 200,
stateGasSpillReclassified: 0,
floorGas: 53_000);
initialRegularGas: 0,
remainingRegularGas: 0,
stateGasSpill: 0,
stateGasSpillReclassified: 0);

Assert.That(blockRegularGas, Is.EqualTo(53_000));
Assert.That(blockRegularGas, Is.EqualTo(21_000));
}
}
28 changes: 16 additions & 12 deletions src/Nethermind/Nethermind.Evm.Test/Eip8037Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,14 @@ public void Amsterdam_access_list_floor_pricing_is_added_to_regular_and_floor_in

IntrinsicGas<EthereumGasPolicy> splitIntrinsicGas = EthereumGasPolicy.CalculateIntrinsicGas(tx, Amsterdam.Instance);
EthereumIntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, Amsterdam.Instance);
long accessListBaseCost = GasCostOf.AccessAccountListEntry + 3 * GasCostOf.AccessStorageListEntry;
// Amsterdam (EIP-2780 + EIP-8038): TX_BASE=12000; access-list entries repriced to COLD_ACCOUNT_ACCESS /
// COLD_STORAGE_ACCESS; the value-bearing recipient touch adds COLD_ACCOUNT_ACCESS + TRANSFER_LOG + TX_VALUE.
long recipientRegular = Eip8038Constants.ColdAccountAccess + GasCostOf.TransferLogEip2780 + GasCostOf.TxValueCostEip2780;
long accessListBaseCost = Eip8038Constants.AccessListAddressCost + 3 * Eip8038Constants.AccessListStorageKeyCost;
long accessListFloorTokens = (20L + 3 * 32L) * Amsterdam.Instance.GasCosts.TxDataNonZeroMultiplier;
long accessListFloorCost = accessListFloorTokens * Amsterdam.Instance.GasCosts.TotalCostFloorPerToken;
long expectedRegular = GasCostOf.Transaction + accessListBaseCost + accessListFloorCost;
long expectedFloorGas = GasCostOf.Transaction + accessListFloorCost;
long expectedRegular = GasCostOf.TransactionEip2780 + recipientRegular + accessListBaseCost + accessListFloorCost;
long expectedFloorGas = GasCostOf.TransactionEip2780 + accessListFloorCost;

Assert.That(splitIntrinsicGas.Standard.Value, Is.EqualTo(expectedRegular));
Assert.That(splitIntrinsicGas.Standard.StateReservoir, Is.Zero);
Expand Down Expand Up @@ -270,22 +273,23 @@ public void State_refund_is_clamped_to_intrinsic_state_floor()
}

[Test]
public void Code_insert_state_refund_is_available_to_later_state_gas()
public void Code_insert_refund_credits_regular_gas_not_state_under_eip8038()
{
const long intrinsicAuthState = GasCostOf.NewAccountState + GasCostOf.PerAuthBaseState;
// EIP-8038: the per-authorization code-insert (EIP-7702 existing-authority) refund returns the
// worst-case ACCOUNT_WRITE to the regular-gas refund counter and leaves the state-gas dimension
// untouched (the NEW_ACCOUNT / AUTH_BASE state refunds are applied separately, pre-execution).
EthereumGasPolicy gas = new()
{
Value = 2 * GasCostOf.SSetState - GasCostOf.NewAccountState,
StateGasUsed = intrinsicAuthState,
Value = 0,
StateReservoir = 0,
StateGasUsed = GasCostOf.PerAuthBaseState,
};

long regularRefund = EthereumGasPolicy.ApplyCodeInsertRefunds(ref gas, 1, Amsterdam.Instance, intrinsicAuthState);
Assert.That(EthereumGasPolicy.ConsumeStateGas(ref gas, GasCostOf.SSetState), Is.True);
Assert.That(EthereumGasPolicy.ConsumeStateGas(ref gas, GasCostOf.SSetState), Is.True);
long regularRefund = EthereumGasPolicy.ApplyCodeInsertRefunds(ref gas, 1, Amsterdam.Instance, stateGasFloor: 0);

Assert.That(regularRefund, Is.Zero);
Assert.That(regularRefund, Is.EqualTo(Eip8038Constants.AccountWrite));
Assert.That((gas.Value, gas.StateReservoir, gas.StateGasUsed, gas.StateGasSpill),
Is.EqualTo((0L, 0L, GasCostOf.PerAuthBaseState + 2 * GasCostOf.SSetState, 2 * GasCostOf.SSetState - GasCostOf.NewAccountState)));
Is.EqualTo((0L, 0L, GasCostOf.PerAuthBaseState, 0L)));
}

[Test]
Expand Down
5 changes: 3 additions & 2 deletions src/Nethermind/Nethermind.Evm.Test/Eip8038Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class Eip8038Tests(bool eip8038Enabled) : VirtualMachineTestsBase
private static readonly Address Target = TestItem.AddressC;

private long ExtraWarmAccess => eip8038Enabled ? Eip8038Constants.WarmAccess : 0;
private long ColdAccountAccess => eip8038Enabled ? Eip8038Constants.ColdAccountAccess : GasCostOf.ColdAccountAccess;

[SetUp]
public override void Setup()
Expand Down Expand Up @@ -72,7 +73,7 @@ public void ExtCodeSize_charges_extra_warm_access()
Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success));
long expected = GasCostOf.Transaction
+ GasCostOf.VeryLow // PUSH20 target
+ GasCostOf.ColdAccountAccess // cold EXTCODESIZE access
+ ColdAccountAccess // cold EXTCODESIZE access (EIP-8038 repriced when enabled)
+ ExtraWarmAccess // EIP-8038 extra access
+ GasCostOf.Base; // POP
AssertGas(result, expected);
Expand All @@ -96,7 +97,7 @@ public void ExtCodeCopy_charges_extra_warm_access()
Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success));
long expected = GasCostOf.Transaction
+ 4 * GasCostOf.VeryLow // three PUSH1 0x00 + PUSH20 target
+ GasCostOf.ColdAccountAccess // cold EXTCODECOPY access
+ ColdAccountAccess // cold EXTCODECOPY access (EIP-8038 repriced when enabled)
+ ExtraWarmAccess; // EIP-8038 extra access
AssertGas(result, expected);
}
Expand Down
Loading
Loading