Alert Source Discuss
⚠️ Draft Standards Track: Interface

EIP-7896: ABI attachment in `wallet_sendCalls`

A capability to enable calldata decoding in wallets.

Authors Francisco Giordano (@frangio)
Created 2025-02-27
Discussion Link https://ethereum-magicians.org/t/eip-tbd-abi-attachment-in-wallet-sendcalls/23016
Requires EIP-5792

Abstract

This EIP extends EIP-5792 with a new interfaces capability, whereby an application can attach the contract interface specifications (aka. ABIs) that the wallet needs to reliably decode the calldata in the request.

Motivation

The security model of Ethereum accounts relies on a separation of concerns between applications and wallets, the latter being responsible for securing private key material and providing restricted access to it. When an application requests a transaction or a signature, the wallet prompts the user to accept it or reject it. The user is expected to make an assessment about the desirability of the operation, given that it can potentially operate on all account assets, in the extreme case “draining” them all for the benefit of an attacker. The wallet is tasked with providing information about the request to lead to an accurate assessment, in particular to help detect unintended effects and attacks.

This idealized vision is far from realized. “Blind signing”, the practice of accepting a request without full visibility of its contents or understanding of its implications, is a pervasive problem across Ethereum. This is a puzzling situation given what’s at stake. A likely explanation is that it is simply very difficult for wallets to extract and provide good information about requests.

Before accepting a transaction request, a user would ideally like to know exactly what effects the transaction will have when included on chain. Transaction simulations have become widespread throughout wallets in recent years, where the wallet (or a service provider) runs the transaction and summarizes the observed effects in a friendly description such as “-1 ETH, +2400 USDC”. However, exactly predicting these effects is impossible due to mutable shared state, and describing the range of possible effects is intractable due to the turing completeness of the EVM, so we should be cautious and not overly rely on this kind of approach.

Whereas transaction simulations try to provide insight into the dynamic behavior of a transaction, wallets should also surface all of the statically available information, such as transaction parameters and application metadata.

Some parameters have clear semantics, for example, the value in a transaction expresses how much of the native token is transferred. The data in a transaction, however, presents a challenge, as it is provided to the wallet as a bytestring and cannot be reliably decoded into more meaningfully structured information without knowledge of the target contract ABI. The wallet can try to use a database of function selectors to try to guess an ABI, but this will fail for new and unknown contracts, and known selectors can be ambiguous due to collisions, including those deliberately introduced by attackers. Alternatively, the wallet can obtain an ABI from a repository of verified source code, with the downside that the main such repository is managed by a centralized party.

Since applications that request transactions are necessarily aware of the relevant ABIs, this EIP proposes a mechanism where they can attach ABIs in transaction requests, so that wallets can show decoded call data to users and help make a more informed assessment.

Specification

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.

A new capability called interfaces is added to EIP-5792 requests.

wallet_sendCalls

When this capability is supported, wallet_sendCalls requests MAY include a global interfaces field.

The interfaces field provided by an application MUST map contract addresses to interface specs. These contract addresses SHOULD correspond to those of the to fields in the calls array of the request, and SHOULD be compared with them case-sensitively. There MAY be addresses in calls without a matching interface spec, and there MAY be addresses in interfaces without a matching call.

type SendCallsParams = { // default fields omitted
    capabilities?: { interfaces?: InterfacesCapability } & Record<string, Capability>;
};

type InterfacesCapability = {
    [contract: `0x${string}`]: {
        version: string;
        spec: unknown; // version-dependent
    };
    optional?: boolean;
};

An interface spec MUST describe how a contract will decode calldata into a series of function arguments. The interpretation of a spec as a decoding procedure depends on a version string.

The two initially defined versions are abi-v1 and abi-v2, corresponding to the Contract Application Binary Interface as defined by Solidity and adopted by other languages. In these cases, the spec MUST be provided as an array as described in Solidity’s documentation, page “Contract ABI Specification”, section “JSON”. The array MAY contain event and error descriptions in addition to function descriptions, though applications SHOULD exclude irrelevant items. The v1-v2 distinction corresponds to Solidity’s pragma abicoder v1 and pragma abicoder v2 (or pragma experimental ABIEncoderV2). Vyper implements abi-v2.

Applications SHOULD mark the interfaces field as optional, so that the user is able to proceed if their wallet does not support the capability or a provided spec version. If the field is marked optional, the wallet MAY ignore interfaces with unsupported spec versions.

Wallets SHOULD use the provided interface specs to decode the data of each call in the calls array in order to present the user with the decoded function arguments. Wallets MAY validate the provided specs against a database of verified or trusted specs.

Example Request

[
  {
    "version": "1.0",
    "from": "0xa22cc169386b820ab57c006a5b4980add068a7eb",
    "chainId": "0x01",
    "calls": [
      {
        "to": "0xdac17f958d2ee523a2206206994597c13d831ec7",
        "value": "0x00",
        "data": "0xa9059cbb000000000000000000000000f0c87f351435211efa00938a33771bf38302d1f10000000000000000000000000000000000000000000000056bc75e2d63100000"
      }
    ],
    "capabilities": {
      "interfaces": {
        "optional": true,
        "0xdac17f958d2ee523a2206206994597c13d831ec7": {
          "version": "abi-v1",
          "spec": [
            {
              "type": "function"
              "name": "transfer",
              "stateMutability": "nonpayable",
              "inputs": [
                {
                  "name": "to",
                  "type": "address"
                },
                {
                  "name": "value",
                  "type": "uint256"
                }
              ],
              "outputs": [],
            }
          ]
        }
      }
    }
  }
]

wallet_getCapabilities

Under the interfaces capability, wallets MUST include a versions array field listing the supported interface spec versions.

Example Response

{
  "0x0": {
    "interfaces": {
      "supported": true,
      "versions": ["abi-v1", "abi-v2"]
    }
  }
}

Rationale

Backwards Compatibility

No backward compatibility issues found.

Security Considerations

Needs discussion.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Francisco Giordano (@frangio), "EIP-7896: ABI attachment in `wallet_sendCalls` [DRAFT]," Ethereum Improvement Proposals, no. 7896, February 2025. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7896.