The general idea is that AAs support intra-transaction calls, after PAYGAS
is executed. In this case, a user with no ether would submit a candidate transaction to a relayer. The relayer would decide if it would like to pay for the transaction. If they decide yes, they would craft a transaction, wrapping the user's transaction, and submit it on-chain. The relayer's account would verify their transaction and execute the PAYGAS
opcode. Immediately after this, the relayer would call the user's account, passing in the user transaction. The user account would process the validity of the transaction. If valid, it would check to see if a PAYGAS
has already been issued, and skip over it to continue the remaining execution if so. This would allow external call from the user account to properly hydrate msg.sender
.
Imagine a user
PAYGASFROM
opcodeIntroduce a new opcode PAYGASFROM
whose arguments are gasprice
, from
, and calldata
. Once executed, the from
account will be called with the calldata to verify that it plans to pay for the execution of the transaction. Upon successful verification, it will update any replay protection mechanisms and then return control to the original entry point to continue execution.
Unlike the relayer calling into the AA, this solution shifts the validation burden to miners. For example, the relayer
A user can invalidate an arbitrary number of transactions in the current construction of the mempool by submitting some number of transactions starting at nonce msg.value
+ gasprice
* gaslimit
) and ii) affecting the validity of other transactions.
Let's modify the transaction format to have 2 new fields: payer
and payer_nonce
. This is in addition to the already existing nonce
. Now we can statically order transactions into a dependency graph. To insert a transaction into the graph, we first check to see if either of the nonces conflict with any other transactions in the mempool. If they don't, they should run the normal validation against the transaction and if it turns out to be valid, insert it into the graph. If there is a conflict, the miner will need to verify that a cycle was not introduced into the graph. This operation can be done in linear
My hypothesis is that this is the simplest form of access lists. In this instance transaction depend on each other in atomic chunks rather than via storage slots. I believe that generalizing this further will only increase the cost of checking for cycles. It's unclear if the cycle check (or a insertion heuristic) is intractable to perform on-the-fly while creating blocks.