# Meta Transactions x Account Abstraction ## Relayer calls into AA #### Idea 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`. #### Problem Imagine a user $A$ asks a relayer $R$ to relay $N$ transactions. $R$ also creates $N$ transactions, wrapping each of $A$'s transactions. Before $R$'s transactions are mined, $A$ submits a transaction with a much higher gas price than $R$, causing it to be included before $R$'s transactions. This creates a griefing vector against $R$ since $A$ can always submit transactions to $R$ which should pay out to them, and then front run them to drain $A$. Inversely, if $A$ submits a large number of transactions and then a single transaction which is relayed by $R$ and the relayed transaction is included, it could potentially invalidate all the transactions submitted by $A$. ## `PAYGASFROM` opcode #### Idea Introduce 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. #### Problem Unlike the relayer calling into the AA, this solution shifts the validation burden to miners. For example, the relayer $R$ could give users $U_{1..N}$ a signature promising to pay for their transactions. This will fill the mempool with $N$ transactions. Then $R$ could front run the transactions and drain their account, causing all $N$ transactions to become invalid and unable to be included in the block. ## Expose two nonces #### Idea 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 $N$, and then submit a conflicting transaction with nonce $N$ that drains the account of ether. This is acceptable because the miner can quickly invalidate transactions from that account without i) rerunning them (just checking `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 $O(V+E)$ time. #### Problem 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.