From f7fd8a554530304db55ad4dc01121bc63bdd6160 Mon Sep 17 00:00:00 2001 From: Conner Swenberg Date: Wed, 16 Oct 2024 17:14:15 -0700 Subject: [PATCH] Purge docs --- README.md | 26 ++------------ docs/CryptoKey.md | 28 --------------- docs/README.md | 29 --------------- docs/SpendPermission.md | 35 ------------------- docs/diagrams/offchain/getPermissions.md | 16 --------- docs/diagrams/offchain/grantPermissions.md | 22 ------------ .../offchain/prepareCalls+sendCalls.md | 34 ------------------ docs/diagrams/offchain/sendCalls.md | 29 --------------- .../onchain/batchUpdatePermissions.md | 25 ------------- docs/diagrams/onchain/paymaster.md | 32 ----------------- docs/diagrams/onchain/withdraw.md | 28 --------------- 11 files changed, 2 insertions(+), 302 deletions(-) delete mode 100644 docs/CryptoKey.md delete mode 100644 docs/README.md delete mode 100644 docs/SpendPermission.md delete mode 100644 docs/diagrams/offchain/getPermissions.md delete mode 100644 docs/diagrams/offchain/grantPermissions.md delete mode 100644 docs/diagrams/offchain/prepareCalls+sendCalls.md delete mode 100644 docs/diagrams/offchain/sendCalls.md delete mode 100644 docs/diagrams/onchain/batchUpdatePermissions.md delete mode 100644 docs/diagrams/onchain/paymaster.md delete mode 100644 docs/diagrams/onchain/withdraw.md diff --git a/README.md b/README.md index 7608054..094f351 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,3 @@ -# Smart Wallet Permissions +# Spend Permissions -**Permissions enable apps to submit transactions on behalf of users.** - -Permissioned user operations can avoid typical user friction in web3 apps like: - -- Wallet popup windows -- Passkey biometric scans -- User presence in-app - -Permissions unlock experiences that keep all of the unique properties of wallets (self-custody, data portability, etc.) without sacrificing on user experience compared to web2: - -- Sign-in and never see mention of a wallet again -- High-frequency transactions (gaming, social, etc.) -- Background transactions (automated trading, subscriptions, etc.) - -## Get started - -> **Note**: These contracts are currently unaudited and are only recommended for testing purposes. Use at your own risk. - -Read about how to [get started here](./docs/examples/). - -## Learn more - -For auditors and the curious, we recommend reading our deep-dive documentation [here](./docs). +**Spend Permissions enable apps to spend native and ERC-20 tokens on behalf of users.** diff --git a/docs/CryptoKey.md b/docs/CryptoKey.md deleted file mode 100644 index 9554315..0000000 --- a/docs/CryptoKey.md +++ /dev/null @@ -1,28 +0,0 @@ -# CryptoKey - -Now that apps are able to sign user operations on behalf of users, a few patterns of key custody emerge: - -1. Self-custodial keys bound to apps -2. Partial-custodial keys bound to apps -3. Custodial keys owned by apps - -All custodial patterns have different tradeoff sweet spots, but for now we are most interested in exploring option 1 first. - -The most common implementation that may come to mind are [Passkeys](https://www.passkeys.com/). While passkeys enable self-custody in a secure and simple manner, their additional friction to sign via a second user verification (e.g. biometric scan) can be cumbersome. For our goals of reaching UX that is on par or superior than any existing application, this is too much friction. - -In pursuit of something simpler, we discovered [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey), a standard web library for generating key pairs and signing messages. In our research thus far, we believe CryptoKeys provide the simplest way for apps to offer self-custodial Session Keys without compromising on usability or security. You can think of it like a slightly less secure Passkey, but without the additional user confirmation burden so we can make signing invisible. - -CryptoKey offers a handful of utilities, but there are four we need to build Session Keys: - -1. [Asymmetric signatures (ECDSA)](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/sign#ecdsa) -2. [Onchain-compatible curve (P-256)](https://developer.mozilla.org/en-US/docs/Web/API/EcKeyGenParams#namedcurve) -3. [Same-origin storage (IndexedDB)](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Basic_Terminology) -4. [Non-extractable](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey/extractable) - -To make this approach even possible, we need the ability to sign arbitrary hashes whose signatures can be verified onchain. Accessing the same signature algorithm (ECDSA) and "P-256" curve (secp256r1) as Passkeys lets us reuse the same signature verification used natively by Coinbase Smart Wallet. - -To make this approach secure, we need the ability to guarantee that keys cannot be accessed by any party other than the app (same-origin storage) or ever leave the device (non-extractable). These two properties actually make CryptoKeys more secure than patterns that transmit secrets over a network (e.g. cookies), which we all rely on for most web applications. - -Note that CryptoKey is a less opinionated library than WebAuthn, which means we can actually sign raw hashes compared to WebAuthn's custom object that packs additional data. Because we would like to reuse existing onchain verifiers like [WebAuthn.sol](https://github.com/base-org/webauthn-sol/blob/main/src/WebAuthn.sol), we actually wrap all hashes within a hardcoded WebAuthn object for compatibility. - -Also note that IndexedDB, our storage mechanism for CryptoKeys, is not the most intuitive to use. We are actively working on an SDK that makes it easier to generate, read, and sign with CryptoKeys for onchain-native use cases. diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 77ae088..0000000 --- a/docs/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Smart Wallet Permissions Docs - -> :information_source: These contracts are unaudited. Please use at your own risk. - -With [ERC-7715](./ERC-7715.md), users can grant permissions to apps to submit transactions on their behalf. These docs are meant to walk you through the key design decisions and mechanisms that chose to enable this feature at the contract layer. Reading all linked resources is encouraged to get the full depth of design intuition. - -## Design Overview - -### 1. ERC-4337 alignment - -Our first iteration chose to lean into the patterns defined by [ERC-4337](https://eips.ethereum.org/EIPS/eip-4337) for actually executing onchain. This allowed us to share infrastructure Coinbase and many other teams have invested in for Bundlers and Paymasters. It also absolved us of redesigning a solution for problems that the Entrypoint already solves like DoS protection via separation of validation and execution phases and modularizing gas payment. - -### 2. Optional addition to Coinbase Smart Wallet V1 - -While implementing this feature as a new V2 wallet implementation was tempting, we decided to leverage the modular owner system from [Smart Wallet V1](https://github.com/coinbase/smart-wallet) and avoid a hard upgrade. This helped reduce our launch timeline and also reduced the risk of introducing this substantially different account authentication paradigm. - -## End-to-end Journey - -### 1. App requests permissions from user (offchain) - -View a sample sequence diagram [here](./diagrams/offchain/grantPermissions.md) and Smart Wallet's supported capabilities [here](./ERC-7715.md). - -### 2. App prepares and sends calls (offchain) - -View a sample sequence diagram [here](./diagrams/offchain/prepareCalls+sendCalls.md). - -### 3. Bundler executes User Operation (onchain) - -View a sample sequence diagram [here](./diagrams/onchain/withdraw.md). diff --git a/docs/SpendPermission.md b/docs/SpendPermission.md deleted file mode 100644 index 2a12ad8..0000000 --- a/docs/SpendPermission.md +++ /dev/null @@ -1,35 +0,0 @@ -# Spend Permission - -## Onchain accounting - -Tracking asset expenditure accurately is important for enforcing user-approved limits. Given the fragility and complications with doing this accounting offchain and the severity of inaccuracies, we designed for fully onchain accounting. Onchain accounting enables us to have higher confidence in its reliability and keep our system trust-minimized. - -To do accounting onchain, we need to design a storage layout and make sure to update it every time assets are spent. For the limited scope of native tokens, we can detect the amount spent by looping over calls in the batch and accumulate `msg.value` on each call. At the end of the call batch, we expect to make an external call to a specific function designed to save the new spend and enforce the user-approved limits. If the enforcement reverts, the entire call batch is reverted too thanks to Smart Wallet's atomicity guarantee. - -### Recurring accounting - -Now that Session Keys replace a pop-up window every transaction with a pop-up window for approving every permission, the frequency of permission requests is the new baseline annoyance for wallet UX. How can we minimize this intrusion? - -Taking a look at the existing approval for common token standards, we unfortunately see an antipattern of over-permissive infinite allowances. Apps also don't want to have to ask the user every single time they want to spend tokens so instead they ask for a high amount of trust. Users aren't really given a choice if they want to use the product, so they comply and extend that trust. Unfortunately, this trust has led to countless drainer events which we would like to prevent with Session Keys. - -Our solution is to create spend permissions that allow an app to request to spend user assets on a recurring basis (e.g. 1 ETH / month). As apps spend user assets through using this permission, the recurring logic automatically increments and enforces the allowance for the current cycle. Once enough time passes to enter the next cycle, the allowance usage is reset to zero and the app can keep spending up to the same allowance. - -This design allows users and apps to have reduced friction in approving asset use, while still giving the user control to manage risk and keep asset allowance small upfront. This design is also intuitive for users and can easily support recurring models like subscriptions, automated trading strategies, and payroll. - -A spend permission is defined by 3 values: - -1. start time -2. cycle period -3. allowance per cycle - -The start time and cycle period set a deterministic schedule infinitely into the future for when allowances reset to zero for the next cycle. - -Here are the first few cycles for a spend permission: - -1. `[start, start + period - 1]` -1. `[start + period, start + 2 * period - 1]` -1. `[start + 2 * period, start + 3 * period - 1]` - -Which follows the general form for the `n`th cycle's time range: `[start + (n - 1) * period, start + n * period - 1]` with first `n = 1`. - -When a new spend of a spend permission is attempted, the contract first determines what the current cycle's usage is. If the current time falls within the cycle of last stored use, we simply check if this new usage will exceed the allowance. If the current time exceeds the cycle of last stored use, that means we are in a new cycle and should reset the allowance to zero and then add our new attempted spend. By leveraging a single storage slot, we are able to have a gas cost that does not scale with usage, keeping it efficient. diff --git a/docs/diagrams/offchain/getPermissions.md b/docs/diagrams/offchain/getPermissions.md deleted file mode 100644 index 20d06ec..0000000 --- a/docs/diagrams/offchain/getPermissions.md +++ /dev/null @@ -1,16 +0,0 @@ -## Get Permissions - -```mermaid -sequenceDiagram - autonumber - box transparent App - participant A as App Interface - participant SDK as Wallet SDK - end - participant WS as Wallet Server - - A->>SDK: wallet_getPermissions - SDK->>WS: wallet_getPermissions - WS-->>SDK: permissions with context - SDK-->>A: permissions with context -``` diff --git a/docs/diagrams/offchain/grantPermissions.md b/docs/diagrams/offchain/grantPermissions.md deleted file mode 100644 index c0b3fad..0000000 --- a/docs/diagrams/offchain/grantPermissions.md +++ /dev/null @@ -1,22 +0,0 @@ -## Grant Permissions - -```mermaid -sequenceDiagram - autonumber - box transparent App - participant A as App Interface - participant SDK as Wallet SDK - end - box transparent Wallet - participant W as Wallet Interface - participant U as User - end - - A->>SDK: wallet_grantPermissions - SDK->>W: wallet_grantPermissions - W->>U: approve permission - U->>U: sign - U-->>W: signature - W-->>SDK: permissions with context - SDK-->>A: permissions with context -``` diff --git a/docs/diagrams/offchain/prepareCalls+sendCalls.md b/docs/diagrams/offchain/prepareCalls+sendCalls.md deleted file mode 100644 index 1dd3cd9..0000000 --- a/docs/diagrams/offchain/prepareCalls+sendCalls.md +++ /dev/null @@ -1,34 +0,0 @@ -## Prepare Calls and Send Pre-Signed Calls - -General flow for sending user operations with a Wallet Server. Supports server signers and our own Wallet A (see [sendCalls+permissionsContext](./sendCalls+permissionsContext.md)). - -```mermaid -sequenceDiagram - autonumber - participant A as App - box transparent Wallet - participant WS as Wallet Server - participant CS as Cosigner - end - box transparent External - participant P as Paymaster - participant B as Bundler - end - - A->>WS: wallet_prepareCalls - Note over A,WS: permissions capability with context - WS->>P: pm_getPaymasterStubData - P-->>WS: paymaster stub data - WS->>P: pm_getPaymasterData - P-->>WS: paymaster data - WS-->>A: prepared calls with hash - A->>A: sign - A->>WS: wallet_sendPreparedCalls - Note over A,WS: prepared calls with signature - WS->>CS: cosign userOp - CS->>CS: validate userOp + sign - CS-->>WS: cosignature - WS->>B: eth_sendUserOperation - B-->>WS: userOpHash - WS-->>A: callsId -``` diff --git a/docs/diagrams/offchain/sendCalls.md b/docs/diagrams/offchain/sendCalls.md deleted file mode 100644 index c9eeea2..0000000 --- a/docs/diagrams/offchain/sendCalls.md +++ /dev/null @@ -1,29 +0,0 @@ -## Normal Send Calls - -Reference point for how a normal `wallet_sendCalls` request is handled by Smart Wallet. - -```mermaid -sequenceDiagram - autonumber - participant A as App - box transparent Wallet - participant WF as Wallet Frontend - participant U as User - end - box transparent External - participant P as Paymaster - participant B as Bundler - end - - A->>WF: wallet_sendCalls - WF->>P: pm_getPaymasterStubData - P-->>WF: paymaster stub data - WF->>P: pm_getPaymasterData - P-->>WF: paymaster data - WF->>U: approve transaction - U->>U: sign - U-->>WF: signature - WF->>B: eth_sendUserOperation - B-->>WF: userOpHash - WF-->>A: callsId -``` diff --git a/docs/diagrams/onchain/batchUpdatePermissions.md b/docs/diagrams/onchain/batchUpdatePermissions.md deleted file mode 100644 index 1539b15..0000000 --- a/docs/diagrams/onchain/batchUpdatePermissions.md +++ /dev/null @@ -1,25 +0,0 @@ -## Batch Update Permissions - -Accounts can batch-revoke/approve/update permissions via batching `revoke` and `approve` calls to `SpendPermissionManager`. - -```mermaid -sequenceDiagram - autonumber - participant E as Entrypoint - participant A as Account - participant SP as Spend Permissions - - E->>A: validateUserOp - Note over E: Validation phase - A-->>E: validation data - E->>A: executeBatch - Note over E: Execution phase - loop - A->>SP: revoke - Note over A,SP: recurring allowance data - end - loop - A->>SP: approve - Note over A,SP: recurring allowance data - end -``` diff --git a/docs/diagrams/onchain/paymaster.md b/docs/diagrams/onchain/paymaster.md deleted file mode 100644 index 3c85502..0000000 --- a/docs/diagrams/onchain/paymaster.md +++ /dev/null @@ -1,32 +0,0 @@ -# Use Spend Permissions as a Paymaster - -Using Spend Permissions as a Paymaster enables spending a recurring allowance on gas so that the spender does not need to have gas in their account to initiate a withdraw. Native token in excess of gas payment can be withdrawn simultaneously and withdrawing ERC-20s must be done with the explicit `withdraw` call in execution phase. - -```mermaid -sequenceDiagram - autonumber - participant E as Entrypoint - participant S as Spender - participant SP as Spend Permissions - participant U as Smart Wallet - - Note over E: Validation phase - E->>S: validateUserOp - E->>SP: validatePaymasterUserOp - SP->>U: execute(paymasterDeposit) - U->>SP: paymasterDeposit - SP->>E: deposit - Note over SP,E: Deposit required prefund - Note over E: Execution phase - E->>S: executeBatch - opt - S->>SP: withdrawGasExcess - SP->>S: call{value}() - end - E->>SP: postOp - opt - SP->>E: withdrawTo - E->>S: call{value}() - Note over E,S: Refund unused gas - end -``` diff --git a/docs/diagrams/onchain/withdraw.md b/docs/diagrams/onchain/withdraw.md deleted file mode 100644 index c4f0de0..0000000 --- a/docs/diagrams/onchain/withdraw.md +++ /dev/null @@ -1,28 +0,0 @@ -# Withdraw from Spend Permissions - -The first time using a recurring allowance, the spender needs to pack an additional `permit` call before withdrawing to validate and store the approval. After a recurring allowance has been approved, the spender only needs to call `withdraw` to transfer tokens from the Smart Wallet. - -```mermaid -sequenceDiagram - autonumber - participant S as Spender - participant M as Spend Permissions - participant A as Smart Wallet - participant ERC20 - - opt - S->>M: permit(spendPermission, signature) - end - Note over M: validate signature and store approval - S->>M: withdraw(spendPermission, value) - Note over M: validate recurring allowance authorized
and withdraw value within allowance - M->>A: execute(target, value, data) - Note over M,A: transfer tokens - alt token is address(e) - A->>S: call{value}() - Note over A,S: transfer native token to spender - else else is ERC20 contract - A->>ERC20: transfer(spender, value) - Note over A,ERC20: transfer ERC20 to spender - end -```