State: selfdestruct and creation flags¶
The per-transaction account lifecycle flags behind SELFDESTRUCT
(EIP-6780) and same-transaction creation tracking.
function k_selfdestruct¶
Marks an account selfdestructed (SELFDESTRUCT; deletion is decided
at transaction end per EIP-6780).
function k_selfdestruct(a : address) -> unit = {
let cur = k_aload(a);
let active = not_bool(cur.selfdestructed);
if active then {
store_account(a, { cur with selfdestructed = true })
}
}Resolves an account through the transaction and block overlays before an authenticated witness read. A transaction-overlay hit was already touched when that row was established; misses record the EIP-7928 account touch before consulting block-scoped state.
function k_aload(a : address) -> Account = {
let tx_account = acct_tx_get(a);
if tx_account.found then {
return tx_account.account
};
bal_account_touch(a);
let block_account = acct_block_get(a);
if block_account.found then {
return block_account.account
};
let address_hash = keccak256_address(a);
let account = stateless_account_by_key(k_parent_state_root, address_hash);
acct_block_cache(a, address_hash, account);
account
}val not_bool = pure {coq: "negb", lean: "_lean_not", _: "not"}: forall ('p : Bool). bool('p) -> bool(not('p))Writes a whole-account row to the transaction overlay.
function store_account(a : address, v : Account) -> unit =
acct_tx_update(a, v)A 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)function k_is_selfdestructed¶
Whether the account is marked selfdestructed this transaction.
Resolves an account through the transaction and block overlays before an authenticated witness read. A transaction-overlay hit was already touched when that row was established; misses record the EIP-7928 account touch before consulting block-scoped state.
function k_aload(a : address) -> Account = {
let tx_account = acct_tx_get(a);
if tx_account.found then {
return tx_account.account
};
bal_account_touch(a);
let block_account = acct_block_get(a);
if block_account.found then {
return block_account.account
};
let address_hash = keccak256_address(a);
let account = stateless_account_by_key(k_parent_state_root, address_hash);
acct_block_cache(a, address_hash, account);
account
}A 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)function k_mark_created¶
Marks an account as created in this transaction (EIP-6780's same-transaction test).
function k_mark_created(a : address) -> unit = {
let cur = k_aload(a);
store_account(a, { cur with created = true })
}Resolves an account through the transaction and block overlays before an authenticated witness read. A transaction-overlay hit was already touched when that row was established; misses record the EIP-7928 account touch before consulting block-scoped state.
function k_aload(a : address) -> Account = {
let tx_account = acct_tx_get(a);
if tx_account.found then {
return tx_account.account
};
bal_account_touch(a);
let block_account = acct_block_get(a);
if block_account.found then {
return block_account.account
};
let address_hash = keccak256_address(a);
let account = stateless_account_by_key(k_parent_state_root, address_hash);
acct_block_cache(a, address_hash, account);
account
}Writes a whole-account row to the transaction overlay.
function store_account(a : address, v : Account) -> unit =
acct_tx_update(a, v)A 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)function k_was_created¶
Whether the account was created in this transaction.
Resolves an account through the transaction and block overlays before an authenticated witness read. A transaction-overlay hit was already touched when that row was established; misses record the EIP-7928 account touch before consulting block-scoped state.
function k_aload(a : address) -> Account = {
let tx_account = acct_tx_get(a);
if tx_account.found then {
return tx_account.account
};
bal_account_touch(a);
let block_account = acct_block_get(a);
if block_account.found then {
return block_account.account
};
let address_hash = keccak256_address(a);
let account = stateless_account_by_key(k_parent_state_root, address_hash);
acct_block_cache(a, address_hash, account);
account
}A 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)function k_zero_balance¶
Zeroes an account's balance (the SELFDESTRUCT sweep of a
self-beneficiary).
function k_zero_balance(a : address) -> unit = {
let cur = k_aload(a);
let balance_is_zero = word_is_zero(cur.info.balance);
if balance_is_zero then {
return ()
};
store_account_info(a, cur, { cur.info with balance = ZERO_WORD })
}Resolves an account through the transaction and block overlays before an authenticated witness read. A transaction-overlay hit was already touched when that row was established; misses record the EIP-7928 account touch before consulting block-scoped state.
function k_aload(a : address) -> Account = {
let tx_account = acct_tx_get(a);
if tx_account.found then {
return tx_account.account
};
bal_account_touch(a);
let block_account = acct_block_get(a);
if block_account.found then {
return block_account.account
};
let address_hash = keccak256_address(a);
let account = stateless_account_by_key(k_parent_state_root, address_hash);
acct_block_cache(a, address_hash, account);
account
}Applies a tuple change with minimal overlay traffic: scalar-field fast paths when existence/storage state is unchanged, and a storage clear when the tuple collapses to empty.
function store_account_info(a : address, acc : Account, info : AccountInfo) -> unit = {
let empty = account_info_empty(info);
if empty then {
storage_tx_clear(a)
};
let next = account_set_info(acc, info);
if (next.info.storage_root != acc.info.storage_root)
| (next.present != acc.present)
| (next.storage_cleared != acc.storage_cleared) then {
store_account(a, next)
} else {
if next.info.balance != acc.info.balance then {
acct_tx_set_balance(a, next.info.balance)
};
if next.info.nonce != acc.info.nonce then {
acct_tx_set_nonce(a, next.info.nonce)
};
if next.info.code_hash != acc.info.code_hash then {
acct_tx_set_code_hash(a, next.info.code_hash)
}
}
}function word_is_zero(w) = w == WORD_ZEROlet ZERO_WORD : word = word_from_bits(0x0000000000000000000000000000000000000000000000000000000000000000)A 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)