Skip to main content

Extending Deployed Contracts with LSP17

Adding new capability to a contract after deployment usually means an upgrade key someone has to hold forever, or a diamond-storage layout everyone has to get right. LSP17 Contract Extension takes a third path: the base contract's fallback resolves an incoming function selector against an ERC725Y-keyed registry of extension addresses and forwards the call. New capability ships as a new extension contract plus a permission-gated setData call β€” no admin upgrade key, no shared storage, no diamond-cut ceremony.

The stack​

StandardRole
LSP17The fallback router on the base contract
Extension contractsOne per new function selector you want to add
LSP14Safer ownership rotation for whoever can register extensions
LSP6Governs the permission to write the registration key, when the registrant is a Universal Profile controller

When this vertical fits​

You're shipping a contract that will need to grow over time β€” new asset receivers, new signature verifiers, new app-specific entry points β€” without ever surrendering a permanent upgrade key over the base bytecode. Or you're extending a Universal Profile with custom behavior that should be registered per-profile rather than coded directly into the account contract.

A Universal Profile is the canonical use case, but LSP17 is a general primitive β€” any contract can adopt the same fallback-and-registry pattern.

The structural guarantee

Known functions always execute as immutable base bytecode. Only unknown selectors ever hit the fallback and route to a registered extension β€” so there's no path back to silently rewriting behavior the base contract already has, unlike a diamond's permanent diamondCut authority.

Related reading: ERC2535 Diamonds vs LSP17 Β· The contract-extension problem