ethereum.forks.bpo5.vm.eoa_delegationethereum.forks.amsterdam.vm.eoa_delegation

Set EOA account code.

SET_CODE_TX_MAGIC

30
SET_CODE_TX_MAGIC = b"\x05"

EOA_DELEGATION_MARKER

31
EOA_DELEGATION_MARKER = b"\xef\x01\x00"

EOA_DELEGATION_MARKER_LENGTH

32
EOA_DELEGATION_MARKER_LENGTH = len(EOA_DELEGATION_MARKER)

EOA_DELEGATED_CODE_LENGTH

33
EOA_DELEGATED_CODE_LENGTH = 23

REFUND_AUTH_PER_EXISTING_ACCOUNT

32
REFUND_AUTH_PER_EXISTING_ACCOUNT = 12500

NULL_ADDRESS

34
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:
38
    <snip>
53
    return (
54
        len(code) == EOA_DELEGATED_CODE_LENGTH
55
        and code[:EOA_DELEGATION_MARKER_LENGTH] == EOA_DELEGATION_MARKER
56
    )

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]:
60
    <snip>
74
    if is_valid_delegation(code):
75
        return Address(code[EOA_DELEGATION_MARKER_LENGTH:])
76
    return None

recover_authority

Recover the authority address from the authorization.

Parameters

authorization The authorization to recover the authority from.

Raises

InvalidSignatureError If the signature is invalid.

Returns

authority : Address The recovered authority address.

def recover_authority(authorization: Authorization) -> Address:
80
    <snip>
99
    y_parity, r, s = authorization.y_parity, authorization.r, authorization.s
100
    if y_parity not in (0, 1):
101
        raise InvalidSignatureError("Invalid y_parity in authorization")
102
    if U256(0) >= r or r >= SECP256K1N:
103
        raise InvalidSignatureError("Invalid r value in authorization")
104
    if U256(0) >= s or s > SECP256K1N // U256(2):
105
        raise InvalidSignatureError("Invalid s value in authorization")
106
107
    signing_hash = keccak256(
108
        SET_CODE_TX_MAGIC
109
        + rlp.encode(
110
            (
111
                authorization.chain_id,
112
                authorization.address,
113
                authorization.nonce,
114
            )
115
        )
116
    )
117
118
    public_key = secp256k1_recover(r, s, U256(y_parity), signing_hash)
119
    return Address(keccak256(public_key)[12:32])

access_delegation

Get the delegation address, code, and the cost of access from the address.

Parameters

evm : Evm The execution frame. address : Address The address to get the delegation from.

Returns

delegation : Tuple[bool, Address, Bytes, Uint] The delegation address, code, and access gas cost.

def access_delegation(evm: Evm, ​​address: Address) -> Tuple[bool, Address, Bytes, Uint]:
124
    <snip>
140
    tx_state = evm.message.tx_env.state
141
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
142
    if not is_valid_delegation(code):
143
        return False, address, code, Uint(0)
144
145
    address = Address(code[EOA_DELEGATION_MARKER_LENGTH:])
146
    if address in evm.accessed_addresses:
147
        access_gas_cost = GasCosts.WARM_ACCESS
148
    else:
149
        evm.accessed_addresses.add(address)
150
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
151
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
152
153
    return True, address, code, access_gas_cost

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]:
125
    <snip>
141
    tx_state = evm.message.tx_env.state
142
143
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
144
145
    if not is_valid_delegation(code):
146
        return False, address, Uint(0)
147
148
    delegated_address = Address(code[EOA_DELEGATION_MARKER_LENGTH:])
149
150
    if delegated_address in evm.accessed_addresses:
151
        delegation_gas_cost = GasCosts.WARM_ACCESS
152
    else:
153
        delegation_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
154
155
    return True, delegated_address, delegation_gas_cost

validate_authorization

Check if the given Authorization is valid against the current state.

Returns the authority address or address and its Account, or None if the validation was if the unsuccessful.validation was unsuccessful.

def validate_authorization(message: Message, ​​auth: Authorization) -> None | AddressTuple[Address, Account]:
161
    <snip>
167
    tx_state = message.tx_env.state
168
169
    if auth.chain_id not in (message.block_env.chain_id, U256(0)):
170
        return None
171
172
    if auth.nonce >= U64.MAX_VALUE:
173
        return None
174
175
    try:
176
        authority = recover_authority(auth)
177
    except InvalidSignatureError:
178
        return None
179
180
    message.accessed_addresses.add(authority)
181
182
    authority_account = get_account(tx_state, authority)
183
    authority_code = get_code(tx_state, authority_account.code_hash)
184
185
    if authority_code and not is_valid_delegation(authority_code):
186
        return None
187
188
    authority_nonce = authority_account.nonce
189
    if authority_nonce != auth.nonce:
190
        return None
191
190
    return authority
192
    return (authority, authority_account)

set_delegation

Set the delegation code for the authorities in the message.

Refills StateGasCosts.NEW_ACCOUNT when the authority's account leaf already exists, and StateGasCosts.AUTH_BASE when its code slot already holds a delegation indicator. The total is returned so block accounting can subtract it from tx_state_gas.

Parameters

message : Transaction specific items.

Returns

refund_counter: state_refund : U256Uint Refund from authority which already exists in state.Total state gas refunded across all processed authorizations.

def set_delegation(message: Message) -> U256Uint:
196
    <snip>
215
    tx_state = message.tx_env.state
209
    refund_counter = U256(0)
216
    state_refund = Uint(0)
217
    for auth in message.tx_env.authorizations:
218
        match validate_authorization(message, auth):
219
            case None:
220
                continue
214
            case authority:
221
            case (authority, authority_account):
222
                pass
223
224
        if account_exists(tx_state, authority):
218
            refund_counter += U256(
219
                GasCosts.AUTH_PER_EMPTY_ACCOUNT
220
                - REFUND_AUTH_PER_EXISTING_ACCOUNT
221
            )
225
            refund = StateGasCosts.NEW_ACCOUNT
226
            message.state_gas_reservoir += refund
227
            state_refund += refund
228
229
        # No new delegation indicator bytes are written: either the
230
        # authority already has one (overwrite in place / clear) or
231
        # this auth clears against an authority with no prior code.
232
        if (
233
            authority_account.code_hash != EMPTY_CODE_HASH
234
            or auth.address == NULL_ADDRESS
235
        ):
236
            refund = StateGasCosts.AUTH_BASE
237
            message.state_gas_reservoir += refund
238
            state_refund += refund
239
240
        if auth.address == NULL_ADDRESS:
241
            code_to_set = b""
242
        else:
243
            code_to_set = EOA_DELEGATION_MARKER + auth.address
244
245
        set_code(tx_state, authority, code_to_set)
228
246
        increment_nonce(tx_state, authority)
247
248
    if message.code_address is None:
249
        raise InvalidBlock("Invalid type 4 transaction: no target")
250
251
    message.code = get_code(
235
        tx_state, get_account(tx_state, message.code_address).code_hash
252
        tx_state,
253
        get_account(tx_state, message.code_address).code_hash,
254
    )
255
238
    return refund_counter
256
    return state_refund