Migrate ERC-721 to LSP·8 on Ethereum/EVM
Step 1 — decide the ID encoding
ERC-721 uses uint256. LSP8 uses bytes32. The trivial case is bytes32(uint256(tokenId)).
The interesting cases are content-hash IDs (keccak256(mintInputs)), structured serials
(abi.encodePacked(season, edition, index)), or external references
(abi.encodePacked(otherContract, otherTokenId)). Pick the encoding once — it’s hard to
change later.
Step 2 — map the metadata model
For each piece of metadata, decide where it lives:
- Collection-level (name, symbol, description) → LSP4 keys under ERC-725Y on the contract
- Per-token static (mint inputs, attributes at mint) → LSP8 per-token data keys
- Per-token dynamic (levels, traits that change) → LSP8 per-token data keys, written by permissioned controllers
- Off-chain media → URI (with VerifiableURI when integrity matters)
Step 3 — pick the migration path
- Fresh mint — LSP8 contract, snapshot the ERC-721 holders, mint LSP8 tokens with the same ID encoding. Cleanest. Original collection becomes a historical artifact.
- Wrap — LSP8 wrapper backed by ERC-721 escrow. Reversible. Adds deposit/withdraw flows.
- Side-by-side — both live. Usually not the answer for NFTs.
Step 4 — handle the receivers
Every downstream that previously implemented IERC721Receiver needs to also implement LSP1
universalReceiver if you want the LSP8 transfers to use force=false. Decide per
integration.
Step 5 — write the per-token data
For dynamic collections: the migration is when you load the current state of every dynamic trait into the new LSP8 contract. Don’t ship the migration without a permissioned writer designed to keep that state correct going forward.
Gotchas.
- Mainnet marketplaces (OpenSea, Blur) don't speak LSP8 today. Migration usually means moving to the LUKSO marketplace ecosystem.
- Casting uint256 → bytes32 is fine, but think about whether the new IDs should encode something semantic.
- Per-token ERC-725Y data is storage. Dynamic updates cost gas.
- Holders mapping migration via snapshot mint changes the original mint history. Keep audit trail.
Verify before ship.
- ownerOf for every token matches pre-migration snapshot
- tokenURI equivalents resolved via getDataForTokenId
- LSP4 collection metadata returns expected JSON
- Universal Profile recipients receive LSP1 hooks on transfer
- Existing on-chain references (staking, vaults) updated to LSP8 ABI