This proposal defines a standard interface for intent-centric smart accounts. It enables externally owned accounts (EOAs) to delegate contract code to a smart account implementation, allowing them to sign intents. These intents can then be executed by solvers (or relayers) on behalf of the account owner, streamlining interactions and expanding the capabilities of EOAs.
Account Abstraction (AA) is a highly discussed topic in the blockchain industry, as it enhances the programmability of accounts, enabling features such as:
The introduction of ERC-4337 established a permissionless standard for AA, unlocking a wide range of powerful features. However, ERC-4337 has several limitations:
UserOperation transactions consumes a high amount of gas.ERC-7521 introduced a smart contract account (SCA) solution with an intent-centric design. It allows solvers to fulfill account owners' intents while maintaining flexibility for custom execution logic and ensuring forward compatibility.
With the introduction of SET_CODE_TX_TYPE=0x04, EOAs can now set contract code dynamically, granting them programmability similar to SCAs. This presents an opportunity to develop a new standard that extends AA capabilities to EOAs while addressing the aforementioned challenges.
By simplifying execution, improving efficiency, and enhancing user experience, this proposal aims to accelerate the adoption of intent-centric account abstraction smart contracts.
In an intent-centric system, solvers play a crucial role in fulfilling user intents and are rewarded accordingly. This proposal introduces an open execution model, where any solver can participate, fostering a competitive environment that benefits users.
With integrated gas abstraction, solvers can cover gas fees using native tokens while receiving other tokens from the EOA account as compensation. Additionally, solvers can further optimize costs by bundling multiple intent executions into a single blockchain transaction.
Each solver is free to develop its own strategies for maximizing profitability. This proposal does not impose restrictions on how solvers execute intents, ensuring flexibility and adaptability in diverse execution scenarios.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
UserIntent schemaEach intent is a packed data structure containing sufficient information about the operations the account owner wants to execute. The core structure of a UserIntent object is as follows:
| Field | Type | Description |
|---|---|---|
sender | address | The address of the account initiating the intent. |
standard | address | The IStandard implementation responsible for validating and parsing the UserIntent |
header | bytes | Metadata associated with the UserIntent, interpreted by standard. Stored as bytes for flexibility. |
instructions | bytes[] | The execution details of the UserIntent, interpreted by standard. Stored as bytes[] to allow flexibility. |
signatures | bytes[] | Validatable signatures required for execution, interpreted by standard. |
header: The bytes header can carry information about how to validate the intent or how to prevent
double-spending. For example, header can contain an uint256 nonce to check if the nonce is used already.instructions: These bytes instructions can just be concatenated (address,value,calldata) or can be
standardized values, for example (erc20TokenAddress,1000) means the instructions can use up to 1000 of the
specified ERC-20 token. It is NOT REQUIRED that all instructions MUST be provided by the EOA owner to allow dynamically carry out other operations during intent executions, but the IStandard design needs to carefully handle this case.signatures: The bytes signatures field can support different signing methods. It is NOT REQUIRED that
all signatures MUST be provided by the EOA owner, some of them MAY be provided by solver, relayer or anyone else.UserIntent as BytesThe UserIntent object is packed and encoded into bytes calldata userIntent. There is no strict schema requirement for the data structure. Each IAccount and IStandard implementation can define its own encoding and decoding methods for handling the bytes data.
Here is an example of packed-encoded format:
| Section | Value Type | Description |
|---|---|---|
| userIntent[0:20] | address | sender |
| userIntent[20:40] | address | standard |
| userIntent[40:42] | uint16 | Length of header |
| userIntent[42:44] | uint16 | Length of instructions |
| userIntent[44:46] | uint16 | Length of signatures |
Next headerLength bytes | bytes | The actual header data |
Next instructionsLength bytes | bytes | The actual instructions data |
Next signatureLength bytes | bytes | The actual signatures data |
| Remaining bytes | bytes | Extra data, such as nested intents for further execution |
IStandard InterfaceEach standard defines how to parse and validate a UserIntent. Implementations of standard must conform to the IStandard interface:
The IStandard interface is responsible for defining and enforcing the validation logic for UserIntent objects.
It operates similarly to the EntryPoint in ERC-4337 and ERC-7521.
The extensibility of bytes4 return types allows future upgrades without modifying the function signatures.
IAccount InterfaceOn the account side, IAccount provides the interface for executing bytes calldata intent:
Using SET_CODE_TX_TYPE=0x04, EOAs can delegate contract code to an IAccount implementation, enabling them to function as smart accounts. A single account implementation can be shared across multiple EOAs, meaning:
IAccount implementation.It is RECOMMENDED that each account leverages IStandard to validate and unpack operations, check Reference
Implementation for examples. Account smart contract can be stateless to avoid sharing storage space with other delegated contracts.
Defining UserIntent object as a struct would improve readability and make it easier to work with in Solidity. For example:
However, this approach has several drawbacks:
IAccount and IStandard implementations to follow this specific struct format reduces flexibility.bytes[] introduces additional gas costs due to Solidity's dynamic array encoding.Since all objects within the UserIntent structure are optional and their usage depends on IStandard and IAccount implementations, the bytes format ensures maximum flexibility while preserving compatibility.
With SET_CODE_TX_TYPE=0x04, EOAs gain the ability to execute contract code. Executing transactions directly from an EOA provides several key benefits:
msg.sender Behavior: Since the execution originates from an EOA, msg.sender always resolves to the EOA address, simplifying authentication and permission checks.IAccount implementation to avoid storing persistent data, reducing storage costs.If an EOA does not require smart contract execution, or if executing an intent is too expensive, the owner can still use the account as a regular EOA without any modifications.
Validation logic often relies on contract state. For example, a weighted multi-owner signature scheme needs to track the weight assigned to each signer. Keeping intent validation entirely within IStandard offers multiple advantages:
EntryPoint concept from ERC-4337 but in a simpler form, IStandard focuses solely on validation.IStandard is responsible only for validation, it becomes easier for contract engineers to implement, audit, and maintain.IStandard interface is inherently modular, allowing for more complex validation mechanisms. For instance, a "compound" standard could decompose an intent into smaller components, validate each separately, and then combine the results.This design enables gasless transactions by allowing any address to initiate a transaction on behalf of the intent's sender.
header or instructions.tx.origin (the address submitting the transaction).This proposal does not enforce built-in re-entry protection mechanisms such as nonces. The rationale behind this decision is that certain intents are inherently designed to be executed multiple times.
Instead of a global re-entry protection mechanism, each standard should define its own protection rules based on its intended use case. Implementers are encouraged to:
This IAccount standard shares the same backwards compatibility considerations as the introduction of EOA contract code execution (SET_CODE_TX_TYPE=0x04).
This PackedIntent is a library to decode (address sender, address standard, uint16 headerLength, uint16 instructionsLength, uint16 signaturesLength) from a packed encoded intent. The following IAccount and IStandrd implementations both follow PackedIntent schema.
This RelayedExecutionStandard allows relayer to execute the operations on chain and take ERC-20 token from the intent sender, thus achieve a gas-less experience for the sender.
The following IAccount implementation uses a StandardRegistry to maintain allowlist of standards and just batch execute
all operations returned from IStandard.unpackOperations.
As shown above, the implementation of IAccount is stateless and simple, so that it can be compatible with different IStandard.
While the IStandard implementation is complex because it needs to define its own schema. But both contracts will be public
and audited, to ensure the security of intent execution.
The security of this standard primarily depends on the implementation of both IStandard and IAccount. Each component must ensure that user intents are validated and executed safely. Additionally, solvers are responsible for securing their own execution environments to prevent unintended exploits.
To ensure security and maintain ecosystem integrity, it is critical that both the standard (IStandard) and account (IAccount) implementations are:
If an IAccount implementation maintains state (instead of being stateless), it could:
Strongly RECOMMEND stateless execution to prevent storage conflicts.
Copyright and related rights waived via CC0.