Skip to content

Commit a0e6a33

Browse files
authored
Merge pull request #142 from ethereum/eip-2200
Implement EIP-2200
2 parents b15dd08 + b0fea29 commit a0e6a33

File tree

3 files changed

+78
-9
lines changed

3 files changed

+78
-9
lines changed

lib/evmone/analysis.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ code_analysis analyze(evmc_revision rev, const uint8_t* code, size_t code_size)
131131
case OP_STATICCALL:
132132
case OP_CREATE:
133133
case OP_CREATE2:
134+
case OP_SSTORE:
134135
instr.arg.number = block.gas_cost;
135136
break;
136137

lib/evmone/instructions.cpp

+20-2
Original file line numberDiff line numberDiff line change
@@ -499,20 +499,38 @@ const instruction* op_sstore(const instruction* instr, execution_state& state) n
499499
if (state.msg->flags & EVMC_STATIC)
500500
return state.exit(EVMC_STATIC_MODE_VIOLATION);
501501

502+
if (state.rev >= EVMC_ISTANBUL)
503+
{
504+
const auto correction = state.current_block_cost - instr->arg.number;
505+
const auto gas_left = state.gas_left + correction;
506+
if (gas_left <= 2300)
507+
return state.exit(EVMC_OUT_OF_GAS);
508+
}
509+
502510
const auto key = intx::be::store<evmc::bytes32>(state.stack.pop());
503511
const auto value = intx::be::store<evmc::bytes32>(state.stack.pop());
504512
auto status = state.host.set_storage(state.msg->destination, key, value);
505513
int cost = 0;
506514
switch (status)
507515
{
508516
case EVMC_STORAGE_UNCHANGED:
509-
cost = state.rev == EVMC_CONSTANTINOPLE ? 200 : 5000;
517+
if (state.rev >= EVMC_ISTANBUL)
518+
cost = 800;
519+
else if (state.rev == EVMC_CONSTANTINOPLE)
520+
cost = 200;
521+
else
522+
cost = 5000;
510523
break;
511524
case EVMC_STORAGE_MODIFIED:
512525
cost = 5000;
513526
break;
514527
case EVMC_STORAGE_MODIFIED_AGAIN:
515-
cost = state.rev == EVMC_CONSTANTINOPLE ? 200 : 5000;
528+
if (state.rev >= EVMC_ISTANBUL)
529+
cost = 800;
530+
else if (state.rev == EVMC_CONSTANTINOPLE)
531+
cost = 200;
532+
else
533+
cost = 5000;
516534
break;
517535
case EVMC_STORAGE_ADDED:
518536
cost = 20000;

test/unittests/evm_state_test.cpp

+57-7
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ TEST_F(evm_state, sstore_cost)
9494
auto v1 = evmc::bytes32{};
9595
v1.bytes[31] = 1;
9696

97-
auto revs = {EVMC_BYZANTIUM, EVMC_CONSTANTINOPLE, EVMC_PETERSBURG};
97+
auto revs = {EVMC_BYZANTIUM, EVMC_CONSTANTINOPLE, EVMC_PETERSBURG, EVMC_ISTANBUL};
9898
for (auto r : revs)
9999
{
100100
rev = r;
@@ -130,45 +130,95 @@ TEST_F(evm_state, sstore_cost)
130130
storage[v1] = v1;
131131
execute(sstore(1, push(1)));
132132
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
133-
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 206 : 5006);
133+
if (rev >= EVMC_ISTANBUL)
134+
EXPECT_EQ(gas_used, 806);
135+
else if (rev == EVMC_CONSTANTINOPLE)
136+
EXPECT_EQ(gas_used, 206);
137+
else
138+
EXPECT_EQ(gas_used, 5006);
134139
execute(205, sstore(1, push(1)));
135140
EXPECT_EQ(result.status_code, EVMC_OUT_OF_GAS);
136141

137142
// Added & unchanged:
138143
storage.clear();
139144
execute(sstore(1, push(1)) + sstore(1, push(1)));
140145
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
141-
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 20212 : 25012);
146+
if (rev >= EVMC_ISTANBUL)
147+
EXPECT_EQ(gas_used, 20812);
148+
else if (rev == EVMC_CONSTANTINOPLE)
149+
EXPECT_EQ(gas_used, 20212);
150+
else
151+
EXPECT_EQ(gas_used, 25012);
142152

143153
// Modified again:
144154
storage.clear();
145155
storage[v1] = {v1, true};
146156
execute(sstore(1, push(2)));
147157
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
148-
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 206 : 5006);
158+
if (rev >= EVMC_ISTANBUL)
159+
EXPECT_EQ(gas_used, 806);
160+
else if (rev == EVMC_CONSTANTINOPLE)
161+
EXPECT_EQ(gas_used, 206);
162+
else
163+
EXPECT_EQ(gas_used, 5006);
149164

150165
// Added & modified again:
151166
storage.clear();
152167
execute(sstore(1, push(1)) + sstore(1, push(2)));
153168
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
154-
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 20212 : 25012);
169+
if (rev >= EVMC_ISTANBUL)
170+
EXPECT_EQ(gas_used, 20812);
171+
else if (rev == EVMC_CONSTANTINOPLE)
172+
EXPECT_EQ(gas_used, 20212);
173+
else
174+
EXPECT_EQ(gas_used, 25012);
155175

156176
// Modified & modified again:
157177
storage.clear();
158178
storage[v1] = v1;
159179
execute(sstore(1, push(2)) + sstore(1, push(3)));
160180
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
161-
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 5212 : 10012);
181+
if (rev >= EVMC_ISTANBUL)
182+
EXPECT_EQ(gas_used, 5812);
183+
else if (rev == EVMC_CONSTANTINOPLE)
184+
EXPECT_EQ(gas_used, 5212);
185+
else
186+
EXPECT_EQ(gas_used, 10012);
162187

163188
// Modified & modified again back to original:
164189
storage.clear();
165190
storage[v1] = v1;
166191
execute(sstore(1, push(2)) + sstore(1, push(1)));
167192
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
168-
EXPECT_EQ(gas_used, rev == EVMC_CONSTANTINOPLE ? 5212 : 10012);
193+
if (rev >= EVMC_ISTANBUL)
194+
EXPECT_EQ(gas_used, 5812);
195+
else if (rev == EVMC_CONSTANTINOPLE)
196+
EXPECT_EQ(gas_used, 5212);
197+
else
198+
EXPECT_EQ(gas_used, 10012);
169199
}
170200
}
171201

202+
TEST_F(evm_state, sstore_below_stipend)
203+
{
204+
const auto code = sstore(0, 0);
205+
206+
rev = EVMC_HOMESTEAD;
207+
execute(2306, code);
208+
EXPECT_EQ(result.status_code, EVMC_OUT_OF_GAS);
209+
210+
rev = EVMC_CONSTANTINOPLE;
211+
execute(2306, code);
212+
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
213+
214+
rev = EVMC_ISTANBUL;
215+
execute(2306, code);
216+
EXPECT_EQ(result.status_code, EVMC_OUT_OF_GAS);
217+
218+
execute(2307, code);
219+
EXPECT_EQ(result.status_code, EVMC_SUCCESS);
220+
}
221+
172222
TEST_F(evm_state, tx_context)
173223
{
174224
rev = EVMC_ISTANBUL;

0 commit comments

Comments
 (0)