Grant a dApp Less Than the Whole Account
Connect most wallets to a dApp and the dApp effectively gets the whole account β there's no standard way to ask for less. Session-key systems exist, but each ships as a different vendor SDK with its own validator shape, so nothing is portable across wallets. LSP6 Key Manager makes scoped access a standard, on-chain vocabulary every Universal Profile speaks: a permission bitfield per controller, plus optional allowed calls (target, standard, selector) and allowed ERC725Y data keys. Granting a narrow session controller is one transaction. Revoking it is one transaction. And because the profile checks permissions on every call, the scope is enforced on-chain β not just hidden behind a wallet UI that a compromised frontend could ignore.
Before / afterβ
| Model | Scope granularity | Enforced where | Portable across wallets |
|---|---|---|---|
| Default wallet connect | full account | nowhere β the dApp gets whatever it asks the user to sign | n/a |
| Argent session keys | per-contract allowlist | wallet-specific validator | no |
| ERC-4337 validation modules | pluggable per wallet | validator contract | mechanism is standard, policy is not |
| Zodiac scope guards (Safe) | module-level | Safe module | Safe-only |
| LSP6 Key Manager | permission bitfield + allowed calls + allowed data keys | the account contract itself | every Universal Profile |
Why "connect wallet" defaults to full accessβ
EOAs sign every action with the same key, so there's no narrower unit of authority to hand out in the first place. Even most smart wallets expose the full account on connect, because there's no standard way for a dApp to ask for something less than everything. When fine-grained authority does exist today, it usually lives in custom validator code written per wallet β interoperability is poor, and revocation tends to be all-or-nothing rather than scoped to the one controller that should lose access.
What people try todayβ
Argent session keys issue temporary signing keys scoped to an allowed-contract list, but the mechanism is vendor-specific to Argent's wallet. ERC-4337 validation modules make pluggable validators possible, which standardizes the mechanism for defining what a key may do, without standardizing the policy vocabulary itself β every wallet SDK still defines its own shape. Zodiac scope guards on Safe gate access at the module level, which is powerful but complex to author and scoped entirely to Safe accounts. Off-chain delegation via signed capability objects is flexible, but enforcement depends entirely on the relayer honoring the capability β there's no on-chain check backing it up.
How LSP6 makes scope a standard vocabularyβ
LSP6 Key Manager assigns each controller a permission bitfield β CALL, SETDATA, TRANSFERVALUE, ADDCONTROLLER, SIGN, and more β plus optional allowed calls (target contract, standard interface, function selector) and allowed ERC725Y data keys:
Controller: app session key 0xabc...
Permission: CALL
AllowedCalls:
- target: 0x<token>, standard: LSP7, selector: transfer
Granting an app a session controller is one transaction. Revoking it is one transaction. The Universal Profile checks permissions on every call through LSP20, so the scope is enforced on-chain, not at a wallet UI layer that a malicious or compromised frontend could bypass. Core LSP6 has no controller-expiry field β a controller's permissions stay live until someone explicitly revokes them in a transaction. An app can layer its own off-chain "session" convention on top (e.g. stop using a key after N hours), but that's an app-level policy, not something the account itself enforces; a direct call with that controller's key still works until the on-chain permission is actually revoked.
A Universal Profile lets a dApp request exactly the permission it needs β one token, one function, one target contract β instead of defaulting to full account access just because there was no standard way to ask for less.
Related reading: The ERC-20 approval problem Β· Social recovery without a seed phrase Β· The EOA key-risk problem Β· Grant controller permissions Β· Get controller permissions