problem · smart contract wallet permissions

smart contract wallet permissions

Wallets don't know how to ask for less.

ERC-4337 LSP·6 LSP·20

Connect a dapp and it gets the whole account. Session scoping isn't standard.

EOA wallet_signTransaction(tx)
full account every time
LSP·6 permissions[controller] + allowedCalls[controller]
per-controller per-call revocable
LUKSO route

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.

continue at the source