-
Notifications
You must be signed in to change notification settings - Fork 13
Smart Sessions
Smart Sessions Module is an ERC-7579 Validator Module, whose main purpose is to allow permissioned validation of ERC-4337 User Operations and ERC-1271 Signatures.
Smart Sessions Module is designed to support DApps requesting permissions from users via ERC-7715 standard flow.
The obvious use case for permissioned userOps validation is Session Keys. Smart Sessions Module allows configuring sophisticated permissions for various kinds of session keys by stacking several kinds of Submodules together.
However, the Smart Sessions Module is capable of unlocking more functionality than just session keys, i.e. subscriptions, recurring payments, ownership, and others.
Smart Sessions Module ensures additional security by allowing to check attestations from Module Registry for every Submodule involved in the configuration of a Permission.
Smart Sessions ships equipped with submodules that unlock the vast majority of existing use cases. However, if there’s no perfect match for your use case amongst pre-built submodules, feel free to build your own according to the interface specifications.
Permission consists of:
- ISessionValidator: performs signature verification. More info.
- Policies: introduce limitations (i.e. when the permission is valid and what is it allowed to do)
- ERC-4337 Policies
- ERC-1271 Policies: scope the verification of ERC-1271 signatures. More info.
PermissionId acts as a main identifier for permission. You can think of PermissionId as of username in *nix operation systems. In *nix systems every user comes with a strict set of access rules, the same applies to PermissionId’s. Permission configuration is stored per PermissionId. So every PermissionId has its own set of what it is capable of signing and executing on behalf of a given Smart Account. Different Smart Accounts can empower the same PermissionId with different permissions (sets of policies + configurations) in the same way as the same user can have different rights on different *nix machines.
Currently, PermissionId is generated by hashing the ISessionValidator submodule address, some salt, and data that is used to configure it. This data is called configuration data and it contains the information about the signer. For example, for a simple EOA ISessionValidator, the configuration data would be just the signer’s EOA address. Thus the PermissionId is in some way the derivative of the signer’s credentials. Salt is used to allow creating different PermissionId-s for the same signer's credentials.
ISessionValidator is a submodule that performs the verification of a signature issued by the signer of the ERC-4337 User Operation or ERC-1271 data.
For every PermissionId there is one and and only one ISessionValidator. However, such an ISessionValidator can be very complex. For example, there is MultiKey ISessionValidator included in the repo (attention: Multikey ISessionValidator is not audited yet), that allows configuring n of n signatures rule, where each of those signatures can be whether secp256k1 (EOA) or secp256r1 (Passkey) signature.
ISessionValidators are just algorithms. So they are stateless and they expect the configuration data for a given ISessionValidator to be provided by the multiplexer (i.e. Smart Sessions Module) that stores it.
This allows ISessionValidator submodules to be reusable across ERC-7579 ecosystem and even work as a standalone ERC-7579 module for Smart Accounts that choose to support them by storing configs in their storage.
Note: Since ISessionValidators are stateless, data is stored in the Smart Sessions storage, and Smart Sessions can not perform any check on this data when enabling the ISessionValidator as it is unaware of its logic. Thus ISessionValidators SHOULD always perform data integrity checks (for example, owner address is not address(0)).
IPolicy is a submodule that enforces restrictions on what kind of ERC-4337 UserOps or ERC-1271 data can be signed by a signer and when such signatures are valid.
The same IPolicy smart contract can be used as UserOp level policy, Action policy, and/or ERC-1271 policy, allowing for efficient code sharing: sharing the same algorithm with different interfaces.
UserOp Policies configured for a given PermissionId apply for every User Operation signed by this PermissionId.
Examples of UserOp-level policies are:
- TimeFrame Policy: applied as a UserOp-level policy, TimeFrame policy configures the validity timeframe for a given Permission
- Gas Limit Policy: limits how much gas User Operations signed by a given signer can spend in total.
- Simple Counter Policy: sets a total amount of UserOps that can be successfully validated for a Smart Account when signed by a given PermissionId's signer
Action Policies apply only if the action that is about to be executed matches any of the configured action.
Action is defined by an ActionId which is a hash of the target smart contract address and function selector.
Smart Session Module identifies all the actions that are going to be executed in an execution phase of a User Operation and applies Action Policies accordingly.
For example, if the User Operation involves batched execution of several calls, every call will be scoped separately depending on what action policies are configured for it.
Examples of Action policies are:
- Universal Action Policy: allows configuration of any arguments for any function call. For example, for an ERC-20 token transfer, receiver, maximum amount per transfer and total transfer limit per signer can be configured.
- TimeFrame Policy: applied as an Action policy, TimeFrame policy configures the timeframe when a certain action can be executed if signed by a given signer
- Simple Counter Policy: how many times given action can be executed in all the user operations signed by a signer
Fallback action policies are a special set of policies which are applied if there are no policies configured for a given actionId. This unlocks several interesting use cases, such as:
- Sudo Permissions. More info.
- Bulk actions processing
- Blacklist actions: allow everything but the actions from the list
- And others
Those policies scope the validation of ERC-1271 signatures. Smart Sessions has a powerful feature of allowing Sessions Keys to sign not only the ERC-4337 User Operations, but also
Examples of ERC-1271 policies are:
- TimeFrame Policy: sets the timeframe when a given signer’s ERC-1271 signatures can be validated
- Sender Policy: defines what protocol may request ERC-1271 signature verification for a given signer
Since isValidSignature calls are not allowed to modify the Smart Account state, the ERC-1271 Policies currently have a very limited range of limitations they can apply.
Smart Sessions module utilises ERC-7739 to allow for readable and secure hashes for ERC-1271 signatures. As per ERC-7739, some extra data is passed in the signature argument of isValidSignature method. This data includes the notation of an EIP-712 data struct that was signed. Smart Sessions module applies more rules based on this notation: allowed types of content are stored per PermissionId. If other content was signed, the validation will fail. That allows to limit the scope of what actions are allowed to be validated through ERC-1271 within the scope of a given permission. It prevents session keys from having too much power. Without this feature, any session key could have been able to sign any kinds of EIP-712 data structs, from Permit2's to off-chain orders.
There are many cases, and ERC-7715 flow is one of them, when dApp may need to enable the Permission inside the same User Operation when the Permission is leveraged. Even when this is not a must, it is still a feature that increases efficiency by packing two actions into the same User Operation, minimising the ERC-4337 gas overhead.
That’s where Smart Sessions Enable Mode comes into play. It allows including the Permission (Session) Enable object into the UserOperation.signature field. This object is used to enable the permission before validating the UserOp signed by a signer empowered by this exact Permission.
Permission Enable object contains the Session itself and the signature over the EIP-712 digest. This signature should be valid when verified via the SmartAccount.isValidSignature
method. So it should be signed by an owner of a given SA or by a user with appropriate rights to enable permissions. Note, that for security reasons it is currently not possible to validate the Smart Sessions Enable Mode signature through SmartSessions.isValidSignatureWithSender
method. Thus permissions are not able to validate adding of other permissions to Smart Session module's storage.
This signature over EIP-712 digest of a Permission Enable object will be verified, and in case the verification succeeds, the Smart Sessions module will enable the Permission before validating the User Operation signed by the signer from this Permission.
Enable mode significantly improves UX for Session Keys, by reducing the number of UserOps => reducing the cost and latency for executing actions scoped by those Sessions.
Note, that Enable Mode is not available when using permissions through isValidSignature
, for it is not allowed to modify state in ERC-1271 flow.
To further improve UX and devX, Smart Sessions Enable Mode is multichain. Imagine user comes to some dApp, for example, some AI trading agent app, for the first time. dApp need to obtain permission from user's Smart Account to perform trades even when user is offline. Imagine, those trades should happen on several DEXes on various chains. Instead of bothering user with signing N Enable objects for N chains, with Smart Sessions dApp can only request one signature over a transparent EIP-712 object including details of the sessions(s) and a list of chains. Thus, dApp can use same signature to enable permissions for user's SA on any of the signed chains. This also allows parameters permissions (sessions) to vary form chain to chain, for example some ERC-20 token transfer limits can be different for permissions enabled on different chains.
Smart Sessions Module unlocks use cases of scoped access to a Smart Account beyond Session Keys.
Some use cases such as Subscriptions involve making recurrent payments. Since the automatic execution initiated by Smart Contract itself is not possible because of EVM architecture, there’s always a party that initiates such a payment.
To ensure better UX for Smart Account owners we can not expect them to manually pay for every Subscription Period. So users can authorize the subscription provider (or even anyone) to initiate such a payment, as long as this execution is within set limitations: how much to pay and how often to do it.
Such a permission pattern can be implemented with Smart Sessions by carefully configuring policies (for example: RateLimit policy to ensure the payment is done only once per defined period of time and the Universal Action Policy to limit the amount of a stablecoin paid for every subscription period). When the execution parameters are properly scoped it is safe to use the all-approving ISessionValidator (YesSessionValidator), so anyone can trigger the payment as long as it corresponds to the rules defined above.
Sudo Permissions (ownership) can be configured via Smart Sessions by using the appropriate ISessionValidator and special policies configuration. How to configure policies for a sudo permission: set 0 userOp policies, then configure 0 actionIds, and set YesPolicy (all approving) as an only fallback policy. In this case any action will fallback to fallback policies list, which only contains all-approving Yes Policy. Thus a given signer can do anything on behalf of a Smart Account.
This pattern unlocks many opportunities, such as turning a Smart Account into a Multisig by configuring a Multisig Signer and an above pattern for policies.