# Paymaster Capability in More Detail We recently shared [Proposal for New Wallet RPCs](https://hackmd.io/@lsr/proposal-for-new-wallet-rpcs) to start a discussion on enabling apps and wallets to communicate about batch transactions, paymasters, and more. Thanks to everyone for the feedback so far. In this post, we will explore the paymaster capability in more detail: covering the motivation, detailing call flows with updates based on feedback, and discussing the implied trust relationship between the wallet and app. ## Motivation Today, apps ask wallets to sign and send a transactions via the `eth_sendTransaction` RPC. This RPC has no field to express paymaster or sponsorship info. If we want to allow apps and wallet to communicate about paymasters, or sponsorship more generally, we need to standardize how that will happen. We first brough this need up [October 2023](https://ethereum-magicians.org/t/eip-idea-eth-signuseroperation-rpc/16184). > Suppose the dapp has its own paymaster, which my wallet knows nothing about, and wants to include the paymaster and signature in the request sent to the wallet. Perhaps the dapp wants to set some of the user operation gas values, and help the wallet with things it may not be aware of. Currently there is no way to do these things. We've had a lot of good discussion since then, and arrived at [the spec we shared last week](https://hackmd.io/@lsr/proposal-for-new-wallet-rpcs). We define some new `wallet_sendTransaction` RPC which accepts various `capabilities`, one of which could be `paymaster` (more details below). Apps can discover wallet capabilities via a new `wallet_getCapabilities` RPC. We expect the wallet community to align on the definitions of various capabilities and add more over time. This document is an effort to get more precise on the `paymaster` capability. You might be thinking, "But I've used apps with a paymaster already, how did that work?" Till date we have had 1. App-defined paymasters used via app-based wallets (aka "Embedded Wallets"). 2. Wallet defined paymasters, added to some request received via `eth_sendTransaction`. What we have not been able to do is allow an app to tell a wallet it does not control (i.e. non-embedded wallet) about a paymaster a user can use for some transaction. This is what we want to enable. ## Details In the original document, we propose a flow like the following. ![image](https://hackmd.io/_uploads/Sk-UlVXC6.png) 1. Upon connecting to a wallet, the application calls `wallet_getCapabilities` to request the wallet's capaibilities 2. The wallet returns its capabilities. In this case, indicating it supports `paymasterService`, by which we mean a web service that can handle various `pm_` calls. 3. The app calls `wallet_sendTransaction` and includes the URL of the `paymasterService` it would like to use to be used for the transaction. 4. The wallet builds a preliminary `UserOperation`, using `calls`. 5. Wallet calls `pm_getStubPaymasterData` on the `paymasterService`. 6. `paymasterService` returns a dummy value for `paymasterAnData` and optionally values for some gas fields. 7. Wallet calls `eth_setimateUerOperationGas` on bundler, passing `UserOperation`. 8. Bundler returns gas estimation. 9. Wallet calls `pm_getPaymasterData` on `paymasterService`, passing the whole `UserOperation`. 10. Paymaster service returns valid `paymasterAndData` for operation, or rejects. 11. Wallet sends `UserOperation` to bundler. 12. Wallet returns some transaction identifier to the app. Note, in this flow, we are now using `paymasterService` rather than `paymaster` as the capability name. We feel it is more clear that this is expected to be a web service. (Thanks to Dror for the push on clear naming.) There was [a comment](https://hackmd.io/@lsr/proposal-for-new-wallet-rpcs?comment=4389abc8-1f6e-4ba4-bb6f-48eacd1596e7&utm_source=comment-card&utm_medium=icon): > there is already quite a lot of support for this with the name `pm_sponsorUserOperation`, why not reuse that? We think there is some advantage to the above flow, in that it allows a `paymasterService` to be very "dumb" and not have to do any gas estimation. But, as there is already support for `pm_sponsorUserOperation` and it simplifies some of the diagrams, we will use it for the rest of this document. Here is an updated flow using `pm_sponsorUserOperation` ![image](https://hackmd.io/_uploads/SybJfNmAa.png) This flow is very close to the first, but now we only need one call to the `paymasterService`, as we expect it to be able to estimate gas and update the `UserOperation` as necessary. ## Trust and Validation Consider one problematic case for the above diagram: What if the `app` has some secret API key for `paymasterService`, which it does not want to expose? Many paymaster services have fairly simple validation rules and are mostly protected by an API key. The app likely does not want to share this API key with the wallet. One idea is to say, "What if the app passes itself as `paymasterSerivce` and proxies calls to the real `paymasterService`?". Something like the below. ![image](https://hackmd.io/_uploads/BkOO7VXAT.png) Now the app can protect its API key, but there are still challenges. How can the app know whether the `UserOperation` it receives in (6.) is one it wants to sponsor? 1. Given there are many different smart account implementations, the app does not know how to decode the `UserOp.callData`. 2. Even if the app could decode the calldata, the wallet might be deceptive! It may look like one function is being call, while the real onchain behavior is different. It seems the app cannot *really* know if it wants to sponsor this operation without fully simulating the onchain transaction. But simulating a transaction and parsing the result is complex, and most developers likely do not want this responsibility. There is a simpler, though more limited, validation option. Apps can check the byte code of the contract itself against known implementations, and use this to get a higher confidence decoding of the calldata. E.g. To support sponsoring tranasctions for [Smart Wallet](https://github.com/coinbase/smart-wallet) users, this might look like 1. If `UserOp.Sender` has byte code (i.e. has been deployed) - Check byte code matches expected proxy byte code. - Check implementation slot matches expected implementation. 2. If `UserOp.Sender` has not been deployed, check `initCode` is calling to the correct factory. 3. Finally, use the Smart Wallet ABI to decode the calldata and check the calls against what the app wants to sponsor. To make life easier for developers, maybe paymaster service providers could enable these kinds of validation in gas policy definitions. ## What's Next This is all still a work in progress, and we are eager to get more feedback. We are working to get this enabled in the [beta Smart Walelt SDK](https://docs.cloud.coinbase.com/wallet-sdk/docs/sw-setup) so that developers can try it out.