Skip to content

Commit bb2532e

Browse files
authored
Merge pull request #281 from moonbeam-foundation/ahmad-cancun-eip-6780
Cancun self destruct changes (EIP 6780)
2 parents c5c927d + c4bad3c commit bb2532e

14 files changed

+442
-23
lines changed

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ sha3 = { version = "0.10", default-features = false }
3232

3333
evm-interpreter = { version = "1.0.0-dev", path = "interpreter", default-features = false }
3434

35+
[dev-dependencies]
36+
hex = { version = "0.4", features = [ "serde" ] }
37+
3538
[features]
3639
default = ["std"]
3740
std = [

interpreter/src/eval/system.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -362,9 +362,7 @@ pub fn suicide<S: AsRef<RuntimeState>, H: RuntimeEnvironment + RuntimeBackend, T
362362
value: balance,
363363
})?;
364364

365-
handler.mark_delete(address);
366-
handler.reset_balance(address);
367-
365+
handler.mark_delete_reset(address);
368366
Ok(((), ()))
369367
}) {
370368
Ok(()) => Control::Exit(ExitSucceed::Suicided.into()),

interpreter/src/runtime.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ pub trait RuntimeBackend: RuntimeBaseBackend {
139139
fn original_storage(&self, address: H160, index: H256) -> H256;
140140
/// Check whether an address has already been deleted.
141141
fn deleted(&self, address: H160) -> bool;
142+
/// Check whether an address has already been created in the transaction.
143+
fn created(&self, address: H160) -> bool;
142144
/// Checks if the address or (address, index) pair has been previously accessed.
143145
fn is_cold(&self, address: H160, index: Option<H256>) -> bool;
144146
fn is_hot(&self, address: H160, index: Option<H256>) -> bool {
@@ -158,8 +160,10 @@ pub trait RuntimeBackend: RuntimeBaseBackend {
158160
) -> Result<(), ExitError>;
159161
/// Create a log owned by address with given topics and data.
160162
fn log(&mut self, log: Log) -> Result<(), ExitError>;
161-
/// Mark an address to be deleted.
162-
fn mark_delete(&mut self, address: H160);
163+
/// Mark an address to be deleted and its balance to be reset.
164+
fn mark_delete_reset(&mut self, address: H160);
165+
// Mark an address as created in the current transaction.
166+
fn mark_create(&mut self, address: H160);
163167
/// Fully delete storages of an account.
164168
fn reset_storage(&mut self, address: H160);
165169
/// Set code of an account.

interpreter/tests/usability.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::rc::Rc;
2-
31
use evm_interpreter::{
42
error::{CallCreateTrap, Capture, ExitError, ExitSucceed},
53
etable::{Control, Etable},
@@ -12,6 +10,7 @@ use evm_interpreter::{
1210
EtableInterpreter, RunInterpreter,
1311
};
1412
use primitive_types::{H160, H256, U256};
13+
use std::rc::Rc;
1514

1615
const CODE1: &str = "60e060020a6000350480632839e92814601e57806361047ff414603457005b602a6004356024356047565b8060005260206000f35b603d6004356099565b8060005260206000f35b600082600014605457605e565b8160010190506093565b81600014606957607b565b60756001840360016047565b90506093565b609060018403608c85600186036047565b6047565b90505b92915050565b6000816000148060a95750816001145b60b05760b7565b81905060cf565b60c1600283036099565b60cb600184036099565b0190505b91905056";
1716
const DATA1: &str = "2839e92800000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001";
@@ -135,6 +134,11 @@ impl RuntimeBackend for UnimplementedHandler {
135134
fn deleted(&self, _address: H160) -> bool {
136135
unimplemented!()
137136
}
137+
138+
fn created(&self, _address: H160) -> bool {
139+
unimplemented!()
140+
}
141+
138142
fn is_cold(&self, _address: H160, _index: Option<H256>) -> bool {
139143
unimplemented!()
140144
}
@@ -157,7 +161,11 @@ impl RuntimeBackend for UnimplementedHandler {
157161
fn log(&mut self, _log: Log) -> Result<(), ExitError> {
158162
unimplemented!()
159163
}
160-
fn mark_delete(&mut self, _address: H160) {
164+
fn mark_delete_reset(&mut self, _address: H160) {
165+
unimplemented!()
166+
}
167+
168+
fn mark_create(&mut self, _address: H160) {
161169
unimplemented!()
162170
}
163171

jsontests/src/run.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ pub fn run_test(
184184
state,
185185
};
186186

187-
let mut run_backend = OverlayedBackend::new(&base_backend, initial_accessed.clone());
188-
let mut step_backend = OverlayedBackend::new(&base_backend, initial_accessed.clone());
187+
let mut run_backend = OverlayedBackend::new(&base_backend, initial_accessed.clone(), &config);
188+
let mut step_backend = OverlayedBackend::new(&base_backend, initial_accessed.clone(), &config);
189189

190190
// Run
191191
let run_result = evm::transact(args.clone(), Some(4), &mut run_backend, &invoker);

src/backend/overlayed.rs

+47-10
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use evm_interpreter::{
1111
};
1212
use primitive_types::{H160, H256, U256};
1313

14-
use crate::{backend::TransactionalBackend, MergeStrategy};
14+
use crate::{backend::TransactionalBackend, standard::Config, MergeStrategy};
1515

1616
#[derive(Clone, Debug)]
1717
pub struct OverlayedChangeSet {
@@ -25,18 +25,24 @@ pub struct OverlayedChangeSet {
2525
pub deletes: BTreeSet<H160>,
2626
}
2727

28-
pub struct OverlayedBackend<B> {
28+
pub struct OverlayedBackend<'config, B> {
2929
backend: B,
3030
substate: Box<Substate>,
3131
accessed: BTreeSet<(H160, Option<H256>)>,
32+
config: &'config Config,
3233
}
3334

34-
impl<B> OverlayedBackend<B> {
35-
pub fn new(backend: B, accessed: BTreeSet<(H160, Option<H256>)>) -> Self {
35+
impl<'config, B> OverlayedBackend<'config, B> {
36+
pub fn new(
37+
backend: B,
38+
accessed: BTreeSet<(H160, Option<H256>)>,
39+
config: &'config Config,
40+
) -> Self {
3641
Self {
3742
backend,
3843
substate: Box::new(Substate::new()),
3944
accessed,
45+
config,
4046
}
4147
}
4248

@@ -57,7 +63,7 @@ impl<B> OverlayedBackend<B> {
5763
}
5864
}
5965

60-
impl<B: RuntimeEnvironment> RuntimeEnvironment for OverlayedBackend<B> {
66+
impl<B: RuntimeEnvironment> RuntimeEnvironment for OverlayedBackend<'_, B> {
6167
fn block_hash(&self, number: U256) -> H256 {
6268
self.backend.block_hash(number)
6369
}
@@ -95,7 +101,7 @@ impl<B: RuntimeEnvironment> RuntimeEnvironment for OverlayedBackend<B> {
95101
}
96102
}
97103

98-
impl<B: RuntimeBaseBackend> RuntimeBaseBackend for OverlayedBackend<B> {
104+
impl<B: RuntimeBaseBackend> RuntimeBaseBackend for OverlayedBackend<'_, B> {
99105
fn balance(&self, address: H160) -> U256 {
100106
if let Some(balance) = self.substate.known_balance(address) {
101107
balance
@@ -145,11 +151,15 @@ impl<B: RuntimeBaseBackend> RuntimeBaseBackend for OverlayedBackend<B> {
145151
}
146152
}
147153

148-
impl<B: RuntimeBaseBackend> RuntimeBackend for OverlayedBackend<B> {
154+
impl<B: RuntimeBaseBackend> RuntimeBackend for OverlayedBackend<'_, B> {
149155
fn original_storage(&self, address: H160, index: H256) -> H256 {
150156
self.backend.storage(address, index)
151157
}
152158

159+
fn created(&self, address: H160) -> bool {
160+
self.substate.created(address)
161+
}
162+
153163
fn deleted(&self, address: H160) -> bool {
154164
self.substate.deleted(address)
155165
}
@@ -184,8 +194,20 @@ impl<B: RuntimeBaseBackend> RuntimeBackend for OverlayedBackend<B> {
184194
Ok(())
185195
}
186196

187-
fn mark_delete(&mut self, address: H160) {
188-
self.substate.deletes.insert(address);
197+
fn mark_delete_reset(&mut self, address: H160) {
198+
if self.config.suicide_only_in_same_tx {
199+
if self.created(address) {
200+
self.substate.deletes.insert(address);
201+
self.substate.storage_resets.insert(address);
202+
}
203+
} else {
204+
self.substate.deletes.insert(address);
205+
self.substate.storage_resets.insert(address);
206+
}
207+
}
208+
209+
fn mark_create(&mut self, address: H160) {
210+
self.substate.creates.insert(address);
189211
}
190212

191213
fn reset_storage(&mut self, address: H160) {
@@ -238,7 +260,7 @@ impl<B: RuntimeBaseBackend> RuntimeBackend for OverlayedBackend<B> {
238260
}
239261
}
240262

241-
impl<B: RuntimeBaseBackend> TransactionalBackend for OverlayedBackend<B> {
263+
impl<'config, B: RuntimeBaseBackend> TransactionalBackend for OverlayedBackend<'config, B> {
242264
fn push_substate(&mut self) {
243265
let mut parent = Box::new(Substate::new());
244266
mem::swap(&mut parent, &mut self.substate);
@@ -278,6 +300,9 @@ impl<B: RuntimeBaseBackend> TransactionalBackend for OverlayedBackend<B> {
278300
for address in child.deletes {
279301
self.substate.deletes.insert(address);
280302
}
303+
for address in child.creates {
304+
self.substate.creates.insert(address);
305+
}
281306
}
282307
MergeStrategy::Revert | MergeStrategy::Discard => {}
283308
}
@@ -294,6 +319,7 @@ struct Substate {
294319
storages: BTreeMap<(H160, H256), H256>,
295320
transient_storage: BTreeMap<(H160, H256), H256>,
296321
deletes: BTreeSet<H160>,
322+
creates: BTreeSet<H160>,
297323
}
298324

299325
impl Substate {
@@ -308,6 +334,7 @@ impl Substate {
308334
storages: Default::default(),
309335
transient_storage: Default::default(),
310336
deletes: Default::default(),
337+
creates: Default::default(),
311338
}
312339
}
313340

@@ -385,4 +412,14 @@ impl Substate {
385412
false
386413
}
387414
}
415+
416+
pub fn created(&self, address: H160) -> bool {
417+
if self.creates.contains(&address) {
418+
true
419+
} else if let Some(parent) = self.parent.as_ref() {
420+
parent.created(address)
421+
} else {
422+
false
423+
}
424+
}
388425
}

src/standard/config.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ pub struct Config {
103103
pub eip_5656_enabled: bool,
104104
/// Uses EIP-1559 (Base fee is burned when this flag is enabled) [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md)
105105
pub eip_1559_enabled: bool,
106+
/// Selfdestruct deletet contract only if called in the same tx as creation [EIP-6780](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-6780.md)
107+
pub suicide_only_in_same_tx: bool,
106108
}
107109

108110
impl Config {
@@ -159,6 +161,7 @@ impl Config {
159161
eip_1153_enabled: false,
160162
eip_5656_enabled: false,
161163
eip_1559_enabled: false,
164+
suicide_only_in_same_tx: false,
162165
}
163166
}
164167

@@ -215,6 +218,7 @@ impl Config {
215218
eip_1153_enabled: false,
216219
eip_5656_enabled: false,
217220
eip_1559_enabled: false,
221+
suicide_only_in_same_tx: false,
218222
}
219223
}
220224

@@ -257,6 +261,7 @@ impl Config {
257261
eip_1153_enabled,
258262
eip_5656_enabled,
259263
eip_1559_enabled,
264+
suicide_only_in_same_tx,
260265
} = inputs;
261266

262267
// See https://eips.ethereum.org/EIPS/eip-2929
@@ -322,6 +327,7 @@ impl Config {
322327
eip_1153_enabled,
323328
eip_5656_enabled,
324329
eip_1559_enabled,
330+
suicide_only_in_same_tx,
325331
}
326332
}
327333
}
@@ -344,6 +350,7 @@ struct DerivedConfigInputs {
344350
eip_1153_enabled: bool,
345351
eip_5656_enabled: bool,
346352
eip_1559_enabled: bool,
353+
suicide_only_in_same_tx: bool,
347354
}
348355

349356
impl DerivedConfigInputs {
@@ -361,6 +368,7 @@ impl DerivedConfigInputs {
361368
eip_1153_enabled: false,
362369
eip_5656_enabled: false,
363370
eip_1559_enabled: false,
371+
suicide_only_in_same_tx: false,
364372
}
365373
}
366374

@@ -378,6 +386,7 @@ impl DerivedConfigInputs {
378386
eip_1153_enabled: false,
379387
eip_5656_enabled: false,
380388
eip_1559_enabled: true,
389+
suicide_only_in_same_tx: false,
381390
}
382391
}
383392

@@ -395,6 +404,7 @@ impl DerivedConfigInputs {
395404
eip_1153_enabled: false,
396405
eip_5656_enabled: false,
397406
eip_1559_enabled: true,
407+
suicide_only_in_same_tx: false,
398408
}
399409
}
400410

@@ -413,9 +423,9 @@ impl DerivedConfigInputs {
413423
eip_1153_enabled: false,
414424
eip_5656_enabled: false,
415425
eip_1559_enabled: true,
426+
suicide_only_in_same_tx: false,
416427
}
417428
}
418-
419429
const fn cancun() -> Self {
420430
Self {
421431
gas_storage_read_warm: 100,
@@ -428,9 +438,10 @@ impl DerivedConfigInputs {
428438
warm_coinbase_address: true,
429439
// 2 * (MAX_CODE_SIZE = `24576`) = (0xC000 = 49152) as per EIP-3860
430440
max_initcode_size: Some(0xC000),
431-
eip_1153_enabled: true,
432-
eip_5656_enabled: true,
441+
eip_1153_enabled: false,
442+
eip_5656_enabled: false,
433443
eip_1559_enabled: true,
444+
suicide_only_in_same_tx: true,
434445
}
435446
}
436447
}

src/standard/invoker/routines.rs

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ where
7575
}
7676

7777
handler.reset_storage(state.as_ref().context.address);
78+
handler.mark_create(state.as_ref().context.address);
7879

7980
resolver.resolve_create(init_code, state, handler)
8081
}

tests/contract/DeployAndDestroy.sol

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
contract DeployAndDestroy {
5+
constructor() {
6+
selfdestruct(payable(msg.sender));
7+
}
8+
}

tests/contract/SimpleContract.sol

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
contract SimpleContract {
5+
address public owner;
6+
7+
// Constructor sets the owner of the contract
8+
constructor() {
9+
owner = msg.sender;
10+
}
11+
12+
// Function to destroy the contract and send the remaining funds to the target address
13+
function destroy(address target) public {
14+
selfdestruct(payable(target));
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
6080604052348015600e575f80fd5b503373ffffffffffffffffffffffffffffffffffffffff16fffe
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
608060405234801561000f575f80fd5b50335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101948061005c5f395ff3fe608060405234801561000f575f80fd5b5060043610610033575f3560e01c8062f55d9d146100375780638da5cb5b14610053575b5f80fd5b610051600480360381019061004c919061010b565b610071565b005b61005b61008a565b6040516100689190610145565b60405180910390f35b8073ffffffffffffffffffffffffffffffffffffffff16ff5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100da826100b1565b9050919050565b6100ea816100d0565b81146100f4575f80fd5b50565b5f81359050610105816100e1565b92915050565b5f602082840312156101205761011f6100ad565b5b5f61012d848285016100f7565b91505092915050565b61013f816100d0565b82525050565b5f6020820190506101585f830184610136565b9291505056fea26469706673582212201e4165398f9671b365261ccc1129042cbcea13db557b5359b2298c51f2ab274d64736f6c63430008150033

0 commit comments

Comments
 (0)