I also STRONGLY think frames should include a value.
I think this was a part of one PR I have seen, though I don’t know it was removed.
One of the advantages that frame transactions have over traditional 7702 wallets, is that it makes it clear in auth only situation what the transaction is having the wallet execute. This is great because it provides a standardized view of what’s happening, which is incredibly useful for wallets and explorers.
Value is also needed when using pure EOA signature handling modes.
I believe the EIP coauthors are supportive of enabling accounts to use SENDER frames to transfer value without implementing their own execute() function, though there are a few different ways to achieve that. Adding a value field is the most obvious approach, but there was also a different idea where we allow SENDER frames to do DELEGATECALL (possibly toggled via a bit flag), and then we define a precompile that implements an execute() function that supports value transfer and atomic batching. So now an account can just DELEGATECALL the precompile for execution.
Note that if we go with the DELEGATECALL + precompile approach, we’d presumably remove the atomic batching flag since then it’d be redundant.
I’m curious to hear if people in this thread would prefer the value + atomic flag approach, or the DELEGATECALL + precompile approach?
When evaluating our learnings from Safe we came to the conclusion that we would like to remove DELEGATECALLs completely, therefore we tend to just add the `value` field (with the atomic flag). Not having DELEGATECALL makes formal verification easier and provides stronger security guarantess.
Actually accessing return data of a frame might not be a good idea I was thinking about it in the context of handling modules. My optimistic approach would be that account contract actually only holds logic for signature verification, the rest would be done via SENDER frames. But if do this and remove DELEGATECALLs then some of the more complex module flows become harder/ impossible to cover. Ultimately this is a tradeoff where we will most likely not get having some “execute” method on the account contract.
Having value in the SENDER frame means that frame transactions can provide a clean separation between what you want the transaction to do (which frames would standardize for AA), and the authorization and payment for that transaction.
Removing value forces frames to be only dumb message pipes to smart contracts. This is bad because this:
Kills the “drop in transaction upgrade” nature of frames that would make for the easiest initial adoption.
Requires that wallets build full featured smart contract wallets for even the least adoption.
Removes the tooling and ecosystem benefits that comes from having the transaction actions default to defined and visible in the frame.
Now that we are leaning more towards having frames support atomic batching, minimizing the need for an execute loop in wallets, I think it makes sense to support value in the frame. The reason for hesitation is that value only makes sense in the SENDER frame. We were hoping for frames to be totally generic across modes and not have a mismatch of usable fields, but it may be unavoidable. The DELEGATECALL approach could replace the need for value because you could delegatecall into a standardized contract to handle your execution.
Not sure if this has been noted, but VERIFY frames are implicitly capped at 2 per transaction.
Every VERIFY must call APPROVE, there are only two approval flags (sender_approved, payer_approved), and each can only be set once. So you either have 1 VERIFY with APPROVE(0x3) or 2 VERIFYs splitting APPROVE(0x1) and APPROVE(0x2). A third VERIFY would have no valid scope left and would fail to APPROVE, invalidating the tx.
Might be worth stating this explicitly in the Constraints section as a static check it’s the kind of thing an implementer could easily miss when reading the spec.
Relatedly, access to frame returndata would enable using it as input in multi-step flows without requiring wrapper contracts, which is desirable in many cases (similar to the motivation behind ERC-8211).
Has native support been considered, e.g. via FRAMERETURNDATASIZE and FRAMERETURNDATACOPY, with per-byte gas cost and a cap per frame?