migration · Safe → LSP·0

Migrate Safe to LSP·0 on Ethereum/EVM

Step 1 — model the Safe as permissions

Take your Safe’s owner set and threshold and translate it into LSP6 vocabulary. A threshold of “3 of 5” doesn’t directly exist in LSP6 (controllers are individual, not aggregated). Two patterns:

  • Recovery contract — deploy a contract that enforces the threshold and is itself registered as the controller with EDITPERMISSIONS on the profile. Day-to-day controllers do day-to-day work; the recovery contract handles ownership-level changes.
  • Day-to-day single controller + cold multisig — flatten the daily workflow to one controller; keep the Safe (or a new threshold contract) as the cold recovery layer.

Step 2 — deploy the Universal Profile

Use the standard lsp-factory.js or equivalent deploy script. Set LSP3 profile metadata. Add controllers per the design from step 1.

Step 3 — transfer assets

For each asset class:

  • Native LYXSafe.execTransaction → profile.execute(0, profile, value, "")
  • ERC-20 / LSP7Safe → token.transfer(profile, balance)
  • NFTsSafe → token.safeTransferFrom(safe, profile, id) (or LSP8 equivalent)

If the Safe holds many assets, write a sweep contract that batches the transfers.

Step 4 — update integrations

Identify every protocol that knows the Safe’s address: vesting contracts, multi-sig DAOs, subscriptions, allowance grants. Update each one to point to the new profile address.

Step 5 — sunset the Safe

Once nothing material lives in the Safe, transfer its remaining gas dust out and consider it historical. Leave it deployed — destroying multisig contracts is unsupported and dangerous.

Gotchas.

  • Multi-sig threshold semantics don't map 1:1 to LSP6 — model it as a recovery controller contract that enforces the threshold and is itself registered as an LSP6 controller with EDITPERMISSIONS.
  • Asset transfer is many separate transactions unless the Safe owns the assets through a sweep contract that batches outbound moves.
  • Anything connected to the Safe's address (vesting schedules, allowance grants, on-chain memberships) needs to be re-pointed to the new profile address — addresses don't migrate, the references do.
  • Safe modules have their own permission shape; LSP6 controllers + LSP17 extensions are the LSP-side equivalents. Map each module to its closest LSP primitive deliberately.

Verify before ship.

  • All assets transferred to the Universal Profile
  • Old Safe paused (no longer holds material assets)
  • Controllers + permissions configured on the new profile
  • Recovery policy in place — at least one cold controller with EDITPERMISSIONS
  • Off-chain integrations updated to the new address

Continue at docs.lukso.tech.