Skip to content

feat(spec-tests): Add EIP-7778 tests with multiple refund types#2074

Merged
marioevz merged 2 commits intoethereum:eips/amsterdam/eip-7778from
gurukamath:eip-7778/multiple-refund-types-in-tx
Jan 26, 2026
Merged

feat(spec-tests): Add EIP-7778 tests with multiple refund types#2074
marioevz merged 2 commits intoethereum:eips/amsterdam/eip-7778from
gurukamath:eip-7778/multiple-refund-types-in-tx

Conversation

@gurukamath
Copy link
Contributor

🗒️ Description

This PR does 2 things

  1. Refactor the refund transaction building mechanism into its own helper function so each test doesn't have to build the refund_tx from scratch
  2. Add a test that has multiple refund types within a single transaction

🔗 Related Issues or PRs

#1874

✅ Checklist

  • All: Ran fast tox checks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:
    uvx tox -e static
  • All: PR title adheres to the repo standard - it will be used as the squash commit message and should start type(scope):.
  • All: Considered updating the online docs in the ./docs/ directory.

Cute Animal Picture

Cute Animals - 7 of 12

@codecov
Copy link

codecov bot commented Jan 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.14%. Comparing base (e958b62) to head (8bd5daf).
⚠️ Report is 99 commits behind head on eips/amsterdam/eip-7778.

Additional details and impacted files
@@                     Coverage Diff                     @@
##           eips/amsterdam/eip-7778    #2074      +/-   ##
===========================================================
- Coverage                    86.33%   86.14%   -0.20%     
===========================================================
  Files                          538      599      +61     
  Lines                        34557    39475    +4918     
  Branches                      3222     3780     +558     
===========================================================
+ Hits                         29835    34005    +4170     
- Misses                        4148     4848     +700     
- Partials                       574      622      +48     
Flag Coverage Δ
unittests 86.14% <ø> (-0.20%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Collaborator

@LouisTsai-Csie LouisTsai-Csie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this refactor! It is incredible. But it seems there is some issue with the changelog changes.

btw, I noticed some dotted lines in the codebase, but linting passes without issues. Not sure whether we’re missing some configuration or if this warning should simply be disabled, probably the latter.

Image

@gurukamath gurukamath force-pushed the eip-7778/multiple-refund-types-in-tx branch from fdc3e8d to 1d28b79 Compare January 26, 2026 12:46
Copy link
Member

@marioevz marioevz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some small cosmetic comments, thanks!

else:
post[contract_address] = Account(
storage=dict.fromkeys(storage_slots, 0),
for refund_type in refund_types:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand this for loop here because we only pass a single refund type each time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If one wants to build a refund transaction that has multiple type of refunds within a single transaction. I could pass something like refund_types = {STORAGE_CLEAR, AUTHORIZATION_EXISTING_AUTHORITY} to have both refund types in a single transaction. (or any combination of refund types once there are more than just those 2)

Comment on lines 91 to 111
authorization_list = None
if count_auth_tuples:
authorization_list = [
AuthorizationTuple(
address=contract_address,
nonce=0,
signer=pre.fund_eoa(amount=1),
)
assert effective_refund > 0, (
f"effective_refund ({effective_refund}) must be greater than 0"
)
gas_used_post_refund = gas_used_pre_refund - effective_refund

refund_tx_gas_used = gas_used_pre_refund
refund_tx_gas_spent = gas_used_post_refund

refund_tx = Transaction(
to=contract_address,
gas_limit=refund_tx_gas_used,
sender=refund_tx_sender,
authorization_list=authorization_list,
expected_receipt={
"gas_used": refund_tx_gas_used,
"gas_spent": refund_tx_gas_spent,
},
)
refund_tx_gas_price = refund_tx.max_fee_per_gas
for _ in range(count_auth_tuples)
]

gas_used_pre_refund = intrinsic_cost_calc(
calldata=call_data,
return_cost_deducted_prior_execution=True,
authorization_list_or_count=authorization_list,
) + code.gas_cost(fork)

# Calculate refund (still applied to user's balance)
refund_counter = gsc.R_AUTHORIZATION_EXISTING_AUTHORITY * count_auth_tuples
if not refund_tx_reverts:
refund_counter += code.refund(fork)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps all of this logic could sandwich the match-case logic like so:

authorization_list = None
refund_counter = 0
match refund_type:
    case RefundTypes.STORAGE_CLEAR:
        for slot in storage_slots:
            code += Op.SSTORE(
                slot,
                Op.PUSH0,
                # Gas accounting
                original_value=1,
                new_value=0,
            )
        empty_storage_on_success = True

    case RefundTypes.AUTHORIZATION_EXISTING_AUTHORITY:
        code += Op.PUSH0
        authorization_list = [
            AuthorizationTuple(
                address=contract_address,
                nonce=0,
                signer=pre.fund_eoa(amount=1),
            )
            for _ in range(refunds_count)
        ]
        refund_counter += gsc.R_AUTHORIZATION_EXISTING_AUTHORITY * refunds_count

    case _:
        raise ValueError(
            f"Unknown refund type: {refund_type} (Test needs update)"
        )
if not refund_tx_reverts:
  refund_counter += code.refund(fork)

Just to not have side-effects disjointed from the code that produces them I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. You are right. I went with this approach because we won't have the delegated_contract for creating the auth_tuples until we have the full code and have pre_deployed the contract with that code.

However, as I think more about this, the delegated contract does not necessarily have to be the same as the contract called by the transaction. So I can just deploy a dummy delegated contract and use that for the auth tuples. I have updated with this approach

@gurukamath gurukamath force-pushed the eip-7778/multiple-refund-types-in-tx branch from 1d28b79 to 8bd5daf Compare January 26, 2026 18:17
@gurukamath
Copy link
Contributor Author

@marioevz @LouisTsai-Csie Have rebased the PR on top of the changes introduced in #2073

@marioevz marioevz merged commit b60e498 into ethereum:eips/amsterdam/eip-7778 Jan 26, 2026
17 of 18 checks passed
github-actions bot pushed a commit that referenced this pull request Jan 26, 2026
* chore(tests): refactor refund transaction build

* feat(tests): eip-7778 tests for multiple refund types
marioevz pushed a commit that referenced this pull request Jan 29, 2026
* chore(tests): refactor refund transaction build

* feat(tests): eip-7778 tests for multiple refund types
fselmo pushed a commit that referenced this pull request Feb 3, 2026
* chore(tests): refactor refund transaction build

* feat(tests): eip-7778 tests for multiple refund types
spencer-tb pushed a commit that referenced this pull request Feb 11, 2026
* chore(tests): refactor refund transaction build

* feat(tests): eip-7778 tests for multiple refund types
fselmo pushed a commit to fselmo/execution-specs that referenced this pull request Feb 12, 2026
…reum#2074)

* chore(tests): refactor refund transaction build

* feat(tests): eip-7778 tests for multiple refund types
fselmo pushed a commit that referenced this pull request Feb 12, 2026
* chore(tests): refactor refund transaction build

* feat(tests): eip-7778 tests for multiple refund types
fselmo pushed a commit that referenced this pull request Feb 13, 2026
* chore(tests): refactor refund transaction build

* feat(tests): eip-7778 tests for multiple refund types
gurukamath added a commit that referenced this pull request Feb 24, 2026
* chore(tests): refactor refund transaction build

* feat(tests): eip-7778 tests for multiple refund types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants