Starknet Account Abstraction Model - Part 2

In this post, a follow-up to post #1 on account abstraction, we’ll continue to explore the fee abstraction and extended validation as part of the account abstraction protocol. Please refer to the first post to better understand the context, goals, and general direction of account abstraction.

As before, feedback on these ideas is more than welcome.

Fee Abstraction

Another goal of abstracting the account mechanism is to allow better UX and flexibility in how network users pay for transaction execution. This can be either by paying with a non-native token and/or allowing application developers to sponsor fees for their users or other innovative models.

To enable this, we follow EIP 4337’s line and allow the transaction to specify a specific contract - a paymaster. This contract will be asked by the sequencer to vouch for the transaction before it is executed, and OS will collect the fee from the paymaster. The OS takes care to collect the fee and allow the paymaster to run again after the transaction execution - a post-operation hook. This allows the paymaster to hook before and after the transaction is executed. It also allows the sequencer to be compensated safely, as before:

paymaster flow

(larger view)

The exact logic of whether to approve a transaction by the paymaster is part of the paymaster implementation and can take many forms. For example, a paymaster that allows accounts to pay in a different token may first lock some token from the requesting account and pay in the native token. In the later “post-op” hook, the paymaster can collect the necessary amount from the amount previously locked (actually refunding what wasn’t used).

A transaction designates the paymaster to use and potentially additional data used by the paymaster validation and payment operations. During validation, the sequencer and OS need to validate that the paymaster has enough funds in the native token to pay for the transaction.

Note that using a paymaster and/or contract can be controlled by different implementations.
Specifically:

  1. An account contract implementation may limit the paymaster it is working with
  2. A paymaster may limit the account contract he’s willing to work with (limit the accounts it pays for).
  3. A sequencer can also limit the paymasters it is willing to serve.

To prevent abuse by paymasters, or abuse of paymasters, we will need to have some way to verify that paymasters are honest. A simple first mechanism would be to have the sequencer approve (“whitelist”) the paymaster it is willing to work with. Additionally, we may have a more robust mechanism where problematic paymasters, either buggy or malicious, are automatically limited in the number of transactions they can serve in a given time frame, e.g., dynamically throttling transactions to such paymaster contracts.

A paymaster will have a validate function similar to the account contract’s validate function. In addition, it will have a postExecute function that will be called after the execution of the transaction; it will receive arguments that will reflect the status of the transaction’s execution as well as how many resources were used/fee collected.

Extra Validation

Given that paymaster contracts are somehow audited or otherwise maintain some stake or reputation, we can use them to enable use cases where extra validation is needed. For example, validating a transaction by an extra party (a social wallet) or running through some kind of fraud detection that might stop problematic transactions automatically.

Such a validating paymaster will run its validate function, and it will also require that the asking account contract has the necessary funds to refund the paymaster. The execution will then go through, and the paymaster will be reimbursed in the postExecute function, essentially not paying for the transaction, only validating it, unless it’s also a paying paymaster.

10 Likes

This seems to be an extra step of validation for me. I am bit confused now that there seems to be 3 validations happens 1) validation when user submit transactions 2) after sequencer picks up the transaction from pool, it asks Account contract for validation 3) finally validation by paymaster. What am I missing here? Is there a sequence diagram that combines the 2 diagrams?

Thanks!

It’s actually two validations: one happens when the transactions are added to the pool.
The other happens when a transaction is added to the block.

The validation when added to the block may be implemented by two contracts - the account contract and the paymaster. Of course, these will probably not validate the same thing.

2 Likes

Can an account contract act as a paymaster?
I guess I didn’t understand the concept correctly, but why is there need for a separate paymaster role? Why can’t the account contract decide how it gathers the fees and then just forwards the fees to the next step (OS?) for the gas costs.

Technically, an account contract can serve as a paymaster, but that would be odd.

The idea is to enable other scenarios where the actual payment isn’t done directly from the account.
For example, paying by a different token, w/o the need for the account to maintain the native token.
Another example might be an application subsidizing its users (partially or fully).

Does this answer the question?

Hmm, I guess the point is that the account contract wouldn’t need to have code for handling the payment in any specific way. It could take a contract address as input and delegate payment to that contract, for example. Then OS asks that contract for the fees and reverts if it doesn’t get the fees. (Of course various other validations need to take place also.) Different paymasters could be used for different transactions - for example ServiceA’s paymaster could be used when transacting with ServiceA, where ServiceA has promised to subsidize user fees. But, nothing stops using the same account contract also as paymaster.

Is this more along the lines of what you have thought? If yes, then yes you did answer my question, thanks :slight_smile:

Yes, that would be one example.

The general idea is to enable this kind of flexibility in payment models.