Replicating a Universal Profile Across EVM Chains

How to deploy your existing LUKSO Universal Profile at the identical address on another EVM chain — and why it works.

What this is. Your Universal Profile (UP) was created on LUKSO through a deterministic factory contract. Because the factory is deployed at the same address on every EVM chain, replaying your exact original creation transaction on another chain produces a contract at the same address there too. This page explains the mechanism and walks through doing it safely, using the companion tools linked at the bottom.

This is a technical procedure. It assumes you're comfortable with MetaMask, smart contracts, and reading a block explorer. It is not a "one click" consumer flow, and it shouldn't be treated as one.

How the address is actually generated

It is not a simple function of "controller + salt". Your UP was created via LUKSO's LSP23LinkedContractsFactory, deployed at the same address (0x2300000A84D25dF63081feAa37ba6b62C4c89a30) on every chain where LUKSO has published it. The factory call includes:

All of this is hashed together (keccak256) to form the real salt used in CREATE2, combined with the hash of the minimal-proxy bytecode pointing at the Universal Profile implementation. The resulting address depends on the entire original transaction — not on any single field in isolation.

This is why only the exact original calldata reproduces the same address: the controller with full control isn't special on its own — it's simply the address that particular calldata already names. Change the calldata (even to name a different controller) and you get a different address entirely.

Step by step

1

Extract your private key

You'll need this key later, in step 8, to operate your profile on the new chain — it's simplest to get it out of the way first. Unlock the Universal Profile browser extension, click the gear icon (Settings) top-right, scroll all the way down to the Developer section, and click Reveal private key. Enter your extension password when asked, and the key is shown as plain text.

UP extension settings, Developer section, Reveal private key button
Settings → scroll to "Developer" → "Reveal private key".
This key is your profile. Whoever has it owns your Universal Profile — on LUKSO and on every chain where you redeploy it — and can move every asset it holds, change its controllers and lock you out. There is no recovery and no one can reverse it.
  • Never type or paste it into a website — including this one and the tools linked here: none of them will ever ask for it. The only place it goes is the "import account" screen of your own wallet, in step 8.
  • Never send it to anyone: not in chat, email, Telegram, Discord or support tickets. Real support (ours included) will never ask for a private key, seed phrase or backup password — anyone who does is trying to steal your funds.
  • Don't store it in plain text: no screenshots, photos, notes apps, documents, cloud drives or messages to yourself. Keep it only in a password manager or offline (on paper, in a safe place).
  • Handle it on a trusted device only: not on a shared or work computer, and not with screen sharing or remote-desktop sessions open. After copying it, clear the clipboard (copy something else) and close the extension panel.
  • If you think it has been exposed, act immediately: move your assets to a safe account and replace the compromised controller (add a new one, then remove the old one) on LUKSO and on every chain where the profile exists — each chain has its own permissions, a fix on one does not protect the others.
2

Find your UP's original creation transaction

Open your UP's address on the LUKSO mainnet explorer, on its Details tab. Find the Creator row — it shows the creator's address "at txn" followed by a transaction hash. Click that transaction hash link: it takes you straight to the creation transaction.

Contract details page with the Creator row showing 'at txn' followed by the creation transaction hash link
On the Details tab, the "at txn" link next to Creator is the shortcut straight to the creation transaction — no need to scroll through the transaction list.

Once you're on that transaction's page, switch to its Raw trace tab.

Transaction details page showing method deployERC1167Proxies and the Raw trace tab
The creation transaction: method deployERC1167Proxies, sent to the factory address. Open "Raw trace" from here.
This is public on-chain data. You don't need your wallet's backup file or any decryption to get it — anyone can look up any UP's creation transaction.
3

Copy the transaction's input data

In the raw trace, find the call field (the raw hex, starting with 0x6a66a753...). Copy the whole string. This is your deployment calldata.

Tip: double-click anywhere on the hex string to select it entirely, then copy — much faster than dragging to select such a long string.
Raw trace tab showing the call field with the deployment calldata
The raw trace: the call field is the deployment calldata.
4

Connect your UP to the Deploy tool

Open the Deploy tool and click Connect your Universal Profile in panel 1. Approve the connection in the extension popup — this only reads your address, it never asks for a private key. Once connected, the tool shows your address and pre-fills the "expected address" field with it.

Deploy tool showing the Universal Profile connected, with its address filled in automatically
Once connected, your UP's address appears here — this is what the decoded calldata will be checked against.
5

Decode it and identify the controller

Paste the calldata you copied in step 3 into the same page. It will show you the address this calldata predicts for your UP on any chain, and — critically — it will decode and display every controller named in the calldata, including which one gets ALL_PERMISSIONS.

Deploy tool showing the decoded controllers, one flagged as system infrastructure and one with ALL_PERMISSIONS
The tool separates known system infrastructure (green) from the actual controller with ALL_PERMISSIONS (red) — that second one is what you need to hold the key for.
Compare the predicted address to your actual UP address on LUKSO. They must match exactly before you go any further. If they don't, something is wrong with the calldata you copied — stop and re-check step 3.
6

Confirm it's the controller shown by your extension

The tool shows the address that receives ALL_PERMISSIONS — this is called the controller address, because it's the account that will control the profile after the deploy. The check to make here isn't generically "does this match the key I extracted" — it's whether this is the same account that your Universal Profile browser extension itself labels as the controller for this profile, and that this is the very account you extracted the private key from in step 1 (not a different one also sitting in the extension). If your Universal Profile has ever had more than one controller connected to it over time (for example, from reinstalling a wallet extension, or connecting a new device), make sure it's this specific controller — the one the extension shows for this profile — not just "a" controller that currently has access. They can look functionally identical (same permissions) while only one of them reproduces the same address on another chain.

The controller address shown by the deploy tool matches the controller shown by the wallet extension for this profile
Cross-check: the ALL_PERMISSIONS address the tool found matches the address your own wallet extension shows as the controller of this specific profile — same string, character for character.
If the address doesn't match the controller shown by your extension, stop here. Proceeding without the right key means deploying a profile you won't be able to operate.
7

Deploy on the destination chain

Still on the Deploy tool: connect any wallet to pay gas (it does not need to be the controller — it only pays the transaction fee), select the destination network, and run the built-in checks. The tool verifies the predicted address again, checks nothing already exists there, estimates gas, and — after the transaction confirms — verifies the deployed bytecode matches exactly before calling it a success.

8

Operate your profile on the new chain

Import the private key you extracted in step 1 into MetaMask (or your wallet of choice) — this is standard "import account" functionality in any wallet. From there, use the Test tool to confirm the controller actually operates the profile — it writes a timestamp on-chain through the Key Manager and reads it back. Once that works, you can also use the Send tool to transfer native currency from the profile to another address, signed by that same controller.

Importing the key puts your whole profile inside that wallet. The same key also controls your profile on LUKSO, so a compromise of this wallet is a compromise of the profile everywhere.
  • Import it into a dedicated wallet or browser profile, protected by a strong password, with no untrusted extensions installed — ideally not the wallet you use every day to connect to dApps.
  • Before signing anything, check the network, the recipient and the amount shown in the wallet popup, not only on the page.
  • Never sign requests you didn't start yourself, and disconnect sites you no longer use.
  • When you no longer need to operate the profile from this wallet, remove the imported account from it.
💡 Funds: two addresses, both yours — don't forget the controller. One is a smart contract account (the UP), the other a normal wallet (the controller, an EOA): different addresses, but both under your control.
Two different connections, two different jobs — this trips people up. On the Test and Send tools, "Connect your Universal Profile" only reads your UP's address, on LUKSO, so you don't have to copy-paste it — no signature happens there. The wallet that actually operates the profile is the second connection, the "signing wallet" (MetaMask with the imported controller key), and it must be connected to the destination chain — the network where you redeployed the profile in steps 6–7 — not to LUKSO. It's completely normal to have both the UP extension and MetaMask active in the same browser at once: each one does a different job, on a different network. Both tools show you which network the signing wallet is currently on, right next to its address, and refuse to send anything if the wallet, the RPC and the network you selected are not the same chain — still, check it yourself before doing anything.

What these tools do — and don't do

This is irreversible, self-directed on-chain activity. No one — including the tools linked here — can undo a deployment or a transfer once confirmed. Use a small amount of funds to test first, on a network where mistakes are cheap.

Tools

Replicare una Universal Profile su altre chain EVM

Come deployare la tua Universal Profile LUKSO esistente allo stesso identico indirizzo su un'altra rete EVM — e perché funziona.

Di cosa si tratta. La tua Universal Profile (UP) è stata creata su LUKSO tramite un contratto factory deterministico. Poiché la factory è deployata allo stesso indirizzo su ogni rete EVM, ripetere esattamente la transazione di creazione originale su un'altra rete produce un contratto allo stesso indirizzo anche lì. Questa pagina spiega il meccanismo e guida attraverso il procedimento in sicurezza, usando gli strumenti collegati in fondo.

È una procedura tecnica. Presuppone dimestichezza con MetaMask, gli smart contract e la lettura di un block explorer. Non è un flusso consumer "a un click" e non va trattata come tale.

Come viene generato davvero l'indirizzo

Non è una semplice funzione di "controller + salt". La tua UP è stata creata tramite LSP23LinkedContractsFactory di LUKSO, deployata allo stesso indirizzo (0x2300000A84D25dF63081feAa37ba6b62C4c89a30) su ogni rete dove LUKSO l'ha pubblicata. La chiamata alla factory include:

Tutto questo viene hashato insieme (keccak256) per formare il salt reale usato in CREATE2, combinato con l'hash del bytecode minimal-proxy che punta all'implementazione della Universal Profile. L'indirizzo risultante dipende dall'intera transazione originale — non da un singolo campo isolato.

Per questo solo la calldata originale esatta riproduce lo stesso indirizzo: il controller con il controllo totale non ha nulla di speciale in sé — è semplicemente l'indirizzo che quella specifica calldata già nomina. Cambiare la calldata (anche solo per nominare un controller diverso) produce un indirizzo completamente diverso.

Passo per passo

1

Estrai la tua chiave privata

Ti servirà più avanti, al passo 8, per operare il profilo sulla nuova rete — conviene toglierla di mezzo subito. Sblocca l'estensione Universal Profile, clicca sull'icona a rotella (Settings) in alto a destra, scorri fino in fondo alla sezione Developer e clicca Reveal private key. Inserisci la password dell'estensione quando richiesto: la chiave viene mostrata in chiaro.

Impostazioni dell'estensione UP, sezione Developer, pulsante Reveal private key
Settings → scorri fino a "Developer" → "Reveal private key".
Questa chiave è il tuo profilo. Chi la possiede controlla la tua Universal Profile — su LUKSO e su ogni rete dove la rideployi — e può spostare tutti gli asset, cambiarne i controller e chiuderti fuori. Non esiste recupero e nessuno può annullare l'operazione.
  • Non digitarla né incollarla mai in un sito web — compreso questo e gli strumenti collegati: nessuno di essi te la chiederà mai. L'unico posto dove va inserita è la schermata "importa account" del tuo wallet, al passo 8.
  • Non inviarla mai a nessuno: né in chat, email, Telegram, Discord o ticket di assistenza. La vera assistenza (compresa la nostra) non chiederà mai una chiave privata, una seed phrase o una password di backup — chi lo fa sta cercando di rubarti i fondi.
  • Non conservarla in chiaro: niente screenshot, foto, app di note, documenti, cloud o messaggi a te stesso. Tienila solo in un password manager oppure offline (su carta, in un luogo sicuro).
  • Maneggiala solo su un dispositivo fidato: non su un computer condiviso o di lavoro, e senza condivisione schermo o sessioni di desktop remoto aperte. Dopo averla copiata, svuota gli appunti (copia qualcos'altro) e chiudi il pannello dell'estensione.
  • Se pensi che sia stata esposta, agisci subito: sposta gli asset su un account sicuro e sostituisci il controller compromesso (aggiungine uno nuovo, poi rimuovi quello vecchio) su LUKSO e su ogni rete dove esiste il profilo — ogni rete ha i propri permessi, sistemarne una non protegge le altre.
2

Trova la transazione di creazione originale della tua UP

Apri l'indirizzo della tua UP sull'explorer di LUKSO mainnet, nella scheda Details. Trova la riga Creator — mostra l'indirizzo del creatore "at txn" seguito da un hash di transazione. Clicca su quel link dell'hash: ti porta direttamente alla transazione di creazione.

Pagina dei dettagli del contratto con la riga Creator che mostra 'at txn' seguito dal link all'hash della transazione di creazione
Nella scheda Details, il link "at txn" accanto a Creator è la scorciatoia diretta alla transazione di creazione — non serve scorrere l'elenco delle transazioni.

Una volta sulla pagina di quella transazione, passa alla scheda Raw trace.

Pagina dei dettagli della transazione con il metodo deployERC1167Proxies e la scheda Raw trace
La transazione di creazione: metodo deployERC1167Proxies, inviata all'indirizzo della factory. Da qui apri "Raw trace".
È dato pubblico on-chain. Non serve il file di backup del wallet né alcuna decrittazione per ottenerlo — chiunque può consultare la transazione di creazione di qualunque UP.
3

Copia l'input data della transazione

Nel raw trace, trova il campo call (l'esadecimale grezzo, che inizia con 0x6a66a753...). Copia l'intera stringa. Questa è la tua calldata di deploy.

Consiglio: fai doppio click in un punto qualsiasi della stringa esadecimale per selezionarla tutta, poi copia — molto più rapido che trascinare per selezionare una stringa così lunga.
Scheda Raw trace con il campo call che contiene la calldata di deploy
Il raw trace: il campo call è la calldata di deploy.
4

Connetti la tua UP allo strumento di Deploy

Apri la pagina di Deploy e clicca Connetti la tua Universal Profile nel pannello 1. Approva la connessione nel popup dell'estensione — questo passaggio legge solo il tuo indirizzo, non chiede mai una chiave privata. Una volta connesso, lo strumento mostra il tuo indirizzo e precompila il campo "indirizzo atteso" con quello.

Strumento di Deploy con la Universal Profile connessa e l'indirizzo compilato automaticamente
Una volta connesso, l'indirizzo della tua UP compare qui — è quello con cui verrà confrontata la calldata decodificata.
5

Decodificala e identifica il controller

Incolla la calldata copiata al passo 3 nella stessa pagina. Ti mostrerà l'indirizzo che questa calldata predice per la tua UP su qualsiasi rete e — punto cruciale — decodificherà e mostrerà ogni controller nominato nella calldata, incluso chi riceve ALL_PERMISSIONS.

Pagina di Deploy con i controller decodificati, uno segnato come infrastruttura di sistema e uno con ALL_PERMISSIONS
Lo strumento separa l'infrastruttura di sistema nota (verde) dal vero controller con ALL_PERMISSIONS (rosso) — di quest'ultimo devi possedere la chiave.
Confronta l'indirizzo predetto con l'indirizzo reale della tua UP su LUKSO. Devono coincidere esattamente prima di andare oltre. Se non coincidono, c'è qualcosa che non va nella calldata copiata — fermati e ricontrolla il passo 3.
6

Conferma che sia il controller indicato dalla tua estensione

Lo strumento mostra l'indirizzo che riceve ALL_PERMISSIONS — si chiama indirizzo del controller, perché è l'account che controllerà il profilo dopo il deploy. Il confronto da fare non è genericamente "corrisponde alla chiave che ho estratto" — è se questo è lo stesso account che la tua estensione del browser Universal Profile indica esplicitamente come controller di questo profilo, e che sia proprio quell'account (non un altro presente nell'estensione) da cui hai estratto la chiave privata al passo 1. Se la tua Universal Profile ha mai avuto più di un controller collegato nel tempo (ad esempio dopo aver reinstallato un'estensione wallet, o collegato un nuovo dispositivo), assicurati che sia proprio questo controller — quello che l'estensione mostra per questo profilo — non semplicemente "un" controller che al momento ha accesso. Possono sembrare funzionalmente identici (stessi permessi) mentre solo uno dei due riproduce lo stesso indirizzo su un'altra rete.

L'indirizzo del controller mostrato dallo strumento di deploy corrisponde al controller mostrato dall'estensione del wallet per questo profilo
Riscontro incrociato: l'indirizzo con ALL_PERMISSIONS trovato dallo strumento corrisponde all'indirizzo che la tua estensione wallet mostra come controller di questo specifico profilo — stessa stringa, carattere per carattere.
Se l'indirizzo non corrisponde al controller indicato dalla tua estensione, fermati qui. Andare avanti senza la chiave giusta equivale a deployare un profilo che non potrai gestire.
7

Deploya sulla rete di destinazione

Sempre sulla pagina di Deploy: collega un wallet qualsiasi per pagare il gas (non deve essere il controller — paga solo la commissione della transazione), scegli la rete di destinazione ed esegui i controlli integrati. Lo strumento riverifica l'indirizzo predetto, controlla che non esista già nulla lì, stima il gas e — dopo la conferma della transazione — verifica che il bytecode deployato corrisponda esattamente prima di dichiarare il successo.

8

Opera il tuo profilo sulla nuova rete

Importa in MetaMask (o nel wallet che preferisci) la chiave privata estratta al passo 1 — è la normale funzione "importa account" di qualsiasi wallet. Da lì usa la pagina di Test per confermare che il controller operi davvero il profilo — scrive un timestamp on-chain tramite il Key Manager e lo rilegge. Una volta verificato, puoi anche usare la pagina di Invio per trasferire valuta nativa dal profilo a un altro indirizzo, firmato dallo stesso controller.

Importare la chiave significa mettere l'intero profilo dentro quel wallet. La stessa chiave controlla il tuo profilo anche su LUKSO: se quel wallet viene compromesso, il profilo è compromesso ovunque.
  • Importala in un wallet o profilo del browser dedicato, protetto da una password robusta e senza estensioni non affidabili — possibilmente non il wallet che usi ogni giorno per collegarti alle dApp.
  • Prima di firmare qualsiasi cosa, controlla rete, destinatario e importo mostrati nel popup del wallet, non solo sulla pagina.
  • Non firmare mai richieste che non hai avviato tu, e scollega i siti che non usi più.
  • Quando non ti serve più operare il profilo da quel wallet, rimuovi l'account importato.
💡 I fondi: due indirizzi, tutti e due tuoi — non dimenticare il controller. Uno è un account smart contract (la UP), l'altro un normale wallet (il controller, un EOA): indirizzi diversi, ma tutti e due sotto il tuo controllo.
Due collegamenti diversi, due compiti diversi — qui è facile confondersi. Nelle pagine di Test e Invio, "Connetti la tua Universal Profile" serve solo a leggere l'indirizzo della tua UP, su LUKSO, così non devi copiarlo a mano — nessuna firma avviene in quel passaggio. Il wallet che opera davvero il profilo è il secondo collegamento, il "wallet firmatario" (MetaMask con la chiave del controller importata), e deve essere connesso alla rete di destinazione — quella dove hai rideployato il profilo ai passi 6–7 — non a LUKSO. È del tutto normale avere sia l'estensione UP che MetaMask attivi insieme nello stesso browser: ognuno fa un lavoro diverso, su una rete diversa. Entrambe le pagine mostrano su quale rete è connesso in questo momento il wallet firmatario, accanto al suo indirizzo, e si rifiutano di inviare qualsiasi cosa se wallet, RPC e rete selezionata non sono la stessa chain — controlla comunque tu stesso prima di fare qualsiasi cosa.

Cosa fanno questi strumenti — e cosa non fanno

Questa è un'attività on-chain irreversibile e autonoma. Nessuno — inclusi gli strumenti qui collegati — può annullare un deploy o un trasferimento una volta confermato. Prova prima con un importo piccolo, su una rete dove gli errori costano poco.

Strumenti