diff --git a/README.md b/README.md index bee0a5f..d20f0e5 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ You may find more information about the IIP Process in [IIP-1](./iips/IIP-0001/i | 5 | [Move View Functions](iips/IIP-0005/iip-0005.md) | A standardized interface for application-specific queries to on-chain state | Standards | Interface | Draft | | 7 | [Validator Scoring Mechanism](iips/IIP-0007/IIP-0007.md) | An automated and standardized system for monitoring validator behavior and scores | Standards | Core | Draft | | 8 | [Dynamic Minimum Commission based on the Validator's Voting Power per Epoch](iips/IIP-0008/IIP-0008.md) | A dynamic minimum validator commission rate set to the validator's voting power percentage to prevent stake hoarding and promote decentralization | Standards | Core | Draft | +| 9 | [Abstract IOTA Accounts](iips/IIP-0009/IIP-0009.md) | Abstract accounts on IOTA enable smart-contract-based authentication of addresses. | Standards | Core | Draft | ## Need help? diff --git a/iips/IIP-0009/fig-1-ownership.svg b/iips/IIP-0009/fig-1-ownership.svg new file mode 100644 index 0000000..e6e3544 --- /dev/null +++ b/iips/IIP-0009/fig-1-ownership.svg @@ -0,0 +1,4 @@ + + + +
          Transaction
 

Sender:

Inputs:

Commands:

Signature:
0xfff
Keypair




Externally Owned Account



EOA Ownership 
owns
IotaAddress: 0xfff
Object



Coin
IOTA
User
holds
derives
ed25519_pub_key
ed25519_priv_key
signature
0x123
transfer()
creates
id: 0x123
Abstracted IOTA Account





AI Account Ownership 
owns
IotaAddress: 0xabc
Object



Coin
IOTA
          Transaction
 

Sender:

Inputs:

Commands:

Signature:
User
auth(inputs)
0x123
transfer()
id: 0x123
Object



AI Account
id: 0xabc
derives
authenticate()
dynamic link
method
call
0xabc
\ No newline at end of file diff --git a/iips/IIP-0009/fig-2-transactions.svg b/iips/IIP-0009/fig-2-transactions.svg new file mode 100644 index 0000000..a6c1d5d --- /dev/null +++ b/iips/IIP-0009/fig-2-transactions.svg @@ -0,0 +1,4 @@ + + + +
       TransactionData 

Sender:

Inputs:

Commands:

Gas:
0xfff
Keypair




EOA Transaction 
User
holds
ed25519_pub_key
ed25519_priv_key
0x456
0x123
transfer()
GenericSignature

signature
TxHash
creates
Validator
TxHash
verify
       TransactionData 

Sender:

Inputs:

Commands:

Gas:
0xabc
Authentication
mechanism
AI Account Transaction 
User
holds
0x111
0x123
transfer()
GenericSignature

MoveAuthenticator(inputs)
TxHash
creates
Validator
TxHash
MoveVM



authenticate()
verify
\ No newline at end of file diff --git a/iips/IIP-0009/fig-3-ai-auth-example.svg b/iips/IIP-0009/fig-3-ai-auth-example.svg new file mode 100644 index 0000000..9eaf0e1 --- /dev/null +++ b/iips/IIP-0009/fig-3-ai-auth-example.svg @@ -0,0 +1,4 @@ + + + +
Abstracted IOTA Account













AI Account Authenticator        
IotaAddress: 0xabc
User
Object



Custom Account
id: 0xabc
Custom Authenticator Package
0x789::custom_auth:: CustomAccount
+ dynamic_field[AuthenticatorFunctionRefKey]: AuthenticatorFunctionRef
+ auth_helpers: vec<Object>
+ authenticate(input1:CustomAccount,input2:Type1,input3:vec<u8>)
          TransactionData 

  Sender:

  Inputs:

  Commands:

  Gas:
0xabc
0x456
0x123
transfer()
GenericSignature

MoveAuthenticator(vec<CallArg>)
dynamic
field
Authenticator
FunctionRef
id: 0xabc
\ No newline at end of file diff --git a/iips/IIP-0009/fig-4-authenticator-function-ref.svg b/iips/IIP-0009/fig-4-authenticator-function-ref.svg new file mode 100644 index 0000000..a120995 --- /dev/null +++ b/iips/IIP-0009/fig-4-authenticator-function-ref.svg @@ -0,0 +1,4 @@ + + + +
Abstracted IOTA Account













Authenticator Function Ref        
IotaAddress: 0xabc
Object



Custom Account
id: 0xabc
Custom Authenticator Package
0x789::custom_auth:: CustomAccount
+ dynamic_field[Authenticatr...Key]: AuthenticatorFunctionRef
+ auth_helpers: vec<Object>
+ authenticate(input1:CustomAccount,input2:Type1,
input3:vec<u8>
)

dynamic
field
Authenticator
FunctionRef
0x2::package_metadata:: PackageMetadata
+ storage_id: ID, + runtime_id: ID, + package_version: u64
+ modules_metadata: VecMap<String, ModuleMetadata>
authenticator_metadata(self:&ModuleMetadata,
function_name:&String): &AuthenticatorMetadata
0x2::authenticator_function:: AuthenticatorFunctionRef
+ package: ID, + module_name: String, + function_name: String
create_auth_function_ref<Account: key>(package_metadata: &PackageMetadatamodule_name: Stringfunction_name: String):
AuthenticatorFunctionRef<Account> 
\ No newline at end of file diff --git a/iips/IIP-0009/iip-0009.md b/iips/IIP-0009/iip-0009.md new file mode 100644 index 0000000..65c6548 --- /dev/null +++ b/iips/IIP-0009/iip-0009.md @@ -0,0 +1,254 @@ +--- +iip: 9 +title: Abstract IOTA Accounts +description: Abstract accounts on IOTA enable smart-contract-based authentication of addresses. +author: Mirko Zichichi (@miker83z) , Valerii Reutov (@valeriyr) , Levente Pap (@lzpap) , +discussions-to: https://github.com/iotaledger/IIPs/discussions/35 +status: Draft +type: Standards Track +layer: Core +created: 2026-02-11 +requires: IIP-0010 +--- + +## Abstract + +This proposal defines a new account type for the IOTA protocol: the Abstract IOTA (AI) Account. An AI Account features a stable on-chain identifier and programmable authentication logic, enabling smart-contract-based verification in place of traditional private key signatures. + +From the perspective of decentralized applications (dApps) and their users, AI Accounts function identically to traditional Externally Owned Accounts (EOAs). The primary objective is to enable flexible authentication mechanisms while ensuring compatibility with existing infrastructure and maintaining consistent behavior at the protocol level. + +## Motivation + +The primary aim of this proposal is to significantly improve user experience throughout the IOTA ecosystem by supporting a diverse range of account authentication methods. This initiative enables extensible user authentication while preserving the integrity of the base protocol and ensuring that backward compatibility is not compromised. Under this model, accounts can operate and authenticate without relying on private keys, instead utilizing external inputs or executable code. + +Authentication paradigms enabled by this proposal include, but are not limited to: + +- Arbitrary cryptographic authentication +- Two-factor authentication (2FA) +- Dynamic multi-signature schemes +- Key rotation and recovery options +- Redundant signing methods +- DAO governance and treasury management +- Developer team or admin accounts for secure contract management + +## Specification + +This section presents the technical specification for implementing an Account Abstraction model within the IOTA protocol. The Abstract IOTA (AI) Account is a new account type designed to support flexible, programmable authentication while maintaining full compatibility with existing protocol components. + +At a high level, the mechanism works as follows: + +1. A third-party developer publishes a Move package containing a custom `AuthenticatorFunction` annotated with `#[authenticator]`. +2. An AI Account object is created on-chain and linked to this `AuthenticatorFunction` via an `AuthenticatorFunctionRef`. +3. When a transaction is submitted with the AI Account as sender, the protocol invokes the linked `AuthenticatorFunction` — passing the proof data from the `MoveAuthenticator` signature field — instead of performing traditional signature verification. +4. If the `AuthenticatorFunction` executes successfully, the transaction is considered authenticated; if it aborts, the transaction is rejected. + +### Requirements + +The proposed Account Abstraction model must adhere to the following constraints: + +1. **Stable Address**: Each AI Account must be associated with a stable and persistent address, enabling long-term reference and asset ownership. +2. **Interoperability**: AI Accounts must be capable of interacting seamlessly with any on-chain smart contract, without being restricted to specific protocols, types, or interfaces. +3. **True Abstraction**: dApps must be able to craft and propose transactions to user wallets without distinguishing between AI Accounts and EOAs. The transaction structure and interaction flow should remain identical, such that the dApp is agnostic to the account type it is interacting with. +4. **Identifier Uniqueness**: Each AI Account must be uniquely identifiable. The system must guarantee a one-to-one correspondence between account instances and their associated identifiers. +5. **Programmable Authentication**: Authentication logic must be fully programmable, enabling third-party developers to define and deploy custom authentication schemes tailored to specific application needs. +6. **Backward Compatibility**: The system must preserve the functionality of existing EOAs, including their native signature-based authentication mechanisms. +7. **Open Account Creation**: The creation of AI Accounts must be permissionless, i.e., any entity should be able to initialize an AI Account on behalf of another, provided the intended owner can later authenticate themselves. +8. **API Uniformity**: Developer-facing APIs for querying balances, initiating transfers, and similar operations must behave identically for both AI Accounts and EOAs, promoting transparency and ease of integration. +9. **Transaction Format Consistency**: The format and semantic structure of transaction payloads must remain unchanged. The protocol must handle TransactionData for AI Account transactions identically to legacy EOAs. +10. **Gas Cost Parity**: Current IOTA protocol static signature verification methods and Move-based verification counterparts should be cost-equivalent in terms of gas. + +### Protocol Design + +To support AI Accounts, we propose the addition of a new set of modules within the `iota-framework`. These modules define the core data structures and their associated methods for creating and interacting with an AI Account. + +#### Account Representation and Addressing + +AI Accounts are represented as objects within the IOTA Move framework, each associated with a globally unique 32-byte `ObjectID`. The `ObjectID` serves as the AI Account Identifier and is itself a valid `IotaAddress`. Ownership of on-chain objects by AI Accounts is expressed using the existing `AddressOwner(IotaAddress)` variant, where the `IotaAddress` is the AI Account Identifier. + +##### Background: IOTA Ownership Model + +Every object in the IOTA Protocol has a [well-defined owner](https://github.com/iotaledger/iota/blob/44f16f273f773ade66b53acf2bb3eccddf5f4170/crates/iota-types/src/object.rs#L550). Only the owner can use their objects as input to a transaction. The current ownership semantics are as follows: + +- `AddressOwner(IotaAddress)` + - `AddressOwner(IotaAddress=PubKey-derived)` – Object owned by a single EOA; it can be set as input of a transaction if the EOA provides a valid signature using the private key associated with the public key from which the `IotaAddress` was derived. + - `AddressOwner(IotaAddress=ObjectID)` – The owner is an `IotaAddress` which is interpreted as an `ObjectID`. Objects are, in essence, owning other objects. To unlock such owned objects, they need to be [received in a transaction](https://docs.iota.org/developer/iota-101/objects/transfers/transfer-to-object#receiving-objects) the first time they are accessed after being transferred. +- `ObjectOwner(IotaAddress=ObjectID)` – Object owned by another object, in a hierarchical, parent-child relationship. The owned object can be dynamically accessed in transactions where the parent is used as input. This is used for Dynamic Fields. +- `SharedOwner` – Mutably accessible by any address; it can be set as input of a transaction with no checks. +- `ImmutableOwner` – Immutably accessible by any address; it can be set as input of a transaction with no checks. + +##### Rationale for `AddressOwner` + +While an ownership of type `ObjectOwner` might appear suitable for an AI Account, since it is indeed an object, it would require additional steps and access control logic when objects are transferred to it. Specifically, if an `ObjectOwner` ownership relationship were established, the sender of an object would be required to use the AI Account object as input of the transfer transaction; moreover, mutable access to the AI Account object would also be necessary. + +Employing an `AddressOwner` ownership relation, instead, allows the sender to simply use the AI Account Identifier as the address. This choice renders AI Accounts indistinguishable from EOA addresses at the ownership level. + +Objects transferred to an AI Account Identifier do not require explicit acceptance by the receiver. When set as inputs of a transaction, their "unlocking" is performed by verifying that the AI Account Identifier matches the sender of the transaction, thereby ensuring that the account is authenticated. + +Figure 1 illustrates how the `AddressOwner(IotaAddress)` ownership variant applies to both EOA and AI Accounts. As shown, the external interface is identical, but the underlying derivation and verification mechanisms differ at the protocol level. + +![Ownership variants](fig-1-ownership.svg) + +The following table summarizes the key differences: + +| Aspect | EOA | Abstract Account | +| --------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| How is the address of the account derived? | `0xffff` address derived from the EOA public key. | `0xabc` is the `ObjectID` of the object representing the account.
`IotaAddress = AIAccountID = ObjectID` | +| Owned object that the transaction wants to unlock (input) | `0x123` with type `Coin`, owner is `0xffff`. | `0x123` with type `Coin`, owner is `0xabc`. | +| Sender field of the transaction | `0xffff` | `0xabc` | +| Signature field of the transaction | Payload containing a valid signature created using the private key (e.g., ED25519). | Payload containing bytes created by logic unknown to the IOTA protocol, but verifiable by a Move `AuthenticatorFunction` that was arbitrarily created by a third-party developer and dynamically linked to the AI Account Identifier. | + +#### Move Authenticator + +As seen above, AI Accounts are capable of initiating transactions, i.e., the AI Account Identifier can be used as sender of transactions. However, unlike EOAs, whose authentication derives from private key signatures, the AI Account Identifier is not necessarily tied to a specific cryptographic keypair, nor derived from one. Therefore, a new authentication flow is introduced into the protocol to allow the implementation of arbitrary authentication mechanisms in Move: the `MoveAuthenticator`. + +The `MoveAuthenticator` is a protocol-level transaction signature variant that allows transaction senders to submit a vector of arguments in the transaction signature field that are passed to the `AuthenticatorFunction` of the AI Account. This enables third-party developers to implement custom programmable authentication schemes using Move. + +> [!NOTE] +> Digression on the structure of IOTA transactions +> +> Currently, the structure of IOTA transactions includes: +> +> - `TransactionData`: Contains core transaction payload such as Programmable Transaction Blocks (PTB) commands and gas configuration. +> - `GenericSignatures`: A vector of protocol-supported authenticators, currently including `MultiSig`, `Signature`, `ZkLoginAuthenticator (disabled)`, and `PasskeyAuthenticator`. + +The proposed addition of `MoveAuthenticator` extends the set of `GenericSignature` variants to support dynamic authentication logic. With this extension, third-party developers can deploy Move packages implementing a custom `AuthenticatorFunction`. An AI Account can then be configured to delegate its authentication to such a package. Inputs to the `AuthenticatorFunction` are encoded as `Vec` (where `CallArg` is a type defining pure and object arguments) and provided in the `MoveAuthenticator` signature field. The function either completes successfully or aborts with an error if authentication fails. + +Figure 2 compares the authentication flow for transactions issued by EOA and AI Accounts. The key distinction is that EOAs rely on cryptographic signature verification at the protocol level, whereas AI Accounts delegate verification to a developer-defined `AuthenticatorFunction` executed in Move. + +![Transaction authentication](./fig-2-transactions.svg) + +The following subsections describe each authentication flow in detail. + +##### (Traditional) EOA Transaction Authentication + +`TransactionData` is the payload that makes transactions cryptographically unique. It includes sender, inputs, commands and gas data. Passing the raw bytes of the payload to a hash function yields its digest, i.e., `TransactionDigest`, which becomes the transaction identifier (encoded in base58). + +An EOA user signs the `TransactionDigest` with the EOA private key (the description is simplified for the sake of readability). This signature becomes the payload of the `GenericSignature` part of the transaction. Once transmitted to a validator, the transaction is authenticated by extracting the sender address and transaction digest from the `TransactionData` and verifying them against the signature. If verification fails, the transaction is marked as invalid. + +##### Abstract Account Transaction Authentication + +In the case of AI Accounts, the `TransactionData` part is exactly the same as the EOA case; it necessitates no changes. The difference lies in the `GenericSignature` part. A developer-defined mechanism can be used (e.g., a different signature scheme, passkey method or business logic) to generate a proof on the client side that can be validated by the `AuthenticatorFunction` in Move. + +This proof (or set of proofs) becomes the `MoveAuthenticator` payload of the `GenericSignature` field of the transaction. Validators authenticate the transaction by executing the account’s dynamically linked `AuthenticatorFunction` Move function with the proof provided as input argument(s). It is important to note that the `AuthenticatorFunction` has a “rich” context: it has access to the `TxContext` contained in the `TransactionData`, i.e., it knows the `TransactionDigest`, and also accesses the inputs and commands of `TransactionData` using an `AuthContext`. This `AuthContext` struct enables parsing of the PTB information included in the `TransactionData`. + +Should the execution of `AuthenticatorFunction` fail for any reason, the transaction is marked as invalid. + +#### The AI Account Interface + +The AI Account representation in Move is designed such that third-party developers can implement any arbitrary type. There is no single AI Account framework object type; rather, any object type can become an AI Account provided it implements the required interface. + +A Move type is considered an abstract account if, and only if: + +- It is an object (i.e., a struct type that has key ability and an `id: UID` field), +- has a dynamic field with key of type `0x2::account::AuthenticatorFunctionRefV1Key` and value of type `0x2::authenticator_function::AuthenticatorFunctionRef`. + +The type `0x2::account::AuthenticatorFunctionRef` contains the fields necessary to uniquely identify an on-chain `AuthenticatorFunction` defined by an external package. For version 1: + +```move +public struct AuthenticatorFunctionRefV1 has copy, drop, store { + package: ID, + module_name: ascii::String, + function_name: ascii::String, +} +``` + +Figure 3 illustrates a concrete example in which a custom Authenticator Move Package is deployed and linked to an AI Account to provide authentication: + +![Custom move based authenticator](fig-3-ai-auth-example.svg) + +In the example above, we imagine a scenario where a developer independently develops the Custom Authenticator package deployed at the address `0x789` (i.e., package id). This package defines the account interface through a module named `custom_auth`. In this module a `0x789::custom_auth::CustomAccount` Move object type is defined, which represents a specific implementation of an AI Account. The `CustomAccount` uses the field `auth_helpers` to store data on-chain; the logic governing this account is arbitrarily defined by the developer. + +The only field required to make `CustomAccount` an AI Account is a dynamic field using the `0x2::account::AuthenticatorFunctionRefV1Key` key and `0x2::authenticator_function::AuthenticatorFunctionRef` value. This dynamic field entry can only be created through a framework method in the `0x2::account` module, namely `create_account_v1`. + +The object with id `0xabc`, once becoming an AI Account, has an authentication method clearly defined by the “attached” `AuthenticatorFunctionRef`. This struct references a specific function within the category of Move functions known as `AuthenticatorFunction`. In the example, it references the `0x789::custom_auth::authenticate` function defined in the same module. + +#### The Authenticator Function + +The `AuthenticatorFunction` is designed to be as generic as possible, allowing third-party developers to implement arbitrary authentication logic. For instance, in the above example, the `CustomAccount` object's `auth_helpers` field can be used within the `AuthenticatorFunction`. This field contains on-chain data that may have been modified by other parties prior to authentication. In general, an `AuthenticatorFunction` receives inputs and can read from the ledger state to allow or reject access to the AI Account. The `vec` passed through the `MoveAuthenticator` payload of the `GenericSignature` part of the transaction is converted into function parameters similarly to what happens today for PTBs. + +An `AuthenticatorFunction` MUST satisfy the following rules: + +1. **Visibility**: The function MUST be declared as a `public` non-`entry` function. + +2. **Read-only inputs**: All inputs MUST be read-only. Accepted input types are [pure types](https://docs.iota.org/developer/ts-sdk/typescript/transaction-building/basics#pure-values) (integers, strings, etc.) and read-only references to objects. Owned Objects MUST NOT be passed as input; only Shared Objects and Immutable Objects are permitted. + +3. **First parameter — Account reference**: The first parameter MUST be a reference to the same Move type as the AI Account being authenticated. The object ID of the argument passed for this parameter MUST be exactly equal to the AI Account Identifier (i.e., the sender of the transaction). + +4. **No return type**: The function MUST NOT define a return type. Authentication succeeds if the function completes execution without error and fails if the function aborts. + +5. **Context parameters**: The second-to-last parameter MUST be `&AuthContext` and the last parameter MUST be `&TxContext`. The `AuthContext` struct exposes the underlying transaction fields (PTB inputs and commands), while `TxContext` exposes the transaction digest, gas parameters, and sponsor details. These context values are not created by the user; the protocol automatically creates and injects them before execution. The presence of `AuthContext` ensures that an `AuthenticatorFunction` cannot be invoked from within Move by other functions. + +##### Execution Lifecycle + +From the protocol point of view, the `AuthenticatorFunction` is invoked twice during the transaction lifecycle: + +1. Optimistic Pre-Consensus Authentication: + - Upon receiving a transaction, all validators execute the `AuthenticatorFunction` related to the TX’s sender account with any shared object read-only reference or pure inputs. + - If the pre-consensus authentication passes, then the TX is treated as any other, i.e., the TX’s owned objects (gas payment objects and the TX inputs) are locked and the validator signature needed for a certificate is returned. + - In this phase, no state modifications occur, i.e., no gas is consumed for the execution of the authentication. +2. Post-Consensus Authentication Execution: + - Once the transaction is ready for the post-consensus execution, the `AuthenticatorFunction` is executed for the second time immediately before the normal execution. + - The gas object versions for the gas payment are guaranteed for post-consensus execution since a majority of validators locked those gas objects. + - In this second phase, `AuthenticatorFunction` execution can still fail due to changes in the state of input shared objects. In this case the authentication gas cost is deducted, but no other state changes are committed to the ledger and the transaction execution result is ABORTED. + - Gas costs for authentication in non-sponsored transactions are deducted from an AI Account’s gas object. Sponsored transactions cover authentication costs via gas payment objects owned by the sponsor. + +#### Creating AuthenticatorFunctionRef + +The `AuthenticatorFunctionRef`, as described above, is a struct that uniquely identifies a function within a package deployed on-chain. Its creation is enabled via the Package Metadata Standard (see [IIP-0010](https://github.com/iotaledger/IIPs/blob/main/iips/IIP-0010/IIP-0010.md)). + +Figure 4 shows how the `PackageMetadata` object is used to validate and create an `AuthenticatorFunctionRef` during package publication. + +![Creating authenticator function references](fig-4-authenticator-function-ref.svg) + +Continuing with the same example from the previous subsection, consider the `CustomAuthenticator` package. When this package is published to the ledger, an associated `PackageMetadata` immutable object is created. This immutable object contains metadata for each module, including functions found in the `0x789::custom_auth` module. Specifically, the `0x789::custom_auth::authenticate` function is designated as an "authenticator" within the `PackageMetadata` object. To be designated as an authenticator, a function MUST follow the rules listed in the previous subsection and MUST be annotated with the `#[authenticator]` function attribute. + +The `PackageMetadata` object acts as a source of validation. This object is created by the protocol during package publication. If an `#[authenticator]` attribute is found for a function, the protocol validates that function using the `iota-move-verifier`. Since `PackageMetadata` is an immutable object that can only be created by the protocol, it cannot be forged with an unauthorized authenticator function. + +Given the trusted nature of the `PackageMetadata`, an `AuthenticatorFunctionRef` can be created by passing a `PackageMetadata` object as input. The function `0x2::authenticator_function::create_auth_function_ref` takes a `PackageMetadata`, a module name, and a function name, then verifies whether these inputs resolve to a valid authenticator function; if so, it returns an `AuthenticatorFunctionRef`. This reference is then used to create an account. + +## Rationale + +This specification introduces a flexible, developer-centric model for account abstraction that preserves compatibility with the existing transaction format and authorization model. By leveraging Move's programmability and object-oriented design, the system supports a wide range of use cases—from key rotation and passwordless login to DAO-based access control and cross-device passkey authentication. + +Alternative models—such as static multisignature schemes or fixed key lists—were deemed insufficient due to their lack of adaptability to dynamic and composable use cases. In contrast, the AI Account model integrates tightly with the Move-based models for asset management. + +Similar models have emerged in other blockchain ecosystems, such as Ethereum’s ERC-4337 and Aptos’ dynamic dispatch system. However, this proposal is uniquely tailored to the IOTA protocol's architecture, emphasizing on-chain object ownership, deterministic addressing, and native MoveVM integration. + +## Backwards Compatibility + +This proposal is designed to be fully backward compatible with the existing IOTA protocol. The following areas are affected: + +| Area | Impact | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Transaction Format** | No changes are made to the `TransactionData` structure. | +| **Signature Support** | A new `MoveAuthenticator` variant is added alongside the existing variants in `GenericSignature`. Existing signature types remain unaffected. | +| **Validation Pipeline** | An optional `AuthenticatorFunction` hook is introduced for transaction validation and pre-PTB execution. The existing validation pipeline is not modified. | +| **RPC and Wallet APIs** | RPC APIs remain unchanged. AI Accounts are fully compatible with existing APIs and indistinguishable from EOAs. However, wallets that wish to support the new account type MUST add support for each authenticator type defined on-chain to derive the bytes supplied to the `MoveAuthenticator`. | + +## Test Cases + +The following test cases SHOULD be implemented to validate the correctness and completeness of the AI Account model: + +| Test Case | Description | Reference Move Implementation | +| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| **Single-key EOA replication** | An AI Account that replicates standard single-key cryptographic authentication, including key rotation capability. | https://github.com/iotaledger/iota/tree/develop/examples/move/iotaccount | +| **Dynamic multisig** | An AI Account authenticated via dynamic multisignature logic based on signatures or on-chain capabilities. | https://github.com/lzpap/isafe/tree/main/contracts/isafe | +| **Function-Call keys** | An AI Account authenticated using a method similar to [Near's Function-Call keys](https://docs.near.org/protocol/access-keys), limiting access only to the execution of some methods for an account. | https://github.com/iotaledger/iota/tree/develop/examples/move/function_keys | +| **Spending limit** | An AI Account where several users are authorized to access but having a specific allowance of IOTA conis set for each one. | https://github.com/iotaledger/iota/tree/develop/examples/move/spending_limit | +| **Third-party authentication** | An AI Account authenticated using an external or third-party verification mechanism, such as ZK proofs validation. | https://github.com/iotaledger/iota/pull/10227 | +| **Time locked** | An AI Account where the authentication is constrained by time. | https://github.com/iotaledger/iota/tree/develop/examples/move/time_locked | + +## Reference Implementation + +Main PR against the develop branch: https://github.com/iotaledger/iota/pull/9586 + +## References to Account Abstraction projects in Web3 + +- [ERC-4337: Account Abstraction Using Alt Mempool](https://eips.ethereum.org/EIPS/eip-4337) +- [account.tech](https://github.com/account-tech) +- [Aptos Account Abstraction](https://aptos.dev/build/sdks/ts-sdk/account/account-abstraction) +- [Sui Account Abstraction Feature Request](https://github.com/MystenLabs/sui/issues/8157) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).