smart contract wallet permissions
Wallets don't know how to ask for less.
Connect a dapp and it gets the whole account. Session scoping isn't standard.
wallet_signTransaction(tx) permissions[controller] + allowedCalls[controller] If you're dealing with smart contract wallet permissions, the LUKSO route is LSP6 + LSP20. LSP6 assigns each controller a permission bitfield plus optional allowed calls (target + standard + selector) and allowed data keys. Granting a session controller is one tx. Revoking it is one tx. Scope is enforced on-chain.
Why this breaks
EOAs sign every action with the same key. Even most smart wallets expose the full account on connect, because there is no standard way for a dapp to ask for narrower authority.
When fine-grained authority does exist, it usually lives in custom validator code per wallet. Interoperability is poor. Revocation tends to be all-or-nothing.
What people try
Argent session keys
Temporary signing keys with scoped allowed contracts. Vendor-specific.
ERC-4337 validation modules
Pluggable validators define what each key may do. Standardizes the mechanism, not the policy vocabulary.
Zodiac scope guards on Safe
Module-level gating. Complex to author. Scoped to Safe accounts.
Off-chain delegation (capabilities, signed permissions)
Flexible. Enforcement depends on the relayer believing the capability.
How LSP solves it
LSP6 Key Manager assigns each controller a permission bitfield (CALL, SETDATA,
TRANSFERVALUE, ADDCONTROLLER, SIGN, …) plus optional allowed calls (target contract +
standard interface + function selector) and allowed ERC-725Y data keys.
Controller: app session key 0xabc...
Permission: CALL
AllowedCalls:
- target: 0x<token>, standard: LSP7, selector: transfer
Expires: app-defined session policy
Granting an app a session controller is one transaction. Revoking it is one transaction. The Universal Profile checks permissions on every call, so the scope is enforced on-chain, not at the wallet UI layer where it can be bypassed.