Swap ETH and LEZ tokens in Logos Basecamp
Install the atomic swap app from a catalogue URL and trade Sepolia ETH for LEZ testnet tokens with a counterparty you never have to trust.
The atomic swap app is a Logos Basecamp app that trades tokens across two unrelated chains without an exchange, a bridge, or an escrow agent. This procedure takes you from a fresh Basecamp install to a completed swap against a live counterparty that Logos operates, ending with a receipt you can check on both chains' block explorers.
You install this app from a catalogue URL rather than building it. There's no repository to clone, no Nix, and no local chain. One part still isn't as smooth: on the currently published version, creating your LEZ account in Step 3 needs a command-line tool. That step says so plainly, and a release that removes the need is on the way.
Networks and addresses
The app ships with these values already filled in. They're listed here so you can check them, and so you can restore one if you change it by mistake.
| Setting | Value |
|---|---|
| Catalogue URL | https://raw.githubusercontent.com/logos-co/eth-lez-atomic-swaps/master/logos-repo.json |
| Ethereum RPC | wss://ethereum-sepolia-rpc.publicnode.com |
| Ethereum HTLC contract, on Sepolia | 0x351B0EA07739FA9F6769213927D7836a790A5FAF |
| LEZ sequencer | https://testnet.lez.logos.co |
| LEZ HTLC program | 27720b5b0345135d8e684eb172c27f5fb237548cc891a3ec889d0ed340504070 |
| Ethereum explorer | https://sepolia.etherscan.io/tx/<TX_HASH> |
| LEZ explorer | https://explorer.testnet.lez.logos.co/transaction/<TX_HASH> |
The Ethereum RPC must use the wss:// scheme. The app subscribes to contract events over a WebSocket, so an https:// URL fails to connect even though the same host serves ordinary calls happily.
How an atomic swap works
A swap is a trade between two people who have no reason to trust each other. One holds LEZ testnet tokens, the other holds Sepolia ETH, and neither wants to send first. An atomic swap removes that problem: either both transfers happen, or neither does.
The mechanism is a hash time-locked contract, or HTLC. Your app invents a random secret, called a preimage, and locks your ETH in a contract on Sepolia that releases only to whoever presents that secret. Your counterparty sees the lock and makes a matching lock of their LEZ against the hash of the same secret. You then claim their LEZ, which publishes the secret on the LEZ chain as a side effect. Your counterparty reads it there and uses it to claim your ETH. Both legs settle, and neither of you ever handed over funds on trust.
The time locks make the failure case safe. Each lock carries a deadline, and yours is deliberately the longer of the two, so you always have time to react to whatever your counterparty does. If they vanish after you lock, nothing is lost. You wait for your deadline to pass and take your own funds back from the Refund tab. In the offer you'll take below, the LEZ side expires after 20 minutes and your Ethereum side after 40.
Before you begin
Make sure you have:
- A supported platform: macOS on Apple silicon, Linux x86-64, or Linux arm64.
- Internet access.
- A small amount of Sepolia ETH. The trade itself costs
0.00001ETH, so roughly0.01Sepolia ETH covers it and the gas comfortably. Any public Sepolia faucet works, and the Ethereum networks documentation lists current options. - An Ethereum wallet such as MetaMask, used in Step 3 to create a throwaway key.
- Rust and
cargo, from rustup, plus a terminal. Step 3 builds the LEZ wallet CLI to create your LEZ account. A future release removes this requirement.
Intel macOS isn't supported. The app bundles zero-knowledge circuits for its LEZ side, and no darwin-x86_64 build of that bundle is published.
You don't need any LEZ to begin. You claim your opening balance from the LEZ testnet faucet in Step 3.
What to expect
- You can add a third-party catalogue to Basecamp and install an app from it.
- You can set up a funded Ethereum key and an initialised, funded LEZ account, and point the app at both.
- You can take a live offer and complete a real cross-chain swap on public test networks.
- You can verify both legs of your swap independently on two block explorers.
Step 1: Install Logos Basecamp
Follow Install Logos Basecamp and take the prebuilt release for your platform. You don't need the source build.
Expected: Basecamp opens with a sidebar down the left-hand side. The UI labels used below come from Basecamp 0.2.2, and 0.2.3 is the current release.
Step 2: Add the catalogue and install the app
Basecamp arrives with the official Logos catalogue configured, and it merges that built-in catalogue with any you add yourself. The atomic swap app is published from its own repository, so you add its catalogue first. A catalogue is a small JSON file naming an index of packages, and Basecamp re-reads it whenever the index changes.
-
In the sidebar, click Package Manager, then click Repositories in the toolbar.
This opens Settings at the Package Repositories page, which lists the repositories you're drawing packages from.
-
Under Add a repository, paste this URL into the field and click Add:
https://raw.githubusercontent.com/logos-co/eth-lez-atomic-swaps/master/logos-repo.jsonExpected: a repository named ETH ↔ LEZ Atomic Swaps joins the list, alongside the built-in one marked
Default. No restart is needed. Basecamp re-reads the catalogue as soon as the repository is added.infoIf the new row shows an
Unreachablebadge, the URL is wrong or your network blocked the request. Click Refresh to retry. The field expects the URL of alogos-repo.jsonindex, not a link to the repository's web page. -
Go back to Package Manager and search for
swap.Expected: two packages from the new repository,
swapandswap_ui, both shown as ETH ↔ LEZ Atomic Swap at version0.3.3. -
Install
swapfirst, then installswap_ui.Each opens an Add Application window listing Required Packages. Confirm with Install and wait for the stage label to reach
Installed.warningInstall
swapbeforeswap_ui. The UI package declares a dependency on the backend, and taking them the other way round leaves the interface with no backend to talk to. -
Restart Basecamp, then open ETH ↔ LEZ Atomic Swap from the sidebar.
Expected: a row of six tabs across the top: Market, Config, Maker, Taker, Refund, and History. Along the top you also get live
ETHandLEZbalances with a Refresh button, and a status line that settles onDelivery connectedonce the app finds a peer.
The catalogue is saved in your Basecamp settings and survives restarts. You add it once.
Step 3: Set up your accounts
A swap needs two identities: an Ethereum key to sign your Sepolia transactions, and an initialised LEZ account to receive your tokens.
On 0.3.3 you create both outside the app, then paste them into the Config tab in Step 4.
This is the roughest part of the journey, and it's worth knowing why before you start. Version 0.3.3 has no in-app account setup, so you handle an Ethereum private key yourself and use a separate command-line tool for the LEZ side. Copying a raw private key between applications is a bad habit, and this app is in the process of removing the need for it. Until that lands, use a brand-new key that holds nothing but Sepolia test funds, and never paste in a key you also use on Ethereum mainnet.
Create a funded Ethereum key
-
In an Ethereum wallet such as MetaMask, create a new account to use for this journey alone.
-
Copy its address, and send Sepolia ETH to that address from a public faucet.
-
Export the account's private key and keep it to hand for Step 4. In MetaMask this is under Account details → Show private key.
Expected: a 64-character hex private key, and an address showing a non-zero Sepolia balance.
Create, initialise, and fund a LEZ account
The LEZ side needs an account that exists, is initialised on-chain, and holds tokens. The LEZ wallet CLI does all three, and it's the only route on 0.3.3. It's built from source with cargo, so this part does need a terminal.
Follow Run an LEZ wallet via the CLI as far as the end of Install the wallet and connect it to the testnet. That builds the wallet and points it at https://testnet.lez.logos.co, the same sequencer this app uses.
Then create a public account, initialise it on-chain, and fund it from the Piñata faucet:
wallet account new public --label me
wallet auth-transfer init --account-id Public/<ACCOUNT_ID>
wallet pinata claim --to me
Expected: the first command prints both an account ID and a private key. Record both. The second initialises the account on-chain. The third credits 150 LEZ, and you can repeat it as often as you need.
Don't skip the initialise command. An uninitialised LEZ account is the most confusing failure in this app, because it produces no error at all. The sequencer silently discards transactions that reference an account it has never seen initialised, so the swap simply stalls rather than failing. The wallet reports Account is Uninitialized until you initialise it.
Arriving in 0.3.4: a guided Setup tab that replaces this whole step with three buttons, generating the Ethereum key and creating, initialising, and funding the LEZ account without a private key ever leaving the app. It's tracked in eth-lez-atomic-swaps#95, which is still in draft with no release date. This page covers the 0.3.3 route until it ships.
Step 4: Fill in the Config tab
The Config tab holds every endpoint, address, and key the app uses, grouped under Ethereum, LEZ, and Swap parameters. Almost all of it is already correct. This step is a check rather than a data-entry exercise.
-
Open the Config tab.
-
Under Ethereum, confirm RPC URL is
wss://ethereum-sepolia-rpc.publicnode.comand HTLC Contract Address is0x351B0EA07739FA9F6769213927D7836a790A5FAF. -
Still under Ethereum, paste the private key from Step 3 into Private Key, and the matching address into Recipient Address.
Recipient Address is where your bought tokens' counterpart settles, so it's the address belonging to that same key.
-
Under LEZ, confirm Sequencer URL is
https://testnet.lez.logos.coand HTLC Program ID is27720b5b0345135d8e684eb172c27f5fb237548cc891a3ec889d0ed340504070. -
Still under LEZ, paste the private key from Step 3 into Signing Key, and your account ID into Taker Account ID.
Leave Wallet Home and Wallet Account ID empty. The app authenticates to the LEZ either with a signing key or with a wallet directory plus account ID, and the signing key is the route that works here. Wallet Home's placeholder,
.scaffold/wallet, is a path from the app's development setup that doesn't exist on a machine that installed from the catalogue.Taker Account ID is the account that receives the maker's LEZ, and it's required whether or not you set anything else.
warningThe Signing Key must be 64 hex characters with no
0xprefix. The Private Key field above it accepts either form, so it's easy to assume this one does too. It doesn't: a0x-prefixed LEZ key passes the Config tab's validation and then fails at run time withinvalid LEZ signing key hexwhen a swap starts. -
Leave Swap parameters alone.
These set the terms of offers you'd publish as a maker. When you take someone else's offer, the amounts and time locks come from that offer instead.
Expected: no red text under any field, and the Market tab's status chip reads Config ready. There's no save button. The app validates and saves as you type, roughly half a second after you stop.
If a field is wrong, the app says so directly underneath it, with messages like Required, Must be a 20-byte ETH address, or Must be a 32-byte hex program ID. Fix those before continuing, because the app refuses to start a swap while any remain.
The contract at 0x351B0EA07739FA9F6769213927D7836a790A5FAF is version 2 of the Ethereum HTLC. Earlier builds of this app pointed at a version 1 contract at 0x8636Fe66DFee166589a913140f14d5F57394834A, which is still deployed and still responds. It's written out in full here so you can check character by character that you aren't on it, because the two are easy to confuse and the failure is unhelpful. Version 1 has no INTERFACE_VERSION function, so the app's compatibility check reverts against it and swaps don't start. If you've used this app before, replace the address with the one above.
Step 5: Take a live offer
Logos runs a maker on this testnet. It publishes offers and waits for someone to take them, which is what lets you complete this journey without a second machine and a friend.
-
Open the Market tab.
Expected: a live tape with the columns
OFFER,RATE LEZ/ETH,MAKER,AGE, andEXPIRES. The board rescans every five seconds.When our maker is online, it advertises
10 LEZfor0.00001 ETH, and that's the offer the rest of this step follows. The board can also be legitimately empty, because offers are live broadcasts rather than stored listings. If you see no offers, work through The Market tab is empty and come back. -
Click the offer.
Expected: a detail pane on the right reading Buy 10 LEZ
for 0.00001 ETH, listing the maker's addresses, the hashlock, and both HTLC identifiers. You're buying the LEZ and paying the ETH. -
Click Accept — buy 10 LEZ.
If the button is disabled, the app shows why immediately beneath it, such as
Complete configuration first → ConfigorThis offer has expired. -
Switch to the Taker tab and watch it run.
Expected: the progress stepper ticks through
Generate Preimage,Lock ETH,ETH Locked,Wait for LEZ Lock,LEZ Lock Detected,Verify LEZ Escrow,LEZ Escrow Verified,Claim LEZ, andLEZ Claimed. It usually takes one to three minutes, most of it waiting on Sepolia confirmations. -
Click Refresh in the header and confirm your
LEZbalance rose by10.
Offers are live announcements, not stored listings. Nothing retains them, so the Market tab can only show what a maker is broadcasting at that moment. The board says as much under the tape: Offers are advertisements — a swap completes only if the maker is live.
Step 6: Read your receipt and verify it
Every finished swap writes a receipt recording both legs, so you can check the trade against the two chains instead of taking the app's word for it. Receipts persist across restarts.
-
Open the History tab and click your swap, then Receipt ▾.
Expected: a card headed
SWAP COMPLETEDwith the hero line Bought 10 LEZ, followed by labelled rows including Hashlock, Preimage, ETH lock tx, LEZ claim tx, ETH HTLC contract, and both time locks. The preimage stays masked behind a Reveal toggle. -
On the ETH lock tx row, click Copy explorer link, then paste the link into your browser.
Expected: the button confirms
Explorer link copied, and Etherscan shows a successful transaction against the HTLC contract. The URL looks likehttps://sepolia.etherscan.io/tx/0x…. -
Do the same on the LEZ claim tx row.
Expected: the LEZ explorer shows the matching claim. The URL looks like
https://explorer.testnet.lez.logos.co/transaction/followed by a 64-character hash with no0xprefix. -
Compare the Hashlock on the receipt with the hashlock the offer advertised in Step 5.
They match, which is the point. The same hash bound both locks, and the preimage now published on the LEZ chain is what released both.
A Basecamp app can't open your browser for you. Logos app interfaces run inside a sandboxed QML engine that silently ignores requests to open an external URL, as reported in eth-lez-atomic-swaps#84. That's why the receipt offers Copy value and Copy explorer link buttons instead of clickable links, and why every instruction here says to paste the link into your browser yourself.
Two rows are deliberately copy-only, with no explorer link. ETH swap ID (lock) is an identifier internal to the contract rather than a transaction hash, and LEZ HTLC program names a program rather than a transaction. Keep the swap ID anyway. It's what the Refund tab asks for if a later swap stalls.
Step 7: Send feedback
This app is a testnet preview, and the quickest way to improve it is to report what you hit.
On any receipt, click Copy feedback link and paste it into your browser. It opens a pre-structured feedback form on the app repository. Then click Copy safe evidence and paste that into the form. It gathers the hashes, addresses, and versions needed to trace your swap on both chains, and it deliberately leaves out your keys and preimage.
If you never got as far as a receipt, open an issue describing what you expected and what happened instead, with your platform and the swap and swap_ui versions from the Package Manager.
Troubleshooting
The app doesn't appear after installing it
Restart Basecamp. A newly installed app reaches the sidebar only after a restart. If it's still missing, check your platform: the catalogue publishes darwin-arm64, linux-amd64, and linux-arm64 builds only, and Basecamp installs nothing at all on a platform with no matching build, which is what happens on Intel macOS.
The Market tab is empty
Read the empty state, because it names the cause. Finish network setup to browse means your configuration isn't valid yet, so the app never subscribed to anything. Connecting to the swap network… means the app hasn't found a delivery peer yet, which usually resolves on its own within a minute. No offers on the board yet means you're connected and configured, and the maker is simply offline for the moment. Wait a few minutes and let the board rescan. Because nothing retains offers, the tab can only ever show what's being broadcast right now.
The app can't connect to Ethereum
Check RPC URL begins with wss:// and not https://. The app opens a WebSocket subscription to watch for lock and claim events, and an https:// endpoint fails at that point even though it's perfectly valid for ordinary calls. The field's own hint says the same thing.
The swap does nothing and no error appears
Your LEZ account is almost certainly uninitialised. The sequencer discards transactions for an account it has never seen initialised and returns no error, so the app has nothing to report. Check the account with the wallet CLI from Step 3. If it reports Account is Uninitialized, run the initialise step, then confirm the balance is genuinely positive before retrying.
The Taker tab reports ETH lock rejected
The maker refuses a lock that doesn't leave it enough time to respond, and the Ethereum contract enforces its own floor of 300 seconds. Your Ethereum deadline has to sit comfortably beyond the LEZ one, not just after it. This shows up when a swap is started against an offer that's nearly expired, so take a freshly published one. The maker keeps waiting rather than failing, so your Taker tab appears to stall.
There isn't enough LEZ in the account
Claim from the Piñata faucet again with the wallet CLI from Step 3. Each claim credits a bounded amount, so repeat it until the balance covers what you need.
A swap stopped halfway and the funds are still locked
This is the case the time locks exist for, and no funds are at risk. Copy ETH swap ID (lock) from the receipt in the History tab, open the Refund tab, paste it into Swap ID under ETH refund, and click Refund ETH once your deadline has passed. The contract enforces that deadline, so an early attempt fails outright rather than passing silently. Reclaiming returns your ETH in full, less gas.
Next steps
- Install and load a module in Logos Basecamp explains how Basecamp packages, installs, and loads the modules this app is built from.
- Initiate native token transfers on the LEZ with the wallet UI covers moving the LEZ tokens you just received.
To build the app from source, or run a swap headlessly from the command line, see the eth-lez-atomic-swaps README.