This is the first of two posts describing account abstraction. You can find the second post here.
As of the Muir Glacier hard-fork, out of Ethereum's two kinds of accountsβexternally owned accounts (EOAs, like your MetaMask wallet) and smart contractsβonly EOAs may pay gas fees for transactions. Lifting that restriction and allowing custom validity logic is, at an extremely high level, Account Abstraction (AA).
In this article, we want to give a brief and understandable explanation of EIP-2938, our proposal to bring AA to Ethereum.
The best way to explore AA is to see what you can build with it! So without further ado, here's a 2-of-2 multisig wallet that pays for its own transactions:
This is a rough sketch of how AA support could look in solidity, based on our early prototypes (available in the playground).
EIP-2938 is a specification for one flavor of AA, designed to be fairly simple to implement while allowing new and more powerful features to be developed in the future.
The EIP contains three consensus critical changes:
[nonce, target, data]
, where target
is the AA contract's address. Note the omission of to
, gas_price
, gas_limit
, and signature fields. Transactions of this type set tx.origin
to 0xffff...ff
; a special address known as the AA entry point.NONCE
opcode (tx.nonce
in solidity) that pushes the transaction's nonce field.PAYGAS
opcode which:
PAYGAS
cannot be undone by subsequent code.1
, but exists for future compatibility with, for example, EIP-1559.When the existing transaction pool logic is combined with AA's arbitrary transaction validity a new[1] type of attack on the Ethereum network is possible: a single transaction included in a mined block can invalidate a large number of previously valid pending transactions. Under a sustained attack, nodes would waste significant computation validating, propagating, then discarding these transactions. The EIP introduces a number of transaction pool restrictions to mitigate this attack, bringing the risk to a level comparable to non-AA transactions.
First, nodes will not accept AA transactions with nonces higher than the currently valid nonce. If multiple transactions arrive with the same nonce, only the highest paying transaction will be kept. When the currently valid nonce for an AA contract changes (i.e. upon receipt of a new block with a transaction for that contract), nodes will drop the pending transaction for that contract, if one exists.
Second, the EIP proposes a standard bytecode prefix for AA contracts. For non-AA invocations (i.e. msg.sender != 0xffff...ff
) the prefix emits a log of msg.sender
and msg.value
. For AA invocations, the prefix passes execution to the main contract. Nodes will drop any AA transactions targeting a contract which doesn't begin with this standard prefix. Over time, more prefixes can be added (without a hard fork) to allow further functionality.
Finally, encountering any of the following conditions before PAYGAS
will cause the node to immediately drop the transaction:
BLOCKHASH
, COINBASE
, β¦);BALANCE
of any account, including the target itself;EXTCODEHASH
, β¦);These restrictions ensure that the only state accessible to the validity logic is state internal to the AA contract, and that this state can only be modified by the contract itself. Therefore, a pending transaction to an AA contract may only be invalidated by a block containing another transaction targeting the same contract.
Furthermore, these restrictions give nodes assurances regarding AA transaction validity similar to those that non-AA transactions already have. As these are not consensus changes, miners are free to include transactions in a block that break these rules.
If you've been following AA over the last couple years, you might have some expectations. Sorry to disappoint, but here's some of what you won't be getting with EIP-2938:
DELEGATECALL
: Requires EIP-2937 for the same reason.msg.sender
and/or tx.origin
is way out of scope.Using the same 2-of-2 multisig contract introduced earlier, this section walks through how an AA transaction is different than a traditional transaction.
Most of structure of an AA transaction is up to the contract itself (besides the mandatory fields). To create a simple transfer transaction for our multisig, first we collect the function arguments:
Then we compute the keccak hash and sign it with both owner keys to give the full calldata:
Finally, the calldata is inserted into the transaction envelope (the mandatory fields mentioned above):
Note the difference in envelope fields from a traditional transaction; specifically:
target
instead of to
.Instead, for the multisig contract, these fields are conveyed in the calldata and handled by the contract itself! Other contracts could use entirely different fields.
When a traditional transaction arrives at a node, it is checked for validity. The same is true for AA transactions, though the checks are different.
When processing incoming traditional transactions, nodes check that:
When processing incoming AA transactions, however, nodes check that:
PAYGAS
before reaching the validation gas limit,PAYGAS
, andPAYGAS
.When the block arrives containing the AA transaction, any other pending transactions for the same account are dropped. This is different from traditional transactions, which get revalidated and possibly broadcast upon receipt of a new block.
Time to celebrate! You made it through the explainer. You're not done yet though. EIP-2938 is still rather short on feedback. If you have any questions or suggestions please leave a comment! You can also find us on the Ethereum R&D Discord in the #account-abstraction
channel.
Are you a smart contract or dApp developer interested in AA? Drop by the Ethereum R&D Discord (#account-abstraction
), we'd love to hear about your use case!
What implementation challenges stand in the way of this EIP? Are you afraid AA will collapse the network? We're pretty sure it won't, but we'd be happy to talk about it!
Quilt has built an AA playground on top of Geth, but it's a little out of sync with the EIP. Let us know how you'd like to try it, and we can update it!
This is the first of two posts describing account abstraction. You can find the second post here.
This isn't strictly a novel attack, but it is significantly more problematic with AA contracts. For a more in-depth discussion, see DoS Vectors in Account Abstraction (AA) or Validation Generalization, a Case Study in Geth. β©οΈ
Quilt has done some limited research into how contracts can combine multiple transactions into one bundle transaction. β©οΈ