Skip to content

Commit

Permalink
Merge pull request #142 from ethereum/eip-2200
Browse files Browse the repository at this point in the history
Implement EIP-2200
  • Loading branch information
chfast authored Nov 12, 2019
2 parents b15dd08 + b0fea29 commit a0e6a33
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 9 deletions.
1 change: 1 addition & 0 deletions lib/evmone/analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ code_analysis analyze(evmc_revision rev, const uint8_t* code, size_t code_size)
case OP_STATICCALL:
case OP_CREATE:
case OP_CREATE2:
case OP_SSTORE:
instr.arg.number = block.gas_cost;
break;

Expand Down
22 changes: 20 additions & 2 deletions lib/evmone/instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,20 +499,38 @@ const instruction* op_sstore(const instruction* instr, execution_state& state) n
if (state.msg->flags & EVMC_STATIC)
return state.exit(EVMC_STATIC_MODE_VIOLATION);

if (state.rev >= EVMC_ISTANBUL)
{
const auto correction = state.current_block_cost - instr->arg.number;
const auto gas_left = state.gas_left + correction;
if (gas_left <= 2300)
return state.exit(EVMC_OUT_OF_GAS);
}

const auto key = intx::be::store<evmc::bytes32>(state.stack.pop());
const auto value = intx::be::store<evmc::bytes32>(state.stack.pop());
auto status = state.host.set_storage(state.msg->destination, key, value);
int cost = 0;
switch (status)
{
case EVMC_STORAGE_UNCHANGED:
cost = state.rev == EVMC_CONSTANTINOPLE ? 200 : 5000;
if (state.rev >= EVMC_ISTANBUL)
cost = 800;
else if (state.rev == EVMC_CONSTANTINOPLE)
cost = 200;
else
cost = 5000;
break;
case EVMC_STORAGE_MODIFIED:
cost = 5000;
break;
case EVMC_STORAGE_MODIFIED_AGAIN:
cost = state.rev == EVMC_CONSTANTINOPLE ? 200 : 5000;
if (state.rev >= EVMC_ISTANBUL)
cost = 800;
else if (state.rev == EVMC_CONSTANTINOPLE)
cost = 200;
else
cost = 5000;
break;
case EVMC_STORAGE_ADDED:
cost = 20000;
Expand Down
64 changes: 57 additions & 7 deletions test/unittests/evm_state_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ TEST_F(evm_state, sstore_cost)
auto v1 = evmc::bytes32{};
v1.bytes[31] = 1;

auto revs = {EVMC_BYZANTIUM, EVMC_CONSTANTINOPLE, EVMC_PETERSBURG};
auto revs = {EVMC_BYZANTIUM, EVMC_CONSTANTINOPLE, EVMC_PETERSBURG, EVMC_ISTANBUL};
for (auto r : revs)
{
rev = r;
Expand Down Expand Up @@ -130,45 +130,95 @@ TEST_F(evm_state, sstore_cost)
storage[v1] = v1;
execute(sstore(1, push(1)));
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 206 : 5006);
if (rev >= EVMC_ISTANBUL)
EXPECT_EQ(gas_used, 806);
else if (rev == EVMC_CONSTANTINOPLE)
EXPECT_EQ(gas_used, 206);
else
EXPECT_EQ(gas_used, 5006);
execute(205, sstore(1, push(1)));
EXPECT_EQ(result.status_code, EVMC_OUT_OF_GAS);

// Added & unchanged:
storage.clear();
execute(sstore(1, push(1)) + sstore(1, push(1)));
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 20212 : 25012);
if (rev >= EVMC_ISTANBUL)
EXPECT_EQ(gas_used, 20812);
else if (rev == EVMC_CONSTANTINOPLE)
EXPECT_EQ(gas_used, 20212);
else
EXPECT_EQ(gas_used, 25012);

// Modified again:
storage.clear();
storage[v1] = {v1, true};
execute(sstore(1, push(2)));
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 206 : 5006);
if (rev >= EVMC_ISTANBUL)
EXPECT_EQ(gas_used, 806);
else if (rev == EVMC_CONSTANTINOPLE)
EXPECT_EQ(gas_used, 206);
else
EXPECT_EQ(gas_used, 5006);

// Added & modified again:
storage.clear();
execute(sstore(1, push(1)) + sstore(1, push(2)));
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 20212 : 25012);
if (rev >= EVMC_ISTANBUL)
EXPECT_EQ(gas_used, 20812);
else if (rev == EVMC_CONSTANTINOPLE)
EXPECT_EQ(gas_used, 20212);
else
EXPECT_EQ(gas_used, 25012);

// Modified & modified again:
storage.clear();
storage[v1] = v1;
execute(sstore(1, push(2)) + sstore(1, push(3)));
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 5212 : 10012);
if (rev >= EVMC_ISTANBUL)
EXPECT_EQ(gas_used, 5812);
else if (rev == EVMC_CONSTANTINOPLE)
EXPECT_EQ(gas_used, 5212);
else
EXPECT_EQ(gas_used, 10012);

// Modified & modified again back to original:
storage.clear();
storage[v1] = v1;
execute(sstore(1, push(2)) + sstore(1, push(1)));
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 5212 : 10012);
if (rev >= EVMC_ISTANBUL)
EXPECT_EQ(gas_used, 5812);
else if (rev == EVMC_CONSTANTINOPLE)
EXPECT_EQ(gas_used, 5212);
else
EXPECT_EQ(gas_used, 10012);
}
}

TEST_F(evm_state, sstore_below_stipend)
{
const auto code = sstore(0, 0);

rev = EVMC_HOMESTEAD;
execute(2306, code);
EXPECT_EQ(result.status_code, EVMC_OUT_OF_GAS);

rev = EVMC_CONSTANTINOPLE;
execute(2306, code);
EXPECT_EQ(result.status_code, EVMC_SUCCESS);

rev = EVMC_ISTANBUL;
execute(2306, code);
EXPECT_EQ(result.status_code, EVMC_OUT_OF_GAS);

execute(2307, code);
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
}

TEST_F(evm_state, tx_context)
{
rev = EVMC_ISTANBUL;
Expand Down

0 comments on commit a0e6a33

Please sign in to comment.