Swaps can be performed on the Sepolia (Ethereum testnet) together with the Monero Stagenet network. This document describes how to do stagenet swaps.
Note: stagenet and mainnet swaps currently take around 20 minutes due to the 2-minute block time and required 10 confirmations before funds can be spent.
Note: the
swapd
process directly interacts with an unlocked Monero wallet and Ethereum private key. This is to allow for a smoother swap process that doesn't require any interaction from you once initiated. However, this effectively givesswapd
access to all your (testnet) funds. In the future, there will be a mode that does not access your keys/wallet, but will require user interaction during a swap.
The atomic swap daemon requires access to a fully synced, stagenet monerod daemon, a Sepolia network endpoint, and a Sepolia network private key funded with some SepETH.
- Install the Monero CLI if you haven't already. You can get it here:
For Linux 64-bit, you can do:
./scripts/install-monero-linux.sh
- Begin the stagenet daemon and wait for it to sync. This may take a day or so. Alternatively, you can use an existing stagenet endpoint if you know of one. You can find remote Monero nodes here: https://monero.fail/?nettype=stagenet
./monero-bin/monerod --detach --stagenet
-
Optional: Place your stagenet monero wallet file in
{DATA_DIR}/wallet/
and call itswap-wallet
. By default{DATA_DIR}
is${HOME}/.atomicswap/stagenet
, but if you are creating multiple stagenetswapd
instances on the same host, you should passswapd
the--data-dir
flag so each instance has a separate directory to store its data. If you skip this step, a new wallet will be created that you can later fund for swaps. -
Create a Sepolia wallet. You can do this using Metamask by selecting "Sepolia Test Network" from the networks, then creating a new account with "Create account". I'd recommend naming this new account something explicit like
sepolia-swap-account
. -
Optional: Export the private key for this account by navigating to: three dots in upper right of Metamask -> account details -> export private key. Paste this private key into a file named
{DATA_DIR}/eth.key
. If you skip this step, a new wallet will be created for you that you can transfer Sepolia ether to or fund directly in the next step.
6a. Fund your Sepolia account using a faucet:
6b. Optional: Obtain some Sepolia ERC20 tokens
This unaffiliated project has deployed some Sepolia tokens of different decimal sizes that can be useful for testing. You can use MetaMask to send the contract address zero Sepolia ETH and the contract will grant you 1000 of its ERC20 tokens. You will pay gas fees that you should validate are sane before sending.
-
Obtain a Sepolia JSON-RPC endpoint. If you don't want to sync your own node, you can find public ones here: https://sepolia.dev/
-
Install go 1.21+. See build instructions for more details.
-
Clone and build the atomic-swap binaries:
git clone https://github.com/athanorlabs/atomic-swap.git
cd atomic-swap
make build
- Start the
swapd
daemon. Change--eth-endpoint
to point to your endpoint.
./bin/swapd --env stagenet --eth-endpoint SEPOLIA_ENDPOINT
Note: You probably need additional flags above:
--data-dir PATH
: Needed if you are launching more than oneswapd
instance on the same host, otherwise accepting the default of${HOME}/.atomicswap/stagenet
is fine.--monerod-host HOSTNAME_OR_IP
and--monerod-port PORT_NUM
: Ideally, you have your own stagenet node on the local network and will use these values. If that is not an option, our stagenet default usesnode.sethforprivacy.com:38089
.--libp2p-port PORT
. The default is9900
. Use this flag when creating multiple swapd instances on the same host.--rpc-port PORT
. The default is5000
. Use this flag when creating multiple swapd instances on the same host.
Note: please also see the RPC documentation for complete documentation on available RPC calls and their parameters.
As a taker, you can use either the UI or swapcli
to discover and take offers.
WARNING: The UI is currently unmaintained and probably does not work; please use the CLI to take offers.
- From the
atomic-swap
directory, build and start the UI. Note: you need to have node.js installed.
cd ui/
yarn install
yarn build
yarn start
- Navigate to http://localhost:8080 to see the UI running. It will automatically connect to your
swapd
process and try to find offers. You can also refresh the offers by clickingrefresh
.
- When you find an offer you'd like to take, press the
take
button to input the amount of ETH you'd like to provide. Then, confirm the offer. If all goes well, you should see the swap complete in the logs ofswapd
.
- Search for existing XMR offers using
swapcli
:
./bin/swapcli discover --provides XMR --search-time 3 --swapd-port 5001
# [[/ip4/127.0.0.1/udp/9934/quic-v1/p2p/12D3KooWC547RfLcveQi1vBxACjnT6Uv15V11ortDTuxRWuhubGv /ip4/127.0.0.1/udp/9934/quic-v1/p2p/12D3KooWC547RfLcveQi1vBxACjnT6Uv15V11ortDTuxRWuhubGv]]
- Query a returned peer as to how much XMR they can provide and their preferred exchange rate (replace
"--peer-id"
field with one of the addresses returned in the above step):
./bin/swapcli query --peer-id 12D3KooWC547RfLcveQi1vBxACjnT6Uv15V11ortDTuxRWuhubGv
# Offer ID=cf4bf01a0775a0d13fa41b14516e4b89034300707a1754e0d99b65f6cb6fffb9 Provides=XMR MinimumAmount=0.1 MaximumAmount=1 ExchangeRate=0.05
Note: the exchange rate is the ratio of XMR:ETH price. So for example, a ratio of 0.05 would mean 20 XMR to 1 ETH. Since we're on testnet, it's not critical what you set it to.
- a. Then, finding an offer you like, take the offer by copying the peer's multiaddress and offer ID into the command below. As well, specify how much SepETH you would like to provide, taking into account the offer's exchange rate and min/max XMR amounts.
./bin/swapcli take --peer-id 12D3KooWC547RfLcveQi1vBxACjnT6Uv15V11ortDTuxRWuhubGv \
--offer-id cf4bf01a0775a0d13fa41b14516e4b89034300707a1754e0d99b65f6cb6fffb9 --provides-amount 0.05
# Initiated swap with ID=0
- b. Alternatively, you can take the offer without getting notified of swap status updates:
./bin/swapcli take --peer-id 12D3KooWHLUrLnJtUbaGzTSi6azZavKhNgUZTtSiUZ9Uy12v1eZ7 \
--offer-id 0xcf4bf01a0775a0d13fa41b14516e4b89034300707a1754e0d99b65f6cb6fffb9 \
--provides-amount 0.05 --detached --swapd-port 5001
If all goes well, you should see the node execute the swap protocol. If the swap ends successfully, the XMR received will automatically be transferred back your original wallet.
- Find your stagenet address:
./bin/swapcli balances | grep 'Monero address'
- Fund this address with some stagenet XMR. You can try the faucets here:
If you don't have any luck with these, please message me on twitter/reddit (@elizabethereum) with your stagenet address, and I can send you some stagenet XMR.
- a. Make an offer with
swapcli
:
./bin/swapcli make --min-amount 0.1 --max-amount 1 --exchange-rate 0.5 --swapd-port 5001
# Published offer with ID cf4bf01a0775a0d13fa41b14516e4b89034300707a1754e0d99b65f6cb6fffb9
- b. Alternatively, make an offer with
swapcli
without subscribing to updates:
./bin/swapcli make --min-amount 0.1 --max-amount 1 --exchange-rate 0.5 --swapd-port 5001 --detached
# Published offer with ID cf4bf01a0775a0d13fa41b14516e4b89034300707a1754e0d99b65f6cb6fffb9
Note: the exchange rate is the ratio of XMR:ETH price. So for example, a ratio of 0.05 would mean 20 XMR to 1 ETH. Since we're on testnet, it's not critical what you set it to.
When a peer takes your offer, you will see logs in swapd
notifying you that a swap has been initiated. If all goes well, you should receive the SepETH in the Sepolia account created earlier.
Ideally, the exit case of the swap should be Success
. If this is not the case, it will either be one of Refunded
or Aborted
.
Refunded
means that the swap refunded after your funds were already locked. In this case, you would lose transaction fees.Aborted
means that the swap exited before any funds were locked, so nothing was lost except time.
Neither of these should happen, so if they happen, it indicates an issue either on your side or the remote peer's side.
A few common errors are:
Failed to get height
: double check that yourmonerod --stagenet
process is running.unlocked balance is less than maximum offer amount
: you will see this if you're a maker and try to make an offer but don't have enough balance. Either get more stagenet XMR or wait for your balance to unlock.
You can also try the swap on another Ethereum or EVM-compatible testnet. However, you'll need to run your own maker nodes.
To connect to a different Ethereum network, follow Setup steps 4-7 but with your desired network. Then, start swapd
with your specified private key file, endpoint, and chain ID. Common chain IDs can be found here.
Note: The
--deploy
flag toswapd
creates a new instance ofSwapCreator.sol
to the network. You need to have funds in your account to deploy the contract. To use a contract deployed with--deploy
in subsequentswapd
instances, use the flag--contract-addr=ADDRESS
. When usingstagenet
, a deployed contract already exists and our code will use it by default.
If you find any bugs or unexpected swap occurrences, please open an issue on the repo, detailing exact steps you took to setup swapd
and what caused the bug to occur. Your OS and environment would be helpful as well. Any bug reports or general improvement suggestions are much appreciated.