Spend Permissions let you designate a trusted spender that can spend tokens on behalf of your Smart Account. This enables use cases like subscription payments, agentic payments, algorithmic trading, automated payouts, and allowance management.Spend Permissions utilize the Spend Permission Manager contract deployed on Base and other networks.
There are two parties involved in a spend permission:
Account - The smart account that creates the spend permission and approves it onchain.
Spender - The entity that can spend tokens on behalf of the account within the limits defined by a spend permission. Can be a Smart Account or a regular account.
The CDP Embedded Wallet SDK makes it easy to work with spend permissions as the account owner, offering methods to create and manage permissions. If you’re the spender, see Using a spend permission.
These are the main components of a spend permission:
Spender - The entity that can spend tokens on behalf of the account.
Token - The token that the spend permission is for, and the amount of that token that the spender is allowed to spend.
Time period - The time period for which the spend permission is valid.
Salt - A random value used to differentiate between spend permissions with the same parameters. The SDK will generate a random salt for you, but you can also specify your own.
Extra Data - Arbitrary data that can be used to store additional information about the spend permission.
See the following sections for more details on the main components.
The spender is specified in the spender field of the spend permission. It can be the address of any account, whether it’s a Smart Account or a regular account.
The token is specified in the token field of the spend permission, and the amount allowed to spend is specified in the allowance field.Spend permissions support both native tokens and ERC-20 tokens. When using the CDP SDK, you have two options for specifying tokens:
Convenient shortcuts - Use "eth" for native ETH or "usdc" for USDC, and the SDK will handle the conversion to the correct token address. This shortcut is only supported on Base or Base Sepolia.
ERC-20 contract addresses - For other tokens, specify the token contract address as a string (e.g., "0x4200000000000000000000000000000000000006" for WETH).
The amount allowed to spend is specified in the allowance field, using the smallest unit of the token. For example, if the token is ETH, the allowance is specified in wei, and if the token is USDC, the allowance is specified in the smallest unit of USDC (6 decimals).
The time period is specified using the periodInDays field for simple day-based periods, or the period, start and end fields for more complex time controls.The periodInDays field provides a convenient way to specify common time periods (e.g., periodInDays: 1 for daily limits, periodInDays: 7 for weekly limits).For more advanced control, the start and end fields specify when the spend permission is valid. This means that the spender can spend the amount specified in the allowance field after the start time and before the end time; attempting to spend outside of this time range will fail.
The period field specifies a rolling window of time in seconds in which the spender can spend the amount specified in the allowance field. This allows you specify things like “the spender can spend up to 0.00001 ETH per day” or “the spender can spend up to 100 USDC per week”.
Smart Accounts must have spend permissions enabled at the time of creation. You cannot create spend permissions on accounts that were created without spend permissions enabled.
Creating a spend permission is a user operation that requires gas. You can use the CDP Paymaster on Base networks by setting useCdpPaymaster: true, or provide your own paymasterUrl for gas sponsorship.
Use useListSpendPermissions to retrieve spend permissions. The hook automatically detects and lists permissions for the authenticated user’s smart account.
The useListSpendPermissions hook automatically lists spend permissions for your current Smart Account.The hook accepts an optional configuration object:
network: The network to fetch spend permissions on. Defaults to “base-sepolia”
pageToken: Token for pagination to fetch the next page of results
The returned data contains:
spendPermissions: Array of SpendPermissionResponseObject where each object contains:
permission: The actual spend permission details
permissionHash: Unique identifier for the permission
revoked: Boolean indicating if the permission has been revoked
createdAt: Timestamp when the permission was created
network: The network where the permission exists
hasNextPage: Boolean indicating if more results are available
nextPageToken: Token to fetch the next page of results
The hook also returns:
refetch: Function to refresh the list of spend permissions
status: Current status (“idle” | “pending” | “success” | “error”)
Use useRevokeSpendPermission to revoke an existing spend permission. The hook returns status, data, and error values for tracking the revocation process:
Report incorrect code
Copy
Ask AI
import { useRevokeSpendPermission } from "@coinbase/cdp-hooks";import { useState } from "react";function RevokeSpendPermission({ permissionToRevoke }) { const { revokeSpendPermission, status, data, error } = useRevokeSpendPermission(); const handleRevokePermission = async () => { if (!permissionToRevoke?.permissionHash) return; try { // This will automatically start tracking the user operation status const result = await revokeSpendPermission({ network: "base-sepolia", permissionHash: permissionToRevoke.permissionHash, useCdpPaymaster: true, // Use CDP Paymaster on Base (enabled by default on Base Sepolia) // Or provide a custom paymaster URL: // paymasterUrl: "https://your-paymaster.example.com", }); console.log("Revoke initiated! User Operation Hash:", result.userOperationHash); } catch (error) { console.error("Failed to revoke spend permission:", error); } }; return ( <div> {status === "idle" && <p>Ready to revoke permission</p>} {status === "pending" && ( <div> <p>Revoking spend permission...</p> {data && <p>User Op Hash: {data.userOpHash}</p>} </div> )} {status === "success" && data && ( <div> <p>Spend permission revoked successfully!</p> <p>User Operation Hash: {data.userOpHash}</p> <p>Transaction Hash: {data.transactionHash}</p> <p>Status: {data.status}</p> </div> )} {status === "error" && ( <div> <p>Failed to revoke spend permission</p> <p>Error: {error?.message}</p> </div> )} <button onClick={handleRevokePermission} disabled={status === "pending"}> {status === "pending" ? "Revoking..." : "Revoke Spend Permission"} </button> </div> );}
Revoking a spend permission is a user operation that requires gas. You can use the CDP Paymaster on Base networks by setting useCdpPaymaster: true, or provide your own paymasterUrl for gas sponsorship.
The revokeSpendPermission function returns:
userOperationHash: The hash of the user operation that revokes the permission
To track the status of the revocation, you can:
Call useWaitForUserOperation() with the user operation hash to wait for the revocation to complete.
To check how much of a spend permission’s allowance remains in the current period, query the getCurrentPeriod function on the Spend Permission Manager contract.