Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 63 additions & 8 deletions EIPS/eip-5792.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
eip: 5792
title: Wallet Call API
description: Adds JSON-RPC methods for sending multiple calls from the user's wallet, and checking their status
author: Moody Salem (@moodysalem), Lukas Rosario (@lukasrosario), Wilson Cusack (@wilsoncusack), Dror Tirosh (@drortirosh), Jake Moxey (@jxom), Derek Rein (@arein), Alex Forshtat (@forshtat), Sam Wilson (@SamWilsn) <sam@binarycake.ca>, Borislav Itskov (@Oxbobby)
author: Moody Salem (@moodysalem), Lukas Rosario (@lukasrosario), Wilson Cusack (@wilsoncusack), Dror Tirosh (@drortirosh), Jake Moxey (@jxom), Derek Rein (@arein), Alex Forshtat (@forshtat), Sam Wilson (@SamWilsn) <sam@binarycake.ca>, Borislav Itskov (@Oxbobby), Joao Tavares (@cryptotavares)
discussions-to: https://ethereum-magicians.org/t/eip-5792-wallet-abstract-transaction-send-api/11374
status: Review
type: Standards Track
Expand Down Expand Up @@ -43,6 +43,8 @@ These fields are set inside this capability's entry in the `capabilities` object
Each entity in the `calls` field may contain an optional `capabilities` object.
This object allows the applications to attach a capability-specific metadata to individual calls.

The `atomicRequired` field specifies if a wallet is required to handle the batch of calls atomically or not. The wallet capacity to execute batch calls atomically is exposed through the built in `atomic` capability and can be sourced via `wallet_getCapabilities`..

Unless these requirements are explicitly overriden by a certain `capability`, the wallet must adhere to the following rules.
Note that such a `capability` is not in the scope of this EIP and should be defined in its own ERC.

Expand All @@ -53,10 +55,14 @@ The wallet:
* MUST send the calls from the address specified in the request's `from` property, if provided
* If `from` is not provided the wallet SHOULD present the user with an opportunity to view and select the `from` address during confirmation
* MUST NOT await for any calls to be finalized to complete the batch
* MUST submit multiple calls as an atomic unit in a single transaction
* MUST NOT send any calls from the request if the user rejects the request
* MAY revert all calls if any call fails
* MUST not execute any further calls after a failed call
* When `atomicRequired` is set to `true`:
* MUST execute all calls atomically, meaning that either all calls execute successfully or no material effects appear on chain.
* MUST execute all calls contiguously, meaning no other transactions/calls may be interleaved with the calls from this batch.
* When `atomicRequired` is set to `false`:
* MAY execute all calls sequentially without any atomicity/contiguity guarantees.
* If a wallet is capable of providing atomicity guarantees, it MAY execute the batch atomically.

* MAY reject the request if the from address does not match the enabled account
* MAY reject the request if one or more calls in the batch is expected to fail, when simulated sequentially
* MUST reject the request if it contains a `capability` (either top-level or call-level) that is not supported by the wallet and the `capability` is not explicitly marked as optional.
Expand Down Expand Up @@ -88,6 +94,7 @@ type SendCallsParams = {
id?: string;
from?: `0x${string}`;
chainId: `0x${string}`; // Hex chain id
atomicRequired: boolean;
calls: {
to?: `0x${string}`;
data?: `0x${string}`;
Expand All @@ -111,6 +118,7 @@ type SendCallsResult = {
"version": "1.0",
"from": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"chainId": "0x01",
"atomicRequired": true,
"calls": [
{
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
Expand Down Expand Up @@ -151,9 +159,11 @@ Note that the `receipts` objects of this method's response is a strict subset of

The `capabilities` object allows the wallets to attach a capability-specific metadata to the response.

The `atomic` field specifies how the wallet handled the batch of calls, which influences the structure of the `receipts` field.

* The receipts in the `receipts` field MUST be in the order that they are included onchain.
* If a wallet executes multiple calls **atomically** in a single transaction, `wallet_getCallsStatus` MUST return an object with a `receipts` field that contains a single transaction receipt, corresponding to the transaction in which the calls were included.
* If a wallet executes multiple calls **non-atomically** through some `capability` defined elsewhere, `wallet_getCallsStatus` MUST return an object with a `receipts` field that contains **an array of receipts** for all transactions containing batch calls that were included onchain. This includes the batch calls that were included on-chain but eventually reverted.
* If a wallet executes multiple calls **atomically**, `wallet_getCallsStatus` MAY return an object with a `receipts` field that contains a single transaction receipt or an array of receipts, corresponding to how the batch of transactions were included onchain. It also MUST be explicit and return an `atomic` field set to `true`.
* If a wallet executes multiple calls **non-atomically**, `wallet_getCallsStatus` MUST return an object with a `receipts` field that contains **an array of receipts** for all transactions containing batch calls that were included onchain. This includes the batch calls that were included on-chain but eventually reverted. It also MUST be explicit and return a `atomic` field set to `false`.
* The `logs` in the receipt objects MUST only include logs relevant to the calls submitted using `wallet_sendCalls`. For example, in the case of a transaction submitted onchain by an [ERC-4337](./eip-4337.md) bundler, the logs must only include those relevant to the user operation constructed using the calls submitted via `wallet_sendCalls`. I.e. the logs should not include those from other unrelated user operations submitted in the same bundle.

#### `wallet_getCallsStatus` RPC Specification
Expand All @@ -166,6 +176,7 @@ type GetCallsResult = {
id: `0x${string}`;
chainId: `0x${string}`;
status: number; // See "Status Codes"
atomic: boolean;
receipts?: {
logs: {
address: `0x${string}`;
Expand Down Expand Up @@ -222,6 +233,7 @@ The `id` batch identifier is a unique 64 bytes represented as a hex encoded stri
"chainId": "0x01",
"id": "0x00000000000000000000000000000000000000000000000000000000000000000e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331",
"status": 200,
"atomic": true,
"receipts": [
{
"logs": [
Expand Down Expand Up @@ -318,6 +330,45 @@ The capabilities below are for illustrative purposes.
}
```

### `atomic` Capability

Like the illustrative examples given above and other capabilities to be defined in future EIPs, the `atomic` capability specifies how the wallet will execute the batches of transactions requested through `wallet_sendCalls` method.

The valid JSON-RPC values for this `atomic` capability only property, `supported`, are `true` or `false`:

* `true` means that the wallet will execute the calls atomically and contiguously.
* `false` means that the wallet does not provide any atomicity or contiguity guarantees.

This capability is expressed separately on each chain and should be interpreted as a guarantee only for batches of transactions on that chain.

If the `atomic` capability is not present for a given chain, and unless it is explicitly overriden by another `capability` (not in scope of this EIP), it means that the wallet does not support batching for that given chain.

#### `atomic` Capability Specification

```typescript
type AtomicCapability = {
supported: boolean;
};
```


#### `wallet_getCapabilities` Example Return Value including `atomicBatch`

```json
{
"0x2105": {
"atomic": {
"supported": true
}
},
"0x14A34": {
"atomic": {
"supported": false
}
}
}
```

## Rationale

### On Naming
Expand All @@ -328,7 +379,11 @@ We also debated whether the methods should be called `wallet_sendTransaction`, `

### Call Execution Atomicity

The `wallet_sendCalls` method accepts an array of `calls` and by default requires that these calls be executed as part of a single transaction. That said, we expect that in some cases app developers might want to submit batched calls if and only if they can be executed non-atomically. This would enable EOA wallets to accept multiple calls as well over the same interface. A definition of this behaviour may be proposed as a separate capability ERC.
The `wallet_sendCalls` method accepts an array of `calls`. However, this proposal does not require that these calls be executed as part of a single transaction. It enables EOA wallets to express their ability to execute calls as part of a single transaction or as part of multiple transactions. It also enables Apps to express their minimum atomicity requirements for how calls must be executed.

The `atomic` special capability was made an integral part of this specification in order promote expressiveness and facilitate adoption (from both wallets and apps). And due to its importance to reduce ambiguity between the App and the Wallet, the capability is expressed as a top-level field in the `wallet_sendCalls` request (through the `atomicRequired` parameter) and the `wallet_getCallsStatus` response (through the `atomic` field).

We initially proposed that multiple calls must be executed atomically, but after some debate we ultimately decided this was too opinionated. Instead, we are including a specification for an `atomic` capability. This allows for EOA wallets to accept multiple calls and still gives developers the option to only submit batched calls if they are executed atomically.

### Call Gas Limit

Expand All @@ -340,7 +395,7 @@ Wallets that do not support the methods defined here SHOULD return error respons

## Security Considerations

App developers MUST NOT assume that all calls will be sent in a single transaction if they were submitted to a wallet with a capability defining how to execute the calls non-atomically. The exact behavior of non-atomically executed calls is to be defined in separate ERCs.
Regardless of the `atomic` value specified, App developers MUST NOT assume that all calls will be sent in a single transaction. An example could be an L2 resistant to reorgs that implements a sendBundle or similar functionality.

Wallets MUST ensure that batch identifiers returned by `wallet_sendCalls` are unpredictable to prevent malicious apps from inferring information about other users' transactions.

Expand Down