EIP-8141: Frame Transaction

You could have a transaction that only decides to pay after the execution, which may occur with SENDER frames.

1 Like

Yes you could based on the current spec, but what is the benefit of offering that flexibility - is there a specific use-case which requires “VERIFY afterwards”?

Yes, you might want to execute some assertions after the main execution ends to ensure the intended outcome occurred. You may not want to pay for the tx unless the expected outcome occurred. This can protect from unbundling attacks.

1 Like

One example is if you have a paymaster who would only sponsor if the user sends it some ERC20 tokens. However, the user may not have any tokens to begin with. But during the execution, the user can swap for the ERC20 tokens and send it to the paymaster. Then in the last VERIFY frame, the paymaster checks that it has indeed received the ERC20 tokens and therefore sponsors the transaction.

OK makes sense. How important is it to support that type of paymaster at the outset? If it is a core requirement, it would be good to outline this as one of the examples.

Pushing complexity to the mempool is one of the most off-putting things about the spec as it stands. Rather than starting with free-for-all frames and making general recommendations that nodes should consider mitigating, it would be better have clear specifications in 8141, in terms of frame order, and what can be done in a VERIFY frame and an initial deployment frame. These restrictions could then evolve over time.

I don’t feel strongly about whether these specifications should be at the protocol level or mempool rules, but @frangio has pointed out that mempool rules have the benefit of being amenable to change without a hard fork.

[Edit: Not actually a problem: the gas parameters are in the data hash used for these signatures]

[This concern was not an actual problem]

I think the transaction sender’s nonce gets incremented when APPROVE returns 0x1 or 0x2 (behavior), and nonce and the sender are both part of the input to the canonical signature hash?

1 Like

Thanks! I was wrong on my concern with EOAs. And yes, both execution approval and payer execution increment the sender’s nonce, which means that you can’t create repayable transactions.

1 Like

Why is P256 being added as a EOA account algorithm via the default code mechanism? That is significant scope creep.

4 Likes

One topic that was raised a couple of times in discussions around EIP-8141 is “Transaction Assertions”.
This EIP is a simlified example of what could be achieved within a final EIP-8141 verification frame:

1 Like

I think there has been too much focus on transaction assertions which I find clearly outside of AA scope, and it’s not doing us any favors to counter the arguments that this EIP is trying to do too much.

I’d personally put assertions aside. They are not necessary to make the case for this EIP.

2 Likes

We can still prevent unintended changes by pre-specifying the allowed positions, everything else will be reverted.

I wouldn’t say native support for P256 accounts is scope creep for a native AA proposal. If you check any of the other recent AA proposals such as Tempo Txns, 8130, 8164, 8175, etc., support for P256 is a first-class concept in all of them.

Having said that, some coauthors have expressed the concern that enabling native P256 EOAs with no clear path to migrate them to quantum-resistant accounts is a form of protocol tech debt. Therefore we are currently planning to remove the P256 part from the default account, and define a minimal, audited P256 account contract in the spec. That doesn’t get us the same benefits as a native P256 account (for example, a native P256 account would be more portable across chains than a P256 contract account), but we think with some additional EIPs such as EIP-7997 the UX of using a P256 contract account might get pretty close to that of a native account.

P256 on it’s own is a fine discussion to have, I am concerned that 8141 is becoming a kitchen sink EIP that will fall apart once one interest doesn’t get what they want.

3 Likes

I appreciate the concern. I wouldn’t say there’s any particular “interest” behind 8141; I think there are two core goals behind 8141 that are driving the recent updates:

  • Make 8141 useful for more people. That’s why we added a default account so it can work for EOA users, and why we were considering R1 accounts.
  • Make it possible for 8141 accounts to be ultra simple (ideally “just a signature check”) by taking on more complexity at the protocol layer. The attempt to add atomic batching to the spec is one such example.

Would it be better if the entire P256 part was extracted to a standalone non-headliner EIP for Hegota that requires EIP-8141?

1 Like

If EIP-8141 is going to introduce crypto-agility for EOAs, I strongly believe we should do it based on EIP-7932 (PR to do this here). It would remove some complexity from EIP-8141 and help make the PQ signature system more interoperable (e.g. with EIP-6404).

Why isn’t the base cost priced based on what it will be used for, similar to EIP-2780? If this were done, the cost would be cheaper than 15,000, thereby increasing demand for basic applications.

Excited to see the various iterations on this EIP in different PRs. Having reflected on it, I think that a few of the different mechanisms can be simplified.

There should only be two modes

Currently there are three modes - DEFAULT, VERIFY and SENDER. It would be nice if the mode is a clear concept, and the current values mix the mode and the sender of the call.

I think that this can be reduced down to two: VERIFY & EXECUTE. Where any EXECUTE that takes place before a VERIFY frame where the sender is approved has ENTRY_POINT as the caller (i.e. the current DEFAULT). All EXECUTE frames after the sender is approved have the sender as the caller.

Perhaps there is a strict need for ENTRY_POINT caller frames after sender approval - if so I want to learn more about those use-cases. Because I think simpler is better, so if we can get down to two modes that would be great. We can always add more modes in the future.

APPROVE doesn’t need scope

Currently there are three different approval scopes, and it’s all a bit complicated (pun intended, given the current efforts to provide approval bits). But in practice the right scope can generally be inferred from the frames, and I think you can tweak the behaviour to make it all a bit more intuitive.

  1. APPROVE should only be allowed in VERIFY frames - this constraint makes sense. APPROVE is equivalent to a returnstatement, and VERIFY frames are STATICCALL. You can just add a VERIFY frame after the EXECUTE frame that you care about, if you need something to happen before you APPROVE
  2. nonce incrementation & gas deduction should only happen after the last VERIFY frame of a transaction, and the payer should be tracked as a variable (read on to understand why)
  3. if the sender calls APPROVE, it approves both execution and payment (updating the payer)
  4. if a non-sender contract calls APPROVE, it can only be approving payment (updating the payer)
  5. subsequent approvals can therefore overwrite the payer, until the last VERIFY frame, when (as mentioned above) the gas is deducted etc.

This is (to my brain) reasonably easy to reason about. APPROVE calls overwrite each other until the last one. In practice I think you should only ever really see a maximum of two VERIFY frames (to the SENDER and to the PAYER). No scope operand or constraint is necessary.

Atomicity via groups

There is a PR which introduces SENDER_ATOMIC frames. This is because there are real use-cases for both atomic and non-atomic frames, i.e.

  • As an account I want all or nothing for my ERC20 approval and swap frames.
  • As an ERC20-based paymaster, I want certainty that the frame which sends me the right amount of DAI won’t revert, if the main execution reverts

If you don’t make these things possible in frames, then you will need to put custom batching in your smart account. Then you have a load of different implementations of batching in EVM code, and is that the right area for innovation (maybe but I do not think so)? If we are going to enshrine then let’s do it properly.

I don’t think we want to add a different MODE for this, and would prefer a GROUP-type approach, i.e. you put EXECUTE frames in groups which are atomic:

  • all frames have group 0 = everything executes or reverts together
    • approve | 0
    • swap | 0
  • erc20 paymaster example (three groups of calls)
    • transfer DAI to paymaster | 0
    • approve DAI to use Uniswap router | 1
    • swap DAI on Uniswap | 1
    • refund remaining DAI based on unpaid gas | 2

I think this is a bit more legible. VERIFY frames can happen in amongst EXECUTION frames but they aren’t part of groups, groups are an EXECUTION thing. Groups could be put in the upper bits of the MODE(where the approval bits are in the current spec, as I mentioned above I don’t think we need these), but I don’t feel strongly.

Honoured to be the 100th comment in this thread. Would love to hear where I have mis-thought. If these ideas are interesting I would happily open PRs.

1 Like