Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement EIP-6780 (new SELFDESTRUCT) #1327

Merged
Merged
Show file tree
Hide file tree
Changes from 2 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
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)
hratoanina marked this conversation as resolved.
Show resolved Hide resolved
%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
%%maybe_insert_selfdestruct_list_loop:
hratoanina marked this conversation as resolved.
Show resolved Hide resolved
%stack (i, nb_created_contracts, addr) -> (i, nb_created_contracts, i, nb_created_contracts, addr)
EQ %jumpi(%%contract_not_created)
// 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)
// stack: i, nb_created_contracts, addr
%increment
%jump(%%maybe_insert_selfdestruct_list_loop)
%%contract_just_created:
// stack: i, nb_created_contracts, addr
%pop3
PUSH 1
// stack: 1
%jump(%%after)
%%contract_not_created:
// 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,
}
}
}
Loading