# EPF Week 2 Updates
Before this week, I mostly studied the static validation updates that will be required for [EIP-7886](https://eips.ethereum.org/EIPS/eip-7886), delayed execution.
This week, I wanted to take a closer look at the post-validation phase in a slot, from the EL's perspective, which is when the transaction execution will take place.
## Project Updates
### Execution Phase
With delayed execution, we'll be processing the tsx after the block itself has been validated, hence the decoupling of block validation and execution.
To support this decoupling, we'll modify `process_transactions` in a few ways:
```
# Take a block-level snapshot of the state before transaction execution
begin_transaction(block_env.state)
```
Taking the initial snapshot allows us to be able to revert back to this state if certain conditions are met, which we'll discuss later.
Next, we'll actually pre-charge senders for the maximum possible gas fees before executing each transaction. We do this so that we can withhold enough gas for each transaction to be able to be successful. Since it's now possible with [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) for an earlier transaction in a block to drain the balance of an account that may need that balance in a subsequent transaction.
```
# Pre-charge senders for maximum possible gas fees upfront
for tx in decoded_transactions:
deduct_max_tx_fee_from_sender_balance(block_env, tx)
```
Now, we're ready to process each transaction in the evm.
```
# Execute each transaction
for i, tx in enumerate(decoded_transactions):
process_transaction(block_env, block_output, tx, Uint(i))
# Stop processing if execution is already reverted
if block_output.execution_reverted:
break
```
If we find that while looping over the txs that a tx is cause for block reversion, no reason to waste compute looping over the rest.
The condition for block reversion is defined as follows:
```
# Validate declared gas used against actual gas used
block_output.execution_reverted = (
block_output.execution_reverted
or block_output.block_gas_used != block_env.block_gas_used
)
```
We check if the declared `gas_used` matches up with what we calculate and revert the block if it doesn't match. The reasons for this check is to ensure the builder doesn't fake the `gas_used`, for reasons like:
- builder doesn't want to include some FOCIL tsx at end of block so claims it's already full
- censoring of tsx
Additionally, when processing each transaction itself, we ensure the block output is reverted if the `gas_used` + `tx.gas` is higher than the block gas limit:
```
if block_output.block_gas_used + tx.gas > block_env.block_gas_limit:
block_output.execution_reverted = True
return
```
The fields that will be reverted are:
```
# If execution is reverted, reset all outputs and rollback the state
if block_output.execution_reverted:
rollback_transaction(block_env.state)
block_output.block_gas_used = Uint(0)
block_output.transactions_trie = Trie(secured=False, default=None)
block_output.receipts_trie = Trie(secured=False, default=None)
block_output.receipt_keys = ()
block_output.block_logs = ()
block_output.requests = []
block_output.execution_reverted = True
else:
# Commit the state if execution is valid
commit_transaction(block_env.state)
```
We must cache the `block_output` in memory for the following block's validation stage and rollback the WST to the pre-execution snapshot. Therefoe, the block is still valid, but there will be no state change.
## Week 3 TODOs
Next week, I plan to:
- Present this project at EthCC
- Gain feedback on the project from core devs
- Attend EthMagicians chat at EthCC to discuss delayed execution vs epbs
- Meet all the folks from the cohort