How to Run an AtomicSwap Market-Making Bot
Running a Market-Making Bot can help maintain the 1:1 peg between BCH and SBCH and get some earnings. We have tried our best to make it robust and secure. This article introduces how to run it robustly and securely.
Parameters
First of all, you need to decide on some parameters which your bot and its counterparties must abide by. They are:
- bch-lock-time: how many bch blocks must go by before a locked fund can be refunded. Recommended value: 144, which means 24 hours.
- min-swap-amt: the minimum amount for a swap. Recommended value: 0.01~0.1BCH
- max-swap-amt: the maximum amount for a swap. Recommended value: 1~10BCH
- bch-confirmations: the minimum confirmations that a BCH mainchain locking transaction must reach before it can be served by your bot. Recommended value: 6~10.
Prepare a cloud machine and start full node clients
It’s suggested to run a bitcoincashnode full-node client and a smartbchd full-node client on your own cloud machine, which provides trustworthy information to your bot. An azure instance DC2sv3 with 16GB RAM will be the best fit because it also supports SGX. The bot can work in an SGX enclave for better protection of your private keys. The clients need about 600GB of SSD space.
If you do not want to use an SGX instance because it’s more expensive, any machine with 16GB RAM and 600GB SSD will do.
Then you can start bitcoincashnode and smartbchd.
Prepare accounts on the mainchain and the sidechain
The bot uses a mainchain account and a sidechain account to send transactions. So you must prepare these accounts’ private keys and send some BCH to them.
It’s suggested to use ElectronCash to generate the WIF private key for the mainchain account and use MetaMask to generate the HEX private key for the sidechain account. For both of these two wallets, you can use the same mnemonics.
After you get the WIF private key from ElectronCash, please use following command to get the public key of the mainchain account:
git clone https://github.com/smartbch/atomic-swap-covenants.git
cd atomic-swap-covenants
npm i
MAINNET=true ts-node scripts/htlc.ts user-info --wif=<WIF-from-ElectronCash>
The pkh
line of the output is what you will need.
The mainchain account’s address must be imported into the bitcoincashnode client through its RPC. Please run the following command on your cloud machine:
curl --user user:pass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "importaddress", "params": ["bitcoincash:xxx", "ASBOT", true] }' -H 'content-type: text/plain;' http://localhost:8332/
Register your bot to the HTLC smart contract
The HTLC smart contract was deployed at 0xBa26D85Bef070Ed2C6B0D555aAAc1c54611ECd22. Its source code was opensourced here.
When it was deployed, the constructor set the following parameters:
- minStakedValue = 1BCH. You must stake one BCH into the contract when registering a bot and can take it back after retiring.
- minRetireDelay = 48 hours. You must wait for 48 hours after retirement before you can take back your staked BCH.
Staking BCH prevents evil guys from spamming the HTLC smart contracts by registering unworkable bots.
Please make sure your bot’s side chain account has at least 1.01 BCH and then use the following commands to register your bot to the HTLC smart contract:
git clone https://github.com/smartbch/atomic-swap-contracts.git
cd atomic-swap-contracts
npm i
KEY=<EVM-private-key-from-MetaMask> \
HARDHAT_NETWORK=sbch_mainnet node ./scripts/htlc.js register-bot \
--signer=0 \
--htlc-addr=0xBa26D85Bef070Ed2C6B0D555aAAc1c54611ECd22 \
--intro=MyBotIsTheBest_or_you_can_write_something_else \
--pkh=<the-public-key-hash-that-you-got-in-the-last-step> \
--bch-lock-time=144 \
--penalty-bps=0 \
--bch-price=0.93 \
--sbch-price=1.07 \
--min-swap-amt=0.01 \
--max-swap-amt=1.0 \
--staked-val=1.0 \
--status-checker=<An-EVM-account-that-can-mark-your-bot-as-unavailable>
You can use an account as your bot’s status checker that watches whether your bot is online. When it finds that your bot is unavailable, it will send a transaction to the HTLC contract to mark your bot’s status as “unavailable” such that users will not trade with it. If you do not need this feature, just set the status checker to the same address as your bot.
Start Your Bot
Now you can start your bot on the cloud instance:
git clone https://github.com/smartbch/atomic-swap-bot.git
cd atomic-swap-bot
ego-go build github.com/smartbch/atomic-swap-bot/cmd/asbot
ego sign asbot
mkdir data
ego run asbot \
--db-file=/data/bot.db \
--bch-rpc-url=http://localhost:8332 \
--sbch-rpc-url=http://localhost:8545 \
--sbch-htlc-addr=0xBa26D85Bef070Ed2C6B0D555aAAc1c54611ECd22 \
--sbch-gas-price=1.05 \
--bch-confirmations=10 \
--bch-lock-fee-rate=2 \
--bch-unlock-fee-rate=2 \
--bch-refund-fee-rate=2 \
--sbch-lock-gas=500000 \
--sbch-unlock-gas=500000 \
--sbch-refund-gas=500000 \
--debug=false
Here we set the miner fee rate to be 2sat/byte. You can lower it to 1sat/byte as well.
The above ego run asbot
command will output something like this to the console:
EGo v1.3.0 (360a6a40836461465fdbd0742dfb0f980b68c638)
[erthost] loading enclave ...
[erthost] entering enclave ...
[ego] starting application ...
The ecies pubkey: 03052743d278846f90cedb64282a3ea3db20a8414b627e4aff3dc5408110073eed
Enter the encrypted BCH WIF:
It needs you to encrypt the BCH WIF private key and the EVM hex private key on you local computer and input the encrypted keys on the cloud machine’s console.
On your local computer, run the following command:
go run github.com/smartbch/atomic-swap-bot/cmd/encrypt
It asks you to input the ecies pubkey generated by the above ego run asbot
command, your bot’s WIF private key and its EVM private key. After you input these data into it, it will output the encrypted WIF key and EVM private key as hex strings. Copy and enter them to the ego run asbot
command’s prompt, and then your bot will decrypt the keys and use them to sign transactions.
Your bot will keep the private keys only in its memory. If it works in an SGX enclave, the private keys are impossible to be stolen from the protected memory.
If you do not have an SGX instance, normal golang can also work. Please replace ego-go build
with go build
, replace ego run asbot
with ./asbot
and skip the ego sign asbot
command.
Start Slaves for Your Bot (optional)
If your bot’s cloud machine panics, it may miss the time window for unlocking funds and losing coins. To further secure your funds, you can use one or more slaves to help your bot. Every slave watches the counterparties’ secret-revealing transactions independently. If your bot fails to unlock funds ten minutes after secret-revealing, a slave will send a transaction to help your bot unlock the fund.
It’s good for a slave to have its own bitcoincashnode client and smartbch client. To start a slave, please use the following command:
git clone https://github.com/smartbch/atomic-swap-bot.git
cd atomic-swap-bot/cmd/asbot
go build .
./asbot \
--debug=false \
--db-file=bot.db \
--bch-rpc-url=http://localhost:8332 \
--sbch-rpc-url=http://localhost:8545 \
--bch-master-addr=bitcoincash:qz0ypj3acm80ve9qpzdy4rm7s9k0u7zrpu6nzfzgyh \
--sbch-master-addr=0xd7d00B26Eac76f1c8B646442ECBfb33201842149 \
--sbch-htlc-addr=0xBa26D85Bef070Ed2C6B0D555aAAc1c54611ECd22 \
--sbch-gas-price=1.05 \
--bch-confirmations=0 \
--bch-lock-fee-rate=2 \
--bch-unlock-fee-rate=2 \
--bch-refund-fee-rate=2 \
--sbch-lock-gas=500000 \
--sbch-unlock-gas=500000 \
--sbch-refund-gas=500000 \
--slave=true
Where the bch-master-addr
and sbch-master-addr
are the addresses of your bot’s mainchain account and side chain account.
Change the prices
You can change your bot’s swapping prices by calling the HTLC smart contract:
git clone https://github.com/smartbch/atomic-swap-contracts.git
cd atomic-swap-contracts
KEY=<EVM-private-key-from-MetaMask> \
HARDHAT_NETWORK=sbch_mainnet node ./scripts/htlc.js update-bot \
--signer=0 \
--htlc-addr=0xBa26D85Bef070Ed2C6B0D555aAAc1c54611ECd22 \
--intro=MyBotIsTheBest_or_you_can_write_something_else \
--bch-price=0.93 \
--sbch-price=1.07 \
--min-swap-amt=0.01 \
--max-swap-amt=1.0 \
--staked-val=1.0 \
--status-checker=<An-EVM-account-that-can-mark-your-bot-as-unavailable>
.command('update-bot', 'update bot', (yargs) => {
return yargs
.option('signer', { required: false,type: 'number', default: 1})
.option('htlc-addr', { required: true, type: 'string', description: 'HTLC contract address' })
.option('intro', { required: true, type: 'string', description: "new introduction" })
.option('bch-price', { required: true, type: 'string', description: 'new BCH price (in sBCH)' })
.option('sbch-price', { required: true, type: 'string', description: 'new sBCH price (in BCH)' })
;