Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 9 additions & 5 deletions lib/evmone/instructions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ inline Result balance(StackTop stack, int64_t gas_left, ExecutionState& state) n

if (state.rev >= EVMC_BERLIN && state.host.access_account(addr) == EVMC_ACCESS_COLD)
{
if ((gas_left -= ADDITIONAL_COLD_ACCOUNT_ACCESS) < 0)
if ((gas_left -= additional_cold_account_access(state.rev)) < 0)
return {EVMC_OUT_OF_GAS, gas_left};
}

Expand Down Expand Up @@ -581,7 +581,7 @@ inline Result extcodesize(StackTop stack, int64_t gas_left, ExecutionState& stat

if (state.rev >= EVMC_BERLIN && state.host.access_account(addr) == EVMC_ACCESS_COLD)
{
if ((gas_left -= ADDITIONAL_COLD_ACCOUNT_ACCESS) < 0)
if ((gas_left -= additional_cold_account_access(state.rev)) < 0)
return {EVMC_OUT_OF_GAS, gas_left};
}

Expand All @@ -605,7 +605,7 @@ inline Result extcodecopy(StackTop stack, int64_t gas_left, ExecutionState& stat

if (state.rev >= EVMC_BERLIN && state.host.access_account(addr) == EVMC_ACCESS_COLD)
{
if ((gas_left -= ADDITIONAL_COLD_ACCOUNT_ACCESS) < 0)
if ((gas_left -= additional_cold_account_access(state.rev)) < 0)
return {EVMC_OUT_OF_GAS, gas_left};
}

Expand Down Expand Up @@ -662,7 +662,7 @@ inline Result extcodehash(StackTop stack, int64_t gas_left, ExecutionState& stat

if (state.rev >= EVMC_BERLIN && state.host.access_account(addr) == EVMC_ACCESS_COLD)
{
if ((gas_left -= ADDITIONAL_COLD_ACCOUNT_ACCESS) < 0)
if ((gas_left -= additional_cold_account_access(state.rev)) < 0)
return {EVMC_OUT_OF_GAS, gas_left};
}

Expand Down Expand Up @@ -1070,7 +1070,7 @@ inline TermResult selfdestruct(StackTop stack, int64_t gas_left, ExecutionState&

if (state.rev >= EVMC_BERLIN && state.host.access_account(beneficiary) == EVMC_ACCESS_COLD)
{
if ((gas_left -= COLD_ACCOUNT_ACCESS) < 0)
if ((gas_left -= cold_account_access(state.rev)) < 0)
return {EVMC_OUT_OF_GAS, gas_left};
}

Expand All @@ -1084,6 +1084,10 @@ inline TermResult selfdestruct(StackTop stack, int64_t gas_left, ExecutionState&
{
if (state.rev >= EVMC_AMSTERDAM)
{
// Balance update costs ACCOUNT_WRITE, charged first so in case of OOG
// the state-gas is not consumed.
if ((gas_left -= ACCOUNT_WRITE) < 0)
return {EVMC_OUT_OF_GAS, gas_left};
Comment thread
chfast marked this conversation as resolved.
if (!state.state_gas.charge(gas_left, NEW_ACCOUNT_STATE_GAS))
return {EVMC_OUT_OF_GAS, gas_left};
}
Expand Down
12 changes: 8 additions & 4 deletions lib/evmone/instructions_calls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace evmone::instr::core
namespace
{
constexpr auto CALL_VALUE_COST = 9000;
constexpr auto CALL_VALUE_COST_AMSTERDAM = ACCOUNT_WRITE + CALL_STIPEND;
constexpr auto ACCOUNT_CREATION_COST = 25000;

/// Get target address of a code executing instruction.
Expand All @@ -30,8 +31,9 @@ inline std::variant<evmc::address, Result> get_target_address(
return addr;

const auto delegate_account_access_cost =
(state.host.access_account(*delegate_addr) == EVMC_ACCESS_COLD ? COLD_ACCOUNT_ACCESS :
WARM_ACCESS);
(state.host.access_account(*delegate_addr) == EVMC_ACCESS_COLD ?
cold_account_access(state.rev) :
WARM_ACCESS);

if ((gas_left -= delegate_account_access_cost) < 0)
return Result{EVMC_OUT_OF_GAS, gas_left};
Expand Down Expand Up @@ -126,13 +128,15 @@ Result call_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noexce

if constexpr (HAS_VALUE_ARG)
{
if (has_value && (gas_left -= CALL_VALUE_COST) < 0)
const auto call_value_cost =
state.rev >= EVMC_AMSTERDAM ? CALL_VALUE_COST_AMSTERDAM : CALL_VALUE_COST;
if (has_value && (gas_left -= call_value_cost) < 0)
return {EVMC_OUT_OF_GAS, gas_left};
}

if (state.rev >= EVMC_BERLIN && state.host.access_account(dst) == EVMC_ACCESS_COLD)
{
if ((gas_left -= ADDITIONAL_COLD_ACCOUNT_ACCESS) < 0)
if ((gas_left -= additional_cold_account_access(state.rev)) < 0)
return {EVMC_OUT_OF_GAS, gas_left};
}

Expand Down
7 changes: 6 additions & 1 deletion lib/evmone/instructions_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,13 @@ constexpr auto STORAGE_COST_SPEC = []() noexcept {
tbl[EVMC_CANCUN] = tbl[EVMC_LONDON];
tbl[EVMC_PRAGUE] = tbl[EVMC_LONDON];
tbl[EVMC_OSAKA] = tbl[EVMC_LONDON];

tbl[EVMC_AMSTERDAM] = tbl[EVMC_LONDON];
tbl[EVMC_AMSTERDAM].set = tbl[EVMC_AMSTERDAM].reset; // Only execution cost (EIP-8037).
tbl[EVMC_AMSTERDAM].set = WARM_ACCESS + STORAGE_WRITE;
tbl[EVMC_AMSTERDAM].reset = tbl[EVMC_AMSTERDAM].set;
tbl[EVMC_AMSTERDAM].clear = (STORAGE_WRITE + COLD_STORAGE_ACCESS) * 4800 / 5000;
tbl[EVMC_AMSTERDAM].cold = ADDITIONAL_COLD_STORAGE_ACCESS;
Comment thread
chfast marked this conversation as resolved.

tbl[EVMC_EXPERIMENTAL] = tbl[EVMC_AMSTERDAM];
return tbl;
}();
Expand Down
25 changes: 21 additions & 4 deletions lib/evmone/instructions_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,30 @@ namespace evmone::instr
/// The special gas cost value marking an EVM instruction as "undefined".
constexpr int16_t undefined = -1;

/// State-access cost constants (EIP-2929).
/// State-access cost constants (EIP-2929, EIP-8038).
/// @{
inline constexpr auto WARM_ACCESS = 100;
inline constexpr auto COLD_STORAGE_ACCESS = 2100;
inline constexpr auto COLD_ACCOUNT_ACCESS = 2600;
inline constexpr auto COLD_ACCOUNT_ACCESS_AMSTERDAM = 3000;
inline constexpr auto ACCOUNT_WRITE = 9000;
inline constexpr auto STORAGE_WRITE = 10000;
inline constexpr auto CREATE_ACCESS = ACCOUNT_WRITE + COLD_ACCOUNT_ACCESS_AMSTERDAM;
Comment thread
chfast marked this conversation as resolved.

/// Additional cold account access cost.
/// The full cold-account-access cost for the given revision.
constexpr auto cold_account_access(evmc_revision rev) noexcept
{
return rev >= EVMC_AMSTERDAM ? COLD_ACCOUNT_ACCESS_AMSTERDAM : COLD_ACCOUNT_ACCESS;
}

/// Additional cold account access cost over the unconditionally-charged warm cost.
///
/// The warm access cost is unconditionally applied for every account access instruction.
/// The warm access cost is part of the base cost of every account access instruction.
/// If the access turns out to be cold, this cost must be applied additionally.
inline constexpr auto ADDITIONAL_COLD_ACCOUNT_ACCESS = COLD_ACCOUNT_ACCESS - WARM_ACCESS;
constexpr auto additional_cold_account_access(evmc_revision rev) noexcept
{
return cold_account_access(rev) - WARM_ACCESS;
}

/// Additional cold storage access cost over the unconditionally-charged warm cost.
inline constexpr auto ADDITIONAL_COLD_STORAGE_ACCESS = COLD_STORAGE_ACCESS - WARM_ACCESS;
Expand Down Expand Up @@ -181,6 +194,10 @@ constexpr inline GasCostTable gas_costs = []() noexcept {
table[EVMC_AMSTERDAM][OP_DUPN] = 3;
table[EVMC_AMSTERDAM][OP_SWAPN] = 3;
table[EVMC_AMSTERDAM][OP_EXCHANGE] = 3;
table[EVMC_AMSTERDAM][OP_CREATE] = CREATE_ACCESS;
table[EVMC_AMSTERDAM][OP_CREATE2] = CREATE_ACCESS;
table[EVMC_AMSTERDAM][OP_EXTCODESIZE] = 2 * WARM_ACCESS;
table[EVMC_AMSTERDAM][OP_EXTCODECOPY] = 2 * WARM_ACCESS;
Comment thread
chfast marked this conversation as resolved.
Comment thread
chfast marked this conversation as resolved.

table[EVMC_EXPERIMENTAL] = table[EVMC_AMSTERDAM];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,19 @@
},
"blocks": [
{
"rlp": "0xf90285f90259a00000000000000000000000000000000000000000000000000000000000000001a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794000000000000000000000000000000000000c014a09906207bb91a552f2c9036ff75ffebd15d6262fe1f1dc40afa6e047158ee25e5a06e1d1e299aa4bca4b32c05a8bd8cf631d97c7d9b54b1401c373860db01a38efea0c220348cfca03fd761c800a2af15752cee5ba04f836e61f798c4c6222c0cab02b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800184010000008265960c80a000000000000000000000000000000000000000000000000000000000000000008800000000000000000ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855e6a502e30180800e830186a094000000000000000000000000000000000000c0de8080c0800101c0c0",
"rlp": "0xf90285f90259a00000000000000000000000000000000000000000000000000000000000000001a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794000000000000000000000000000000000000c014a0f4935bad0acc0232b2d047082ad8a77060b8197220f0230ce4dc6ca40ca61214a06e1d1e299aa4bca4b32c05a8bd8cf631d97c7d9b54b1401c373860db01a38efea0bd211715b321166deb01159022eb56acf61b8e3183bf8f88325ebde25fc5a77db9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800184010000008281520c80a000000000000000000000000000000000000000000000000000000000000000008800000000000000000ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855e6a502e30180800e830186a094000000000000000000000000000000000000c0de8080c0800101c0c0",
"blockHeader": {
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000001",
"uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"coinbase": "0x000000000000000000000000000000000000c014",
"stateRoot": "0x9906207bb91a552f2c9036ff75ffebd15d6262fe1f1dc40afa6e047158ee25e5",
"stateRoot": "0xf4935bad0acc0232b2d047082ad8a77060b8197220f0230ce4dc6ca40ca61214",
Comment thread
Copilot marked this conversation as resolved.
"transactionsTrie": "0x6e1d1e299aa4bca4b32c05a8bd8cf631d97c7d9b54b1401c373860db01a38efe",
"receiptTrie": "0xc220348cfca03fd761c800a2af15752cee5ba04f836e61f798c4c6222c0cab02",
"receiptTrie": "0xbd211715b321166deb01159022eb56acf61b8e3183bf8f88325ebde25fc5a77d",
"bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0x00",
"number": "0x01",
"gasLimit": "0x01000000",
"gasUsed": "0x6596",
"gasUsed": "0x8152",
"timestamp": "0x0c",
"extraData": "0x",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
Expand Down Expand Up @@ -106,7 +106,7 @@
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
"code": "0x",
"nonce": "0x01",
"balance": "0x0254075c4c"
"balance": "0x0254063b9a"
},
"0x000000000000000000000000000000000000c0de": {
"code": "0x6000600155",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
},
"blocks": [
{
"rlp": "0xf90285f90259a00000000000000000000000000000000000000000000000000000000000000001a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794000000000000000000000000000000000000c014a09906207bb91a552f2c9036ff75ffebd15d6262fe1f1dc40afa6e047158ee25e5a06e1d1e299aa4bca4b32c05a8bd8cf631d97c7d9b54b1401c373860db01a38efea0c220348cfca03fd761c800a2af15752cee5ba04f836e61f798c4c6222c0cab02b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800184010000008265960c80a000000000000000000000000000000000000000000000000000000000000000008800000000000000000ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855e6a502e30180800e830186a094000000000000000000000000000000000000c0de8080c0800101c0c0",
"rlp": "0xf90285f90259a00000000000000000000000000000000000000000000000000000000000000001a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794000000000000000000000000000000000000c014a09906207bb91a552f2c9036ff75ffebd15d6262fe1f1dc40afa6e047158ee25e5a06e1d1e299aa4bca4b32c05a8bd8cf631d97c7d9b54b1401c373860db01a38efea0c220348cfca03fd761c800a2af15752cee5ba04f836e61f798c4c6222c0cab02b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800184010000008265968080a000000000000000000000000000000000000000000000000000000000000000008800000000000000000ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855e6a502e30180800e830186a094000000000000000000000000000000000000c0de8080c0800101c0c0",
"blockHeader": {
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000001",
"uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
Expand Down
13 changes: 11 additions & 2 deletions test/state/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "state_view.hpp"
#include <evmone/constants.hpp>
#include <evmone/delegation.hpp>
#include <evmone/instructions_traits.hpp>
#include <algorithm>
#include <ranges>

Expand Down Expand Up @@ -64,6 +65,10 @@ TransactionCost compute_tx_intrinsic_cost(evmc_revision rev, const Transaction&
static constexpr auto TX_CREATE_COST = 32000;
static constexpr auto ACCESS_LIST_ADDRESS_COST = 2400;
static constexpr auto ACCESS_LIST_STORAGE_KEY_COST = 1900;
static constexpr auto ACCESS_LIST_ADDRESS_COST_AMSTERDAM =
instr::additional_cold_account_access(EVMC_AMSTERDAM);
static constexpr auto ACCESS_LIST_STORAGE_KEY_COST_AMSTERDAM =
instr::ADDITIONAL_COLD_STORAGE_ACCESS;
Comment thread
chfast marked this conversation as resolved.
static constexpr auto ACCESS_LIST_ADDRESS_BYTES = 20;
static constexpr auto ACCESS_LIST_STORAGE_KEY_BYTES = 32;
static constexpr auto DATA_TOKEN_COST = 4;
Expand All @@ -82,8 +87,12 @@ TransactionCost compute_tx_intrinsic_cost(evmc_revision rev, const Transaction&
const auto access_list_num_bytes =
static_cast<int64_t>(num_addresses * ACCESS_LIST_ADDRESS_BYTES +
num_storage_keys * ACCESS_LIST_STORAGE_KEY_BYTES);
const auto access_list_cost = static_cast<int64_t>(
num_addresses * ACCESS_LIST_ADDRESS_COST + num_storage_keys * ACCESS_LIST_STORAGE_KEY_COST);
const auto address_cost =
(rev >= EVMC_AMSTERDAM) ? ACCESS_LIST_ADDRESS_COST_AMSTERDAM : ACCESS_LIST_ADDRESS_COST;
const auto storage_key_cost = (rev >= EVMC_AMSTERDAM) ? ACCESS_LIST_STORAGE_KEY_COST_AMSTERDAM :
ACCESS_LIST_STORAGE_KEY_COST;
const auto access_list_cost = static_cast<int64_t>(num_addresses) * address_cost +
static_cast<int64_t>(num_storage_keys) * storage_key_cost;

const auto auth_list_cost =
static_cast<int64_t>(tx.authorization_list.size()) * AUTHORIZATION_EMPTY_ACCOUNT_COST;
Expand Down
7 changes: 5 additions & 2 deletions test/unittests/evm_storage_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
/// This file contains EVM unit tests that access or modify the contract storage.

#include "evm_fixture.hpp"
#include <evmone/constants.hpp>
#include <array>

using namespace evmc::literals;
Expand Down Expand Up @@ -227,6 +228,7 @@ TEST_P(evm, sstore_cost_net_gas_metering)
int64_t set = -1;
int64_t reset = -1;
int64_t clear = -1;
int64_t state_set = 0; ///< Storage creation, charged in state gas (EIP-8037).
};

const auto test = [this](const evmc::bytes32& original, const evmc::bytes32& current,
Expand All @@ -246,8 +248,9 @@ TEST_P(evm, sstore_cost_net_gas_metering)
cost_constants[EVMC_ISTANBUL] = {800, 20000, 5000, 15000};
cost_constants[EVMC_BERLIN] = {100, 20000, 2900, 15000};
cost_constants[EVMC_LONDON] = {100, 20000, 2900, 4800};
cost_constants[EVMC_AMSTERDAM] = {100, 10100, 10100, 11616, evmone::STORAGE_SET_STATE_GAS};

for (const auto r : {EVMC_ISTANBUL, EVMC_BERLIN, EVMC_LONDON})
for (const auto r : {EVMC_ISTANBUL, EVMC_BERLIN, EVMC_LONDON, EVMC_AMSTERDAM})
{
rev = r;
const auto& c = cost_constants.at(static_cast<size_t>(r));
Expand All @@ -260,7 +263,7 @@ TEST_P(evm, sstore_cost_net_gas_metering)
test(O, Y, Z, b + c.warm_access, 0);
test(X, Y, Z, b + c.warm_access, 0);

test(O, O, Z, b + c.set, 0); // added
test(O, O, Z, b + c.set + c.state_set, 0); // added
test(X, X, O, b + c.reset, c.clear); // deleted
test(X, X, Z, b + c.reset, 0); // modified
test(X, O, Z, b + c.warm_access, -c.clear); // deleted added
Expand Down
9 changes: 5 additions & 4 deletions test/unittests/state_transition_eip7778_block_gas_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ TEST_F(state_transition, eip7778_sstore_clear_refund_amsterdam)
tx.to = To;
pre[To] = {.storage = {{0x01_bytes32, 0x42_bytes32}}, .code = sstore(1, 0)};

// Pre-refund: 21000 intrinsic + 5000 (cold SSTORE reset) + 6 (two PUSHes) = 26006.
// London-schedule clear refund 4800 ≤ cap 26006/5, so the full refund applies.
expect.gas_used = 26006 - 4800;
expect.block_gas_used = 26006;
// Pre-refund: 21000 intrinsic + 12100 (EIP-8038 cold SSTORE clear: WARM_ACCESS 100
// + STORAGE_WRITE 10000 + additional COLD_STORAGE_ACCESS 2000) + 6 (two PUSHes) = 33106. The
// EIP-8038 clear refund (11616) is capped at pre-refund/5 = 6621 (EIP-3529).
expect.gas_used = 33106 - 6621;
expect.block_gas_used = 33106;
expect.post[To].exists = true;
expect.post[To].storage[0x01_bytes32] = 0x00_bytes32;
}
Loading
Loading