AccountAbstraction for simple MobileApps - MIP-22

The goal: create a SC through which users can interact without owning a seedphrase, using passkeys/other built-in methods from Android/IOS phones. By doing that, we can create a mobile app SDK for any type of application, which would be connected seamlessly to the blockchain.

Account abstraction is the key word to use - and we start first with passkeys, after we will try to bring in privacy as well in an upcoming solution.

Ethereum specs: ERC-4337: Account Abstraction Using Alt Mempool

A few things out of this paper are already resolved at the protocol (gasless, relayed transactions), we have subscription contracts as well. In terms of user security Guardians provide that for seedphrases, but here we have a new set of users who use the phone passkeys. As we look into the security of passkeys in new smartphones, we could say that they are kept in a safe place and they can/are used for everyday financial operations.

What are the goals?

  • Achieve the key goal of account abstraction: allow users to use smart contract wallets in which signature verification is via passkeys
  • Decentralization
    • Allow any relayer to participate in the process of including account-abstracted user operations
    • Avoid trust assumptions on relayers
  • Try to support other use cases
    • Atomic multi-operations
    • Pay tx fees with ESDT, or Subscription by the user.
    • Relayer will verify before putting a userOperation to execution, whether they are paid or not, if the SC would do it and it would fail, the relayer would pay for the gas.

What do we need to have account abstraction:

  1. A smart contract wallet for each shard. Multiple users inside one SC and/or one SC per user.
  2. A 3rd party to send and pay for transactions
  3. A flexible way for the user to pay the 3rd party
  4. An interface to show user assets
  5. Social recovery - web3auth - this creates and EOA - this is nice
  6. Key rotation

Deploy a SC for multiple addresses and allow deposits of any tokens for addresses

Anyone can deploy the multiAA contract with passkeys.

The first endpoints we need are:

  1. registerUser@userAddress@signature - signature will sign the message “registerUser@userAddress@SCAddress@0” being the first nonce. SCAddress is the deployed multiAA contract, this represents the signed intent of the user to register himself to this contract. “Address” should be the public key for the given passkey of the user.
  2. depositForUser@userAddress - this can be called by anyone and will deposit different ESDT tokens into for the user.
  3. The contract saves a bigger structure for each of its users. Nonce is quite important as every userOp will contain a nonce and it must be verified against current nonce, as in mainnet.

Allow arbitrary execution

Once the user deploys its own SC (or a service deploys for a user), we can expand the base SC (which contains the subscription service) with a few new endpoints where atomic multi operations can happen by the user. The transaction will be posted by a relayer, the execution happens from the SC, signature verification for the user will happen on the SC. The multiOperation might contain a payment towards the relayer as well. We need different types of execution like async and syncronous execution modes.

  1. multiActionForUser@userAddress@list<action, nonce, signature> - the nonce must be increasing, and the first nonce must be equal with the current Nonce from the user.

    a. The signature for an action should be hash<action, currentSCAddress, nonce> so that users which register in multiple contracts are not vulnerable to replays

  2. multiActionForMultiUsers@List<userAddress, Llist<action, nonce, signature>> - this bundles together multiple users and actions.

Definition of action:

An action can have multiple execution steps, not only one, in that case all the execution steps are done or none of them, meaning atomic multi operations.

An action can have multiTransfer and execution towards contracts, in case of MultiTransfer we have to see if the userAddress actually owns those tokens or not (inside this SC) before executing this.

In order to consume less gas, relayer payments can be done inside this SC, meaning one step in the action is payment towards the relayer, which is only an internal balance transfer of the given ESDT. Inside the SC funds are moved from userAddress to relayerAddress.

  1. Withdraw - relayer calls this to withdraw all the funds sent to him inside the multiAA contract.
  2. User can withdraw funds from multiAA account to his own account by signing an ACTION which will do this actually.

Manage my finance - special actions which require no signature

In order for a user to enjoy maximum security, he likes to keep the access to finances in a ledger, but it would be awesome to have a set of functions which can be done from another wallet. These set of functions are claimRewards from staking/delegation contracts, reDelegateRewards, farming and more. The user with the ledger would deploy the SC, and set up another account which is allowed to take certain actions. Each action and allowance has to be clearly defined.

Going further with the definition from above:

  1. whiteList@address@WellDefinedActions(tokens, addresses, limits)@noVerification
  2. takeAction@action@noSig - can be done by whitelisted address only.

Payment masters - relayers, bots for finances, subscription to be paid

As the base SC contains subscriptions by default, relayers or bots can take out tokens if the user made a subscription to them, plus we can register every action the bots made for the user.

So in the base SC we add a new structure - botActions - it contains the address of the bot + the number of transactions the bot made for the user. The user can set up how much X tokens he is willing to pay for the bot per transaction.

  1. Using the generalization from point 2 we can add something more to the takeAction endpoint.

    a. takeAction@action@paymetForRelayer@signature: in this case the relayer defines the payment and how much he wants to get paid, the user has to sign the full message (action@paymentForRelayer) and this is verified at the SC level
    b. once verified, the payment is transferred to the relayer through a transferESDT function first and action is taken after it.

  2. In order to enhance the contract we make endpoints of depositForPaymentMaster endpoints which can be called by any address.


Users could sign and save multiple intents in the SC and have anyone to execute them.

  1. saveIntents@userAddress, List<intents, nonce, signature>> - check nonce, signatures, save intents, anyone can execute later the intents.
  2. multiUserSaveIntents@list<userAddress, List<intents, nonce, signature>> - check nonce, signatures, save intents, anyone can execute later the intents.
  3. executeIntent@userAddress@intentID - execute intent with asyncCall / asyncCallBack - if the execution was correct, delete intent, if not, keep it in storage.

One very important thing to mention: doing a transaction through a smart contract is not the same than doing one directly from a wallet, because other smart contracts can require callers to not be a smart contract.

The solution is to create an account abstraction contract factory on each shard, which deploys the AA SCs. Thus, third party smart contracts that want to be called only by wallets can use the following pseudo-code condition: is_not_smart_contract(caller_address) || owner(caller_address) == ACCOUNT_ABSTRACTION_FACTORY

1 Like