Skip to content

Commit

Permalink
Implement EIP-6780 (new SELFDESTRUCT) (#1327)
Browse files Browse the repository at this point in the history
* Implement EIP-6780 (new SELFDESTRUCT)

* Fix balance transfer logic

* Apply comment
  • Loading branch information
hratoanina authored Nov 7, 2023
1 parent a67c057 commit 1d8a841
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 22 deletions.
19 changes: 18 additions & 1 deletion evm/src/cpu/kernel/asm/core/create_contract_account.asm
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@

%%add_account:
// stack: existing_balance, address
DUP2 %journal_add_account_created
DUP2 PUSH 1
// stack: is_contract, address, existing_balance, addr
%journal_add_account_created
// stack: existing_balance, addr
DUP2
%append_created_contracts
%%do_insert:
// stack: new_acct_value, address
// Write the new account's data to MPT data, and get a pointer to it.
Expand Down Expand Up @@ -60,3 +65,15 @@
%%end:
// stack: status
%endmacro

%macro append_created_contracts
// stack: address
%mload_global_metadata(@GLOBAL_METADATA_CREATED_CONTRACTS_LEN)
// stack: nb_created_contracts, address
SWAP1 DUP2
// stack: nb_created_contracts, address, nb_created_contracts
%mstore_kernel(@SEGMENT_CREATED_CONTRACTS)
// stack: nb_created_contracts
%increment
%mstore_global_metadata(@GLOBAL_METADATA_CREATED_CONTRACTS_LEN)
%endmacro
8 changes: 6 additions & 2 deletions evm/src/cpu/kernel/asm/core/selfdestruct_list.asm
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
%endmacro

/// Remove one occurrence of the address from the list.
/// Panics if the address is not in the list.
/// No effect if the address is not in the list.
global remove_selfdestruct_list:
// stack: addr, retdest
%mload_global_metadata(@GLOBAL_METADATA_SELFDESTRUCT_LIST_LEN)
// stack: len, addr, retdest
PUSH 0
remove_selfdestruct_list_loop:
%stack (i, len, addr, retdest) -> (i, len, i, len, addr, retdest)
EQ %jumpi(panic)
EQ %jumpi(remove_selfdestruct_not_found)
// stack: i, len, addr, retdest
DUP1 %mload_kernel(@SEGMENT_SELFDESTRUCT_LIST)
// stack: loaded_addr, i, len, addr, retdest
Expand All @@ -40,6 +40,10 @@ remove_selfdestruct_list_found:
SWAP1
%mstore_kernel(@SEGMENT_SELFDESTRUCT_LIST) // Store the last address at the position of the removed address.
JUMP
remove_selfdestruct_not_found:
// stack: i, len, addr, retdest
%pop3
JUMP

global delete_all_selfdestructed_addresses:
// stack: retdest
Expand Down
74 changes: 63 additions & 11 deletions evm/src/cpu/kernel/asm/core/terminate.asm
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,6 @@ global sys_selfdestruct:
%charge_gas
%stack (kexit_info, balance, address, recipient) -> (balance, address, recipient, kexit_info)

// Insert address into the selfdestruct set.
// stack: balance, address, recipient, kexit_info
DUP2 %insert_selfdestruct_list

// Set the balance of the address to 0.
// stack: balance, address, recipient, kexit_info
PUSH 0
Expand All @@ -95,14 +91,17 @@ global sys_selfdestruct:
// stack: balance_ptr, 0, balance, address, recipient, kexit_info
%mstore_trie_data

%stack (balance, address, recipient, kexit_info) ->
(address, recipient, address, recipient, balance, kexit_info)

// If the recipient is the same as the address, then we're done.
// Otherwise, send the balance to the recipient.
// stack: address, recipient, address, recipient, balance, kexit_info
EQ %jumpi(sys_selfdestruct_journal_add)
%stack (address, recipient, balance, kexit_info) -> (recipient, balance, address, recipient, balance, kexit_info)
// EIP-6780: insert address into the selfdestruct set only if contract has been created
// during the current transaction.
// stack: balance, address, recipient, kexit_info
DUP2 %contract_just_created
// stack: is_just_created, balance, address, recipient, kexit_info
%jumpi(sys_selfdestruct_just_created)

// Send the balance to the recipient.
%stack (balance, address, recipient, kexit_info) ->
(recipient, balance, address, recipient, balance, kexit_info)
%add_eth

sys_selfdestruct_journal_add:
Expand All @@ -115,6 +114,21 @@ sys_selfdestruct_journal_add:
PUSH 1 // success
%jump(terminate_common)

sys_selfdestruct_just_created:
// Send funds to beneficiary only if the recipient isn't the same as the address.
%stack (balance, address, recipient, kexit_info) -> (address, recipient, balance, address, recipient, balance, kexit_info)
EQ ISZERO
// stack: address ≠ recipient, balance, address, recipient, balance, kexit_info
MUL
// stack: maybe_balance, address, recipient, balance, kexit_info
DUP3
// stack: recipient, maybe_balance, address, recipient, balance, kexit_info
%add_eth
// stack: address, recipient, balance, kexit_info
DUP1
%insert_selfdestruct_list
%jump(sys_selfdestruct_journal_add)

global sys_revert:
// stack: kexit_info, offset, size
%stack (kexit_info, offset, size) -> (offset, size, kexit_info, offset, size)
Expand Down Expand Up @@ -209,3 +223,41 @@ global terminate_common:

// stack: parent_pc, success, leftover_gas
JUMP




// Returns 1 if the address is present in SEGMENT_CREATED_CONTRACTS, meaning that it has been
// created during this transaction. Returns 0 otherwise.
// Pre stack: addr
// Post stack: is_just_created
%macro contract_just_created
// stack: addr
%mload_global_metadata(@GLOBAL_METADATA_CREATED_CONTRACTS_LEN)
// stack: nb_created_contracts, addr
PUSH 0
%%contract_just_created_loop:
%stack (i, nb_created_contracts, addr) -> (i, nb_created_contracts, i, nb_created_contracts, addr)
EQ %jumpi(%%contract_just_created_false)
// stack: i, nb_created_contracts, addr
DUP1 %mload_kernel(@SEGMENT_CREATED_CONTRACTS)
// stack: addr_created_contract, i, nb_created_contracts, addr
DUP4
// stack: addr, addr_created_contract, i, nb_created_contracts, addr
EQ %jumpi(%%contract_just_created_true)
// stack: i, nb_created_contracts, addr
%increment
%jump(%%contract_just_created_loop)
%%contract_just_created_true:
// stack: i, nb_created_contracts, addr
%pop3
PUSH 1
// stack: 1
%jump(%%after)
%%contract_just_created_false:
// stack: i, nb_created_contracts, addr
%pop3
PUSH 0
// stack: 0
%%after:
%endmacro
4 changes: 3 additions & 1 deletion evm/src/cpu/kernel/asm/core/transfer.asm
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ global add_eth_new_account:
POP
// stack: addr, amount, retdest
DUP2 ISZERO %jumpi(add_eth_new_account_zero)
DUP1 %journal_add_account_created
DUP1 PUSH 0
// stack: is_eoa, addr, addr, amount, retdest
%journal_add_account_created
%get_trie_data_size // pointer to new account we're about to create
// stack: new_account_ptr, addr, amount, retdest
SWAP2
Expand Down
18 changes: 14 additions & 4 deletions evm/src/cpu/kernel/asm/journal/account_created.asm
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
// struct AccountCreated { address }
// struct AccountCreated { account_type, address }
// account_type is 0 for an EOA, 1 for a contract.

%macro journal_add_account_created
%journal_add_1(@JOURNAL_ENTRY_ACCOUNT_CREATED)
%journal_add_2(@JOURNAL_ENTRY_ACCOUNT_CREATED)
%endmacro

global revert_account_created:
// stack: entry_type, ptr, retdest
POP
%journal_load_1
// stack: address, retdest
%journal_load_2
// stack: account_type, address, retdest
%jumpi(decrement_created_contracts_len)

revert_account_finish:
%delete_account
JUMP

decrement_created_contracts_len:
%mload_global_metadata(@GLOBAL_METADATA_CREATED_CONTRACTS_LEN)
%decrement
%mstore_global_metadata(@GLOBAL_METADATA_CREATED_CONTRACTS_LEN)
%jump(revert_account_finish)
8 changes: 6 additions & 2 deletions evm/src/cpu/kernel/constants/global_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,19 @@ pub(crate) enum GlobalMetadata {
ContractCreation = 38,
IsPrecompileFromEoa = 39,
CallStackDepth = 40,
/// Transaction logs list length
/// Transaction logs list length.
LogsLen = 41,
LogsDataLen = 42,
LogsPayloadLen = 43,
TxnNumberBefore = 44,
TxnNumberAfter = 45,
BlockBlobBaseFee = 46,
/// Number of created contracts during the current transaction.
CreatedContractsLen = 47,
}

impl GlobalMetadata {
pub(crate) const COUNT: usize = 47;
pub(crate) const COUNT: usize = 48;

pub(crate) fn all() -> [Self; Self::COUNT] {
[
Expand Down Expand Up @@ -140,6 +142,7 @@ impl GlobalMetadata {
Self::TxnNumberBefore,
Self::TxnNumberAfter,
Self::BlockBlobBaseFee,
Self::CreatedContractsLen,
]
}

Expand Down Expand Up @@ -193,6 +196,7 @@ impl GlobalMetadata {
Self::TxnNumberBefore => "GLOBAL_METADATA_TXN_NUMBER_BEFORE",
Self::TxnNumberAfter => "GLOBAL_METADATA_TXN_NUMBER_AFTER",
Self::BlockBlobBaseFee => "GLOBAL_METADATA_BLOCK_BLOB_BASE_FEE",
Self::CreatedContractsLen => "GLOBAL_METADATA_CREATED_CONTRACTS_LEN",
}
}
}
7 changes: 6 additions & 1 deletion evm/src/memory/segments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,12 @@ pub enum Segment {
ContextCheckpoints = 35,
/// List of 256 previous block hashes.
BlockHashes = 36,
/// List of contracts which have been created during the current transaction.
CreatedContracts = 37,
}

impl Segment {
pub(crate) const COUNT: usize = 37;
pub(crate) const COUNT: usize = 38;

pub(crate) fn all() -> [Self; Self::COUNT] {
[
Expand Down Expand Up @@ -114,6 +116,7 @@ impl Segment {
Self::TouchedAddresses,
Self::ContextCheckpoints,
Self::BlockHashes,
Self::CreatedContracts,
]
}

Expand Down Expand Up @@ -157,6 +160,7 @@ impl Segment {
Segment::TouchedAddresses => "SEGMENT_TOUCHED_ADDRESSES",
Segment::ContextCheckpoints => "SEGMENT_CONTEXT_CHECKPOINTS",
Segment::BlockHashes => "SEGMENT_BLOCK_HASHES",
Segment::CreatedContracts => "SEGMENT_CREATED_CONTRACTS",
}
}

Expand Down Expand Up @@ -200,6 +204,7 @@ impl Segment {
Segment::TouchedAddresses => 256,
Segment::ContextCheckpoints => 256,
Segment::BlockHashes => 256,
Segment::CreatedContracts => 256,
}
}
}

0 comments on commit 1d8a841

Please sign in to comment.