Move XLS-20 NFTs from the XRP Ledger to the XRPL EVM sidechain — with no XRPL amendment, no governance, and no registry.
Nobody has done this. Not because it is impossible, but because the two obvious routes are structurally closed:
- XLS-38
XChainBridgetypes every asset as a(currency, issuer)pair. NFTs are unrepresentable in its type system — zero mentions across 59 KB of specification. The amendment also is not enabled on mainnet (4 of 35 validators, threshold 28). - Axelar, the canonical XRPL ↔ XRPL EVM bridge, has a prover whose transaction enum is exactly
{Payment, SignerListSet, TicketCreate, TrustSet}. It cannot construct anNFTokenAcceptOffer, so it cannot take an NFT into custody at any price.
This repo contains a design that works anyway, the research proving it works, and a roadmap to build it.
Invert the usual arrangement. Treat the XRP Ledger as a dumb vault and an append-only log, and put all bridge state on the EVM side where arbitrary code already runs. A single multisig "door" account holds deposited NFTs and nothing else — no bridge-specific ledger objects, no new transaction types, no amendment required, because every primitive needed already shipped years ago. On the EVM side lives everything that thinks: a per-NFT lock/release state machine, an epoched k-of-n signer set, replay guards, and ERC-721 wrappers deployed at CREATE2 addresses derived arithmetically from (issuer, taxon) — so listing a new collection requires no registration, no approval, and no admin. It is a pure function. A user deposits by making a 0-drop sell offer to the door; witnesses observe the validated ledger, apply a published admission policy, multisign the door's accept, and sign an EIP-712 attestation that mints the wrapper.
The NFTokenID maps into an ERC-721 tokenId 1:1 with no mapping table — 256 bits into 256 bits, losslessly. That is precisely the mismatch that killed Wormhole's NFT bridge (Solana's u64 IDs versus Ethereum's uint256), and on this route it simply does not exist.
The honest case is a bet, and it is worth stating as one rather than dressing it up.
Today the XRPL NFT market is small. Roughly 350 priced trades per day, a median sale near 12 XRP, on the order of $250k/month of GMV. A bridge that has to fund a trust-minimised signer set purely from toll revenue does not close at that size. Earlier drafts of this repo concluded from that fact that the project was dead.
That conclusion assumed the wrong business model and the wrong cost base. Two things change it:
- The toll is not the revenue — the destination is. An NFT bridged to an EVM chain trades on an EVM marketplace, and keeps trading there. Whoever operates that venue captures a fee on every subsequent sale, indefinitely, on supply their bridge brought over. The bridge can run at cost as a supply pipeline. (
docs/06-thesis.mdmodels this.) - Trust should scale with TVL, not precede it. The original cost model assumed a $2,430/month 7-of-9 HSM signer set from day one, against a market that does not yet justify it. Start capped and clearly labelled, and the same design starts at roughly $100/month — moving break-even from ~2,542 bridges/month to ~180.
That is a bet on the market growing and on capturing the destination, not a claim that today's numbers already work. Read docs/05-open-questions.md §3 before you believe any of it — the kill criteria are written down deliberately, while walking away is still cheap.
Not asserted — measured, against live mainnet, reproducibly:
NFTokenID codec |
8,385/8,385 exact, decode and round-trip re-encode. Run it yourself: python3 reference/nftokenid_codec.py |
tokenId mapping |
Lossless and collision-free; no reserved values in EIP-721 |
| Page density | ≈69% fill, ≈22 NFTs per page — converges on ln 2 because rippled deliberately scrambles the taxon. Reproduced from two disjoint sampling frames (57,260 and 8,512 NFTs) |
| Reserve cost | 0.0091 XRP (~$0.010) per bridged NFT — 174× smaller than opex, i.e. not the constraint |
| XLS-38 cannot serve this | Zero NFT support in the spec; amendment not enabled on mainnet |
| Axelar cannot serve this | Prover cannot emit NFTokenAcceptOffer |
| CREATE2 substitution is impossible | 2¹⁶⁰ preimage resistance; EIP-6780 closes metamorphism |
Stated plainly, because finding these late is how bridges die:
| Risk | Status |
|---|---|
| Any k of n signers can take everything in the door, instantly and irreversibly | Irreducible on this ledger. No protocol mitigation exists. The only real answers are capped TVL, genuinely independent operators, or not custodying at all |
| Coordinator-free byte-determinism — n witnesses must build byte-identical XRPL transactions or no quorum forms | Never been run. This is the gate. T1 is two days of work and it decides the architecture |
Royalty bypass — bridging pays no TransferFee |
Undecided. Plausibly the biggest demand driver and the biggest legal exposure at once. docs/06-thesis.md §5 proposes turning it into a feature |
| Demand | Never tested. No waitlist has ever been run |
| Mutable URIs | DynamicNFT is live on mainnet — a tfMutable NFT's metadata can be rewritten by its issuer after bridging. Screenable from the ID, but real |
git clone <this repo> && cd xrpl-nft-bridge
python3 reference/nftokenid_codec.py # ~30s, hits mainnet, must exit 0| If you are… | Read |
|---|---|
| an AI agent picking this up | AGENTS.md — invariants, task queue, acceptance criteria |
| deciding whether to build | docs/00-README.md → docs/06-thesis.md → docs/05-open-questions.md §3. Twenty minutes |
| implementing | docs/07-roadmap.md → docs/02-wire-spec.md. Implement against the wire spec, never against prose |
| reviewing security | docs/04-threat-model-and-ops.md §0 and §6 |
| Doc | What it is |
|---|---|
docs/00-README.md |
Orientation and reading order |
docs/01-architecture.md |
The design. §3, §6.5, §7.1 |
docs/02-wire-spec.md |
Normative byte-level spec — the thing to implement |
docs/03-economics.md |
Unit economics and measured market data |
docs/04-threat-model-and-ops.md |
Threats, runbook, launch gates |
docs/05-open-questions.md |
Every unknown, ranked — plus kill criteria |
docs/06-thesis.md |
Why this is worth building; phased trust model |
docs/07-roadmap.md |
Discrete tasks with acceptance criteria |
docs/data/ |
Raw measurements and reproduction commands |
This is deliberately public and deliberately permissive. If you want to build it, build it — no permission needed, no attribution required beyond the licence. If you get the determinism harness (T1) working, that alone is a genuine contribution to XRPL infrastructure whether or not the rest ever ships.
Two requests, neither enforceable: do not custody other people's assets until the launch gates in docs/04 §6 are met, and if you find something in here that is wrong, open an issue. Several claims in earlier drafts were confidently stated and false; they were caught by adversarial review and are corrected in place. Assume more remain.
MIT. See LICENSE.