{"id":"EIP-2255","name":"Wallet Permissions System","status":"Final","chain":"both","category":{"id":"onboarding","name":"Onboarding & Access","description":"Getting users into web3 without friction"},"journeyStages":[{"id":"discovery","name":"Discovery & Connection","description":"Finding and connecting wallet to dApp"},{"id":"approving","name":"Approving & Permissioning","description":"Granting permissions for actions"}],"uxImpact":"EIP-2255 standardizes wallet_getPermissions and wallet_requestPermissions so a wallet can expose a permission model and caveats for a dApp. It supports progressive consent when the selected wallet implements the requested permission methods; it does not require a revocation RPC, expiry field, or common management UI.","officialUrl":"https://eips.ethereum.org/EIPS/eip-2255","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"EIP-2255","specConstraints":[{"id":"eip-2255-permission-list","constraint":"wallet_getPermissions returns a list of Permission objects that the application can inspect and explain.","appliesTo":"application","normativity":"normative","specQuote":"The format of the returned permissions MUST be an array of `Permission` objects, which are defined as follows:","specSection":"Specification — wallet_getPermissions — Returns","specUrl":"https://eips.ethereum.org/EIPS/eip-2255#walletgetpermissions-returns","designImplication":"Render the returned permission scope and caveats as data from the selected wallet. Do not invent a common permission shape when the wallet returns a different or empty list."},{"id":"eip-2255-permission-request-result","constraint":"wallet_requestPermissions accepts one PermissionRequest and returns the permissions requested by the wallet after the request.","appliesTo":"application","normativity":"normative","specQuote":"The `wallet_requestPermissions` method is used for an application to request additional permissions. It MUST take a single parameter, a `PermissionRequest` object, and MUST return an array of `RequestedPermission` objects.","specSection":"Specification — wallet_requestPermissions","specUrl":"https://eips.ethereum.org/EIPS/eip-2255#walletrequestpermissions","designImplication":"Show the requested scope before approval and the returned granted scope after approval. Keep denied, partial, and unsupported results distinct from a successful permission grant."},{"id":"eip-2255-authorization-gate","constraint":"Restricted methods must fail until the user accepts the corresponding wallet_requestPermissions request.","appliesTo":"wallet","normativity":"normative","specQuote":"Attempted requests to a restricted method must fail with an error, until a `wallet_requestPermissions` request is made and accepted by the user.","specSection":"Specification — wallet_requestPermissions — Parameters","specUrl":"https://eips.ethereum.org/EIPS/eip-2255#walletrequestpermissions-parameters","designImplication":"Make consent a real gate in the flow. Do not show a restricted action as available merely because the app can construct the request."},{"id":"eip-2255-favicon-request-safety","constraint":"Wallets rendering a website favicon should sanitize arbitrary URI requests by whitelisting schemes and ports.","appliesTo":"wallet","normativity":"security-considerations","specQuote":"As such, it is recommended for wallets to sanitize the URI by whitelisting specific schemes and ports.","specSection":"Security Considerations — Server-Side Request Forgery (SSRF)","specUrl":"https://eips.ethereum.org/EIPS/eip-2255#server-side-request-forgery-ssrf","designImplication":"Treat remote favicon fetching as an untrusted-wallet boundary. Keep the connection approval UI independent of a URL's icon and make failures safe rather than silently fetching arbitrary local resources."},{"id":"permission-rejection-error","constraint":"A rejected wallet_requestPermissions request should return EIP-1193 error code 4001.","appliesTo":"wallet","normativity":"normative","specSection":"Specification > wallet_requestPermissions > Parameters","specUrl":"https://eips.ethereum.org/EIPS/eip-2255#walletrequestpermissions","designImplication":"Show user rejection as a deliberate denied state, distinct from unsupported, malformed, or transport failures.","specQuote":"If a `wallet_requestPermissions` request is rejected, it should throw an error with a `code` value equal to `4001` as per [EIP-1193](./eip-1193.md)."}],"summary":"EIP-2255 standardizes wallet_getPermissions and wallet_requestPermissions so a wallet can expose a permission model and caveats for a dApp. It supports progressive consent when the selected wallet implements the requested permission methods; it does not require a revocation RPC, expiry field, or common management UI.","applicability":{"whenToUse":["The selected wallet exposes wallet_getPermissions and wallet_requestPermissions.","The product needs progressive consent and can show returned scopes and caveats.","The UI can recover when permission management, expiry, or revocation is unavailable."],"whenToAvoid":["The wallet does not support the requested permission RPCs or capability.","The product needs a wallet-mandated expiry or revocation UI that the returned permission model does not expose.","The app cannot fall back when a permission request is denied."]},"designerTakeaways":["Request the smallest permission set that supports the next user action.","Show the wallet's returned permissions and caveats in plain language.","Only show revoke, expiry, or management controls that the selected wallet and permission model actually expose."],"problemsSolved":[{"problem":"Connecting wallet exposes everything at once","oldWay":"Click \"Connect\" and dApp can see all addresses, request any transaction","newWay":"The dApp requests a specific permission set and the wallet returns the granted scope and caveats when supported","impact":"critical"},{"problem":"Users can't revoke specific permissions","oldWay":"Only option is to fully disconnect, losing all access","newWay":"A wallet may expose permission management, but revocation and expiry controls are implementation-specific","impact":"high"},{"problem":"No way to know what a dApp can do","oldWay":"Users unsure what they agreed to when connecting","newWay":"Clear permission list shows exactly what dApp can access","impact":"high"},{"problem":"Can't progressively expand trust","oldWay":"Must grant full access upfront or not connect at all","newWay":"Start with \"view address\", add \"sign messages\" later","impact":"medium"},{"problem":"Apps request more than they need","oldWay":"No incentive to request minimal permissions","newWay":"Permission prompts make over-requesting obvious to users","impact":"medium"}],"uxPatterns":[{"name":"Progressive Permission Request","description":"Request permissions as needed, not all at once","userFlow":["User clicks Connect","Wallet shows minimal permission request","User understands exactly what's being asked","User approves minimal access","Later: dApp requests signing permission when needed","User can approve/deny each escalation"]},{"name":"Permission Escalation","description":"Request additional permissions when needed","userFlow":["User tries to list NFT","dApp detects signing permission needed","Permission request explains why it's needed","User sees existing permissions for context","User grants additional permission","Action proceeds"]},{"name":"Permission Management Dashboard","description":"Inspect and present the wallet's returned permissions; management actions depend on wallet support","userFlow":["User opens wallet settings","Sees list of connected sites","Each site shows granted permissions","User can revoke or disconnect only when the wallet exposes that control","Or fully disconnect site"]},{"name":"Permission Request with Context","description":"Explain why each permission is needed","userFlow":["Permission needed for user action","Wallet shows what permission does","dApp provides context (why needed)","User can learn more if unsure","Informed decision to grant or deny"]}],"uiComponents":[{"name":"PermissionRequestModal","description":"Modal showing permission being requested","states":["requesting","approved","denied","expired"],"props":["permissions[]","site","context","onApprove","onDeny"]},{"name":"PermissionBadge","description":"Visual indicator of permission type","states":["view","sign","transact","advanced"],"props":["permissionType","granted","canRevoke"]},{"name":"ConnectedSiteCard","description":"Card showing site with its permissions","states":["connected","limited","full-access"],"props":["site","permissions[]","connectedAt","onDisconnect"]},{"name":"PermissionToggle","description":"Toggle for a wallet-supported permission change.","states":["granted","revoked","pending","required"],"props":["permission","enabled","canRevoke","onChange"]},{"name":"CapabilityExplainer","description":"Explains what a permission allows","states":["collapsed","expanded"],"props":["permission","description","risks","examples"]}],"antiPatterns":[{"pattern":"Requesting all permissions upfront","why":"Users don't understand why you need everything, reduces trust","instead":"Request minimal permissions first, escalate only when needed","severity":"critical"},{"pattern":"No explanation for why permission is needed","why":"Users deny requests they don't understand","instead":"Provide clear context: \"Needed to list your NFT for sale\"","severity":"high"},{"pattern":"Breaking the app when permission denied","why":"Users feel forced to grant everything","instead":"Gracefully degrade, show what features require the permission","severity":"high"},{"pattern":"Not showing current permission state","why":"Users forget what they granted, feel out of control","instead":"Show active permissions in settings or footer","severity":"medium"},{"pattern":"Using technical permission names","why":"\"eth_signTypedData_v4\" means nothing to users","instead":"Say \"Sign messages\" with explanation of what that enables","severity":"medium"},{"pattern":"No way to revoke without full disconnect","why":"Users lose all access to revoke one thing","instead":"Expose wallet-supported revoke or disconnect controls, and explain when the permission model offers no individual revocation","severity":"medium"}],"keyTakeaways":["Request only permissions needed for the next action.","Explain the returned caveats and capability scope in human language.","Feature-detect wallet_getPermissions and wallet_requestPermissions.","Treat expiry and revocation UI as wallet and implementation-specific.","Gracefully handle denied or unsupported permission requests."],"technicalNotes":"EIP-2255 adds wallet_getPermissions and wallet_requestPermissions. A permission response can include arbitrary caveats, but the EIP does not mandate a revocation RPC, expiry field, or wallet UI. Support varies by wallet and permission method; feature-detect methods and render controls from the returned model.","lastUpdated":"2026-09-18","sources":[{"label":"EIP-2255 official specification","url":"https://eips.ethereum.org/EIPS/eip-2255","type":"official-spec"}],"lastReviewed":"2026-09-18"},"sources":[{"label":"Official specification","url":"https://eips.ethereum.org/EIPS/eip-2255","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=EIP-2255","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/EIP-2255","markdown":"https://www.eipsfordesigners.com/standards/EIP-2255/content.md","agent":"https://www.eipsfordesigners.com/standards/EIP-2255/agent.md","api":"https://www.eipsfordesigners.com/api/standards/EIP-2255","official":"https://eips.ethereum.org/EIPS/eip-2255","discussion":"https://ethereum-magicians.org/search?q=EIP-2255"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}