State: account code¶
Account code operations over the content-addressed code store, including EIP-7702 delegation designators.
function k_code_key¶
The account's code hash — the code-store key.
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)The common digest type used by trie, code, and block hashes.
type hash = b256function k_get_codehash¶
EXTCODEHASH (EIP-1052): a truly non-existent account reads as 0,
not KECCAK_EMPTY.
function k_get_codehash(a : address) -> hash = {
let acc = k_aload(a);
let missing = not_bool(acc.present);
if missing then {
ZERO_HASH
} else {
acc.info.code_hash
}
}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))let ZERO_HASH : hash = hash_from_bits(0x0000000000000000000000000000000000000000000000000000000000000000)A 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)The common digest type used by trie, code, and block hashes.
type hash = b256function k_deploy_code¶
Deploys code to an account: analyzes, stores, and binds its hash.
function k_deploy_code(a : address, code : CodeSlice) -> unit = {
let execution_profile = k_execution_profile;
let profile = execution_profile.protocol;
let cur = k_aload(a);
let h : hash = code_db_insert(code, profile.fork);
store_account_info(a, cur, { cur.info with code_hash = h })
}Analyzes and stores code, returning its content hash.
function code_db_insert(code : CodeSlice, fork : Fork) -> hash = {
let jumpdest_table = analyze_code(code, fork);
let analyzed = analyzed_code(code, jumpdest_table);
code_db_store(analyzed)
}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)
}
}
}The active protocol policy and all gas limits derived from the executing header, selected together while decoding the stateless input.
register k_execution_profile : ExecutionProfile = DEFAULT_EXECUTION_PROFILEA source-backed executable byte span. Its length carries the separate representation invariant needed by program-counter arithmetic; this is not a protocol deployment-size limit.
type CodeSlice = {
'off 'len,
code_region_valid_range('off, 'len) & code_valid_length('len).
CodeRegionSliceFields('off, 'len)
}A 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)The common digest type used by trie, code, and block hashes.
type hash = b256function k_set_delegation¶
Installs an EIP-7702 delegation designator
(0xef0100 ‖ target) as the account's code.
function k_set_delegation(a : address, target : address) -> unit = {
let cur = k_aload(a);
let execution_profile = k_execution_profile;
let code_region = code_region_from_delegation(target);
let code = validated_code_slice(code_region);
let h : hash = code_db_insert(code, execution_profile.protocol.fork);
store_account_info(a, cur, { cur.info with code_hash = h })
}Analyzes and stores code, returning its content hash.
function code_db_insert(code : CodeSlice, fork : Fork) -> hash = {
let jumpdest_table = analyze_code(code, fork);
let analyzed = analyzed_code(code, jumpdest_table);
code_db_store(analyzed)
}Materializes an EIP-7702 delegation designator in the executable-code arena so it follows the ordinary analysis and content-addressing path.
val code_region_from_delegation = impure { c: "code_region_from_delegation" } : address -> CodeRegionSliceResolves 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)
}
}
}Converts a source span whose producer guarantees executable cursor headroom. The explicit check re-establishes the proof after the length has crossed a non-dependent host boundary.
function validated_code_slice(bytes : CodeRegionSlice) -> CodeSlice =
if bytes.len <= sizeof(code_region_bound) - 32 then {
code_slice(bytes)
} else {
assert(false, "executable code cursor headroom");
code_slice(EMPTY_CODE_REGION_SLICE)
}The active protocol policy and all gas limits derived from the executing header, selected together while decoding the stateless input.
register k_execution_profile : ExecutionProfile = DEFAULT_EXECUTION_PROFILEA 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)The common digest type used by trie, code, and block hashes.
type hash = b256function k_clear_code¶
Resets an account's code to empty (EIP-7702 clearing).
function k_clear_code(a : address) -> unit = {
let cur = k_aload(a);
store_account_info(a, cur, { cur.info with code_hash = KECCAK_EMPTY })
}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)
}
}
}keccak256 of the empty string: the codeHash of every codeless
account.
let KECCAK_EMPTY : hash = hash_from_bits(0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470)A 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)function k_deleg_target¶
The delegation target of an account's code, with a validity flag — false when the code is not a designator.
function k_deleg_target(a : address) -> (bool, address) = {
let h : hash = k_code_key(a);
let r : AddressResult = code_db_read_delegation(h);
(r.success, r.address)
}Reads a stored delegation designator: the leading bit of the 168-bit result flags a well-formed designator and carries the delegate address.
val code_db_read_delegation = impure { c: "code_db_read_delegation" } : hash -> AddressResultThe account's code hash — the code-store key.
function k_code_key(a : address) -> hash = k_aload(a).info.code_hashA host address operation's success flag and address result.
struct AddressResult = {
success : bool,
address : address,
}A 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)The common digest type used by trie, code, and block hashes.
type hash = b256function k_get_code_size¶
EXTCODESIZE: the account's code length in bytes.
function k_get_code_size(a : address) -> code_length = {
let code_key = k_code_key(a);
let code = code_db_resolve(code_key);
code.len
}The code for a code hash; KECCAK_EMPTY resolves to empty code, and
an unwitnessed hash is a deficient witness.
function code_db_resolve(code_hash : hash) -> Code =
if code_hash == KECCAK_EMPTY then {
EMPTY_CODE
} else {
let code = code_db_lookup(code_hash);
if code.len == 0 then {
fatal_error(WitnessDeficient)
} else {
code
}
}The account's code hash — the code-store key.
function k_code_key(a : address) -> hash = k_aload(a).info.code_hashA 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)A contract-code length.
type code_length = range(0, code_region_bound)function k_code_copy¶
EXTCODECOPY: copies account code into frame memory, zero-padded
past the end.
function k_code_copy(a : address, dst : memory_base, off : word, len : memory_length) -> unit = {
let code_key = k_code_key(a);
let code = code_db_resolve(code_key);
let bytes = code_bytes(code);
slice_copy_word_offset(bytes, dst, off, len)
}function code_bytes(code) = struct { bytes = code.bytes, len = code.len }The code for a code hash; KECCAK_EMPTY resolves to empty code, and
an unwitnessed hash is a deficient witness.
function code_db_resolve(code_hash : hash) -> Code =
if code_hash == KECCAK_EMPTY then {
EMPTY_CODE
} else {
let code = code_db_lookup(code_hash);
if code.len == 0 then {
fatal_error(WitnessDeficient)
} else {
code
}
}The account's code hash — the code-store key.
function k_code_key(a : address) -> hash = k_aload(a).info.code_hashA 20-byte account address (YP §4.1), in canonical protocol byte order.
type address = vector(20, inc, byte)An absolute byte position in the shared EVM-memory arena.
type memory_base = range(0, memory_region_bound)A materialized length or allocation size in the EVM-memory arena.
type memory_length = range(0, memory_region_bound)The EVM 256-bit machine word (YP §9.1). A transparent range keeps the mathematical subtype relation visible: narrower non-negative ranges can be passed as words without a model-level conversion.
type word = range(0, 2 ^ 256 - 1)