After multiple rejected or stalled proposals to add native support for smart contract wallets (smart accounts) to Ethereum, ERC-4337 has been accepted as the (interim) standard to implement Account Abstraction (AA) without protocol level changes to the EVM. Over the last few months, there has been a surge in activity in a subset of AA which revolves around the modularization of these smart accounts to make them more easily extensible for both users and developers. This general approach is termed modular account abstraction and the following article aims to give an overview of the developments in this ecosystem over the past 3 months and where things are heading.
The following section will outline and discuss the different components of the modular AA ecosystem. These components are the account, modules, registry, UIs and developer tooling. These components may not be the only parts required to make this ecosystem function in the long term, but at least for now adequately encompass the different areas that teams are focusing their research and development efforts on.
Modular accounts are smart accounts that are easily and securely extensible by a user, as opposed to “static” accounts that can only be modified by a developer and need to be redeployed. This allows the user to switch out, add or remove functionality in their smart account on the fly.
There are currently two different approaches to modular smart accounts, those created or inspired by the Safe architecture and those inspired by the Multi-Facet Proxy (aka Diamond) Standard (ERC-2535). These two approaches have evolved differently and can be contrasted along multiple axes.
The Safe account has evolved over time from the original multisig built by Gnosis and predates ERC-4337. The team places a strong emphasis on security and extensibility, whereas ERC-4337 support is at this point in time only possible through a module. However, there are talks about implementing native support in a future version. An example of a team building a modular account inspired by the Safe architecture is Biconomy. Their recently released (and fully audited) account changes the Safe account in several ways, namely by adding native ERC-4337 support and making all accounts 1/1 multi-sigs.
The other approach is inspired by ERC-2535 and has been discussed and pursued extensively by different teams over the last several months. This standard aims to make smart contracts extensible by standardising a way of storing a reference to modules (called facets) and executing these using the delegatecall opcode. While discussion around this opportunity has been ongoing for a while, the (to our knowledge) first working implementation was built by us at ETHDenver. Since then, several other teams have released implementations at various stages, such as the ZeroDev Kernel, which is a minimal and extensible smart account that has taken some inspiration from ERC-2535. Further, the Alchemy team has written up a draft stage EIP (ERC-6900), aiming to standardise modular smart accounts with inspiration taken from ERC-2535. Soul Wallet has also experimented with an ERC-2535 account in the past, although they have since shelved these attempts (we were unable to link to any code of these attempts).
As stated above, these two different approaches can be contrasted along different axes. One of these is the usage of delegatecall to execute modules as opposed to using an external call. Using delegatecall allows the execution of external code from within the context of the calling contract, which entails that the external code can modify the storage of the calling contract and make external calls that emanate from the calling account rather than the module. This does not allow for a separation of concerns, meaning that a module can overwrite any storage slot on the account, which gives rise to a major attack vector. While the Safe account currently does allow a module to be called using delegatecall, this might change in the future, either by being removed entirely or by creating different permission levels for modules. One upside of using delegatecall to execute modules is that modules can be singletons, drastically reducing the gas cost associated with adding a module.
Another difference between these approaches is the way that modules are stored and transactions are routed. ERC-2535 uses a mapping from function selector to module address, which entails that no two active modules can share the same function name (the selector being the hash of the name and arguments). The transaction flow using this router is to look up a function signature in this mapping and call the corresponding contract address with this signature and arguments using delegatecall. The Safe account, on the other hand, only stores a reference to the module address, thus making it possible for multiple modules to use the same function selector. Further, the transaction flow can either be triggered by the Safe account or the module, which can then call into the Safe account to execute a transaction from there.
The third major difference is the way that these implementations handle storage. Because of the way that ERC-2535 calls modules, storage cannot be handled like it would in a normal smart contract. Instead, developers usually choose to use structured or “diamond” storage, which stores data to storage slots that are the hash of a unique, module-specific identifier. This means that different modules don’t overwrite each other’s stored data and cause the contract to behave in unexpected ways. While Safe modules can be called using delegatecall, they are not required to be called in that way and can therefore handle their own storage. This means that storage is not required to be structured in the aforementioned way but can be used in the regular (sequential) way that Solidity storage positioning is usually implemented or any other desired way of handling storage.
These are some of the biggest differences between the approaches, but for another evaluation on the different approaches see this article written by the Safe team.
Modules, sometimes called plugins or facets, are smart contracts that aim to extend the functionality of smart accounts. For example, a module might allow the owner to use a different signature scheme to control their wallet or to trigger a certain action every time a token is transferred to another account. Related to the different implementations of modular accounts that exist so far and have been discussed above, there are different ways of building and executing modules. Hence, the modules that exist today are either built for the Safe architecture, like these or these, or for a diamond-inspired architecture, such as for ZeroDev’s Kernel or some demo modules built by us at ETHDenver.
As explained in more detail above, how a module is structured depends on the account implementation that it is meant to be used for. One main difference is that a module built for the Safe infrastructure needs to (unless called via delegatecall) call back into the Safe account to initialize a function call from within the context of the account. By contrast, a module built for a diamond-inspired account does not need to do this since it’s code is executed from within the smart account itself. On top of this, there also exists a standard that modules built on top of the Safe architecture can use, called the Zodiac standard. The standard aims to separate different components of a modular account, termed avatars, guards and modules and thus aims to create a generalised framework for building smart account modules. Some examples of modules that use this standard can be found here.
One example of a team that is building a module for smart accounts in public is Permissive. Their focus has, so far, been to build an authorization framework for smart accounts, mostly focusing on allowing more granular access control whereby a user can give different entities concrete permissions over specific actions that are executed by the account. They have released a module for the Safe account and are working on porting this over to different modular implementations.
Many of the modular implementations of both smart contracts generally and smart accounts more specifically have so far been built with a strong trust assumption between the user and module developer. This is how ERC-2535 is almost exclusively used today, allowing developer teams to manage large and complicated codebases. However, the greater vision for the smart account ecosystem is to remove this trust assumption, allowing for 3rd party developers to build modules that non-technical users can securely add into their wallet. While the trust assumption cannot be completely removed (someone, after all, needs to attest to the security of a module), we can bundle all the trust assumptions made between individual users and module developers into a single entity, the module registry. This means that a user now only needs to trust this single entity rather than needing to trust every single developer of a module that they want to use.
While this line of thought leads to the conclusion of a centralized registry, this is far from the vision that we (rhinestone) are pursuing. Instead, we are currently prototyping a registry that is akin to a hyperstructure, meaning that it is open, unstoppable and, most importantly, permissionless. This means that different parties with different security assumptions can sit on top of this registry and it is up to the user to choose which party to trust under which circumstances. Currently, we are prototyping different implementations with helpful input and collaboration from different teams, such as Safe and members of the 4337 team at EF. Once we have more concrete details on the upsides of different implementations and incentive designs, we will start sharing these more publicly and open-sourcing the underlying code.
As previously noted by Yoav, one of the lesser-explored aspects of modular AA is a similarly modular frontend design. This is necessary because UI components need to be specifically built to trigger certain on-chain functionality by knowing function selectors, argument encodings and (potentially) what frontend or backend logic to execute. So far, we are not aware of any team making significant progress on this problem, although we are slowly starting to explore this for the reference implementation built on top of the registry discussed above. From our initial research, a secure design of a modular frontend allowing for external module developers is non-trivial.
While there exists developer tooling for dapp or wallet developers to integrate modular AA into their applications, there is very little guidelines or tooling to help developers build modules. Safe has a guide here and ZeroDev has one here but apart from these we are unaware of anything more substantial that allows developers to easily understand how to build a module. As the space matures, we imagine that more guides and actual tools will emerge, lowering the barriers to entry for module developers substantially.
Modular AA is a subset of the broader AA movement which aims to modularize smart accounts in order to make them customizable for a user and allow developers to easily build self-contained smart account features rather than needing to build an entire account. The aim of the above article is to give an extensive overview of the current state of this space as well as highlighting where progress is being made. We have also tried to include as many relevant links to progress that we are aware of, but if we left anything out, please do contact us so that we can include them. Finally, there is a Telegram group in which many of the ongoing discussions in this space are happening. Feel free to join it if you are interested in staying up to date and/or contributing. If you have any questions feel free to contact me or check out what we’re building at rhinestone.
Thanks to Kurt, ZeroKnots, Lukas and Derek for helping me with valuable feedback.