ethereum.forks.amsterdam.vm.eoa_delegation
Set EOA account code.
SET_CODE_TX_MAGIC¶
| 33 | SET_CODE_TX_MAGIC = b"\x05" |
|---|
EOA_DELEGATION_MARKER¶
| 34 | EOA_DELEGATION_MARKER = b"\xef\x01\x00" |
|---|
EOA_DELEGATION_MARKER_LENGTH¶
| 35 | EOA_DELEGATION_MARKER_LENGTH = len(EOA_DELEGATION_MARKER) |
|---|
EOA_DELEGATED_CODE_LENGTH¶
| 36 | EOA_DELEGATED_CODE_LENGTH = 23 |
|---|
NULL_ADDRESS¶
| 37 | NULL_ADDRESS = hex_to_address("0x0000000000000000000000000000000000000000") |
|---|
is_valid_delegation ¶
Whether the code is a valid delegation designation.
Parameters
code: bytes
The code to check.
Returns
valid : bool
True if the code is a valid delegation designation,
False otherwise.
def is_valid_delegation(code: bytes) -> bool:
| 41 | <snip> |
|---|---|
| 56 | return ( |
| 57 | len(code) == EOA_DELEGATED_CODE_LENGTH |
| 58 | and code[:EOA_DELEGATION_MARKER_LENGTH] == EOA_DELEGATION_MARKER |
| 59 | ) |
get_delegated_code_address ¶
Get the address to which the code delegates.
Parameters
code: bytes
The code to get the address from.
Returns
address : Optional[Address]
The address of the delegated code.
def get_delegated_code_address(code: bytes) -> Optional[Address]:
| 63 | <snip> |
|---|---|
| 77 | if is_valid_delegation(code): |
| 78 | return Address(code[EOA_DELEGATION_MARKER_LENGTH:]) |
| 79 | return None |
calculate_delegation_cost ¶
Get the delegation address and the cost of access from the address.
Parameters
evm : Evm
The execution frame.
address : Address
The address to check for delegation.
Returns
delegation : Tuple[bool, Address, Uint]
The delegation address and access gas cost.
def calculate_delegation_cost(evm: Evm, address: Address) -> Tuple[bool, Address, Uint]:
| 128 | <snip> |
|---|---|
| 144 | tx_state = evm.message.tx_env.state |
| 145 | |
| 146 | code = get_code(tx_state, get_account(tx_state, address).code_hash) |
| 147 | |
| 148 | if not is_valid_delegation(code): |
| 149 | return False, address, Uint(0) |
| 150 | |
| 151 | delegated_address = Address(code[EOA_DELEGATION_MARKER_LENGTH:]) |
| 152 | |
| 153 | if delegated_address in evm.accessed_addresses: |
| 154 | delegation_gas_cost = GasCosts.WARM_ACCESS |
| 155 | else: |
| 156 | delegation_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS |
| 157 | |
| 158 | return True, delegated_address, delegation_gas_cost |
set_delegation ¶
Apply the EIP-7702 authorizations and charge their state-dependent costs at the top frame.
Each valid authorization is charged, on top of the
state-independent GasCosts.REGULAR_PER_AUTH_BASE_COST already
paid in the intrinsic cost:
StateGasCosts.NEW_ACCOUNT(state) when the authority's account leaf does not yet exist.GasCosts.ACCOUNT_WRITE(regular) when applying the authorization is the transaction's first write to the authority's leaf. Writes the transaction already prices elsewhere are exempt: the sender's, covered byTX_BASE, and, for a value-bearing transaction, the recipient's, covered byTX_VALUE_COST. Repeated authorizations on one authority pay it once.StateGasCosts.AUTH_BASE(state) when a net-new delegation indicator is written: the authority held no delegation before the transaction, none was set for it earlier in the transaction, and this authorization sets one. It is charged at most once per authority and is never credited back -- a delegation set and then cleared in the same transaction keeps its charge.
These costs depend on the authority's current state and so cannot
be charged in the intrinsic cost. Insufficient gas raises an
OutOfGasError; the caller rolls back the authorizations applied
so far and halts the top frame.
Parameters
evm : The top-level transaction frame.
def set_delegation(evm: Evm) -> None:
| 199 | <snip> |
|---|---|
| 234 | message = evm.message |
| 235 | tx_state = message.tx_env.state |
| 236 | # Accounts whose write the transaction has already priced: the |
| 237 | # sender's leaf was written at inclusion (nonce bump and fee |
| 238 | # deduction), and a value-bearing transaction prepays the |
| 239 | # recipient's balance write -- the transfer itself only happens at |
| 240 | # frame entry, after these charges. |
| 241 | written_accounts: Set[Address] = {message.tx_env.origin} |
| 242 | if evm.message.tx_env.value > U256(0): |
| 243 | written_accounts.add(evm.message.current_target) |
| 244 | # Authorities a delegation was set for earlier in this transaction. |
| 245 | delegation_set_for: Set[Address] = set() |
| 246 | for auth in message.tx_env.authorizations: |
| 247 | match validate_authorization(message, auth): |
| 248 | case None: |
| 249 | continue |
| 250 | case authority: |
| 251 | pass |
| 252 | |
| 253 | if not account_exists(tx_state, authority): |
| 254 | charge_state_gas(evm, StateGasCosts.NEW_ACCOUNT) |
| 255 | |
| 256 | if authority not in written_accounts: |
| 257 | charge_gas(evm, GasCosts.ACCOUNT_WRITE) |
| 258 | written_accounts.add(authority) |
| 259 | |
| 260 | pre_state_authority_account = get_pre_state_account( |
| 261 | tx_state, authority |
| 262 | ) |
| 263 | pre_state_authority_code = get_code( |
| 264 | tx_state, pre_state_authority_account.code_hash |
| 265 | ) |
| 266 | delegated_before_tx = is_valid_delegation(pre_state_authority_code) |
| 267 | |
| 268 | if auth.address == NULL_ADDRESS: |
| 269 | code_to_set = b"" |
| 270 | else: |
| 271 | if not delegated_before_tx and authority not in delegation_set_for: |
| 272 | charge_state_gas(evm, StateGasCosts.AUTH_BASE) |
| 273 | delegation_set_for.add(authority) |
| 274 | code_to_set = EOA_DELEGATION_MARKER + auth.address |
| 275 | |
| 276 | set_code(tx_state, authority, code_to_set) |
| 277 | increment_nonce(tx_state, authority) |