--- disqus: trinkler-software --- # Agora Trade Technical Paper ###### tags: `Trinkler Software AG` `Public` `Agora Trade` `Technical Paper` ## Table of contents [toc] ## Introduction [Agora Trade](https://agora.trade) is a cross-chain, non-custodial, cryptocurrency exchange based on multisignature timelocked contracts and [hashed timelocked contracts](https://en.bitcoin.it/wiki/Hashed_Timelock_Contracts). - **Cross-chain:** Using hashed timelocked contracts to implement atomic swap trading. - **Non-custodial:** Locked tokens that can only be spent if approved by an authority or if the timelock expires. Using multisignature timelocked contracts, make orders can be generated off-chain. Therefore providing liquidity becomes free. To increase security and usability, we target [Imagewallet](https://trinkler.software/tools) integration and IPFS deployment. - **Imagewallet**: We use Imagewallets as easy-to-use login credentials to the web application. - **IPFS**: Due to the content-addressed nature of IPFS one can have a webapp where the user can know with certainty that wallet keys and hash preimages are not stolen. IPFS allows us to build secure distributed content-addressed applications. Finally, [Agora Trade](https://agora.trade) is open-source and evolving. - **Open-source**: Our front-end code is or will be open-sourced. This means that you don't have to trust us with the security of your keys. - **Evolving**: We strive to build the most secure, cheapest and most usable product for you. For this reason we're constantly evolving our product. ## Goal Our goal is to be the _cross-chain, non-custodial, cryptocurrency exchange_ with the most unique vistors per day and the highest daily volume. ## Problem Why decentralised exchanges. > _Decentralised exchanges will give people more freedom, as they don’t have to hold their assets on the exchange, adding, it doesn’t necessarily mean that it’s safer for you, it just means you have more control._ Changpeng Zhao, CEO Binance in [Cryptonews](https://cryptonews.com/news/decentralized-binance-prototype-is-expected-within-a-couple-2212.htm) > _I definitely hope centralized exchanges go burn in hell as much as possible._ Vitalik Buterin, Ethereum Creator at [Techcrunch](https://cryptonews.com/news/decentralized-binance-prototype-is-expected-within-a-couple-2212.htm) > Tech executives have known for years that a backlash was coming. But their mistake was to try to be liked when they needed to be trusted. [The Information](https://www.theinformation.com/articles/silicon-valleys-big-pr-mistake?jwt=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJyQGtvLmNvbSIsImV4cCI6MTU2MzEyODEzNywibiI6Ikd1ZXN0Iiwic2NvcGUiOlsic2hhcmUiXX0.1sKpO4HTaYAd1QOr15CsiVnkSfroS0AMjNR4M-_YemM&unlock=560d306d1a1ea73e) _The problem we solve is that we let the user regain control over their crypto assets._ ## Solution ### Prelude We propose three main approaches for cross-chain, non-custodial exchanges: 1. Cross-chain asset trading: [Hashed Timelock Contracts](https://en.bitcoin.it/wiki/Hashed_Timelock_Contracts) 2. Cross-chain asset _transfer_: [Relaychain](https://polkadot.network/) 3. Inter-chain asset trading: [Revive](https://eprint.iacr.org/2017/823.pdf) #### Current Work Current work focuses on point one from above, that is cross-chain asset trading using Hashed timelocked contracts. Example [description](https://nimiq-network.github.io/developer-reference/chapters/accounts-and-contracts.html#hashed-time-locked-contract-htlc) and [implementation](https://github.com/nimiq-network/core/blob/60bb1671e108e9a4bcd7a0b01226405dcba47be3/src/main/generic/consensus/base/account/HashedTimeLockedContract.js) of a Hashed Timelock Contract. #### Future work Once [Relaychain](https://polkadot.network/) is ready we will be able to remove the biggest UX bottleneck of Agora Trade. This is that the user, who initiated the make order, needs to come online to initiate the second side of the swap. ## Product ### Primary tenets - **Usable**: Our primary goal is to build something that is _usable_. It's our responsiblity to make the complex simple. Our application has a clear focus and we require as little work from the user as possible. - **Minimal**: We focus on one thing and one thing only: Cross-chain, non-custodial exchange. This however we do better than anyone else. - **Robust**: We build the exchange on sound tech standards. We keep a well organized, clean and readable codebase; anticipate errors and avoid interruptions. We minimize any central points of failure. See also [Gnome design principles](https://developer.gnome.org/hig/stable/design-principles.html.en). ## Main components _Everything is designed with many different currencies in mind, not just two_. - Custodian solution: [Imagewallet](https://github.com/Trinkler/imagewallet): Easy to use, multi-chain custodian solution. - Blockchain scripting: [Agora-htlcs](https://github.com/Trinkler/agora-htlcs): Collection of hashed time-locked contracts for Agora Trade. - NPM Package: [Agora-swap](https://github.com/Trinkler/agora-swap): Tool to perform cross-chain atomic swaps - Webapp: [Agora.trade](https://github.com/Trinkler/agora.trade): Cross-chain, non-custodial, cryptocurrency exchange. ## User story New concepts for user: - User needs to generate and download an imagewallet. The imagewallet contains the private key to the keys used to trade on [agora.trade](https://agora.trade). - Imagewallet is secured by a password which if lost, can not be recovered. - User uses imagewallet to login to the exchange. - User needs to return to [agora.trade](https://agora.trade) to initiate the second side of the atomic swap of a make order. This having to return to page to complete trade is the main difference to the user story of centralised exchanges. Three parts to user story: - Off-chain make order - Make order using HTLC - For make orders the user needs to _return to page_ to initiate second side of swap (take) - Take order using HTLC - Take orders don't require additional user interaction. ### Overview ```flow st=>start: Start e_trade=>end: End s_get_orders=>subroutine: Request all orders from server. Establish consensus with Blockchains of Assets: - Init Nimiq - Init Ethereum (infura.io) - .. o_drap_drop_login=>operation: Imagewallet login: derive Asset keys o_buy_sell=>operation: User selects Buy/Sell Asset Inserts <Price>, <Amount> c_can_be_matched=>condition: Order can be matched with existing orders? o_make_order=>operation: Alice; Make Order (Off-chain): Display additional information about make order and wait for user confirmation op4=>operation: Bob; Take Order (On-chain): Display additional information about take order and wait for user confirmation conf_take=>condition: Bob confirms take order s_deploy_htlc_1=>subroutine: Bob deploys first side of the channel (Tx1) and encrypts his secret using Alices and Exchanges public keys, sends this with signed regularTransfer (Tx4) to Server. s_ping_user=>subroutine: Ping other Order.owner (== Alice) to sign tx <Wait until Alice online again> o_user_online=>operation: Alice; Take Order (On-chain): Once Alice online Display all the necessary information to her conf_off_chain_make=>condition: Alice confirms off-chain make order s_store_server=>subroutine: Store in Server and display in <open orders> conf_trade=>condition: Alice confirms trade execution s_douple_sig=>subroutine: Alice sets up second side of the channel (Tx2). Decrypts outerlayer of Bobs secret. Sends signed regularTransfer (Tx4) to server s_execute_trade=>subroutine: Send coins to Alice and coins to Bob Completes trade sub1=>subroutine: Take Order st->s_get_orders->o_drap_drop_login->o_buy_sell(right)->c_can_be_matched c_can_be_matched(yes, right)->op4->conf_take c_can_be_matched(no)->o_make_order->conf_off_chain_make conf_take(yes)->s_deploy_htlc_1->s_ping_user->o_user_online->conf_trade conf_take(no)->e_trade conf_trade(yes)->s_douple_sig conf_trade(no)->e_trade s_douple_sig->s_execute_trade->e_trade conf_off_chain_make(yes)->s_store_server->s_ping_user conf_off_chain_make(no)->e_trade ``` ### Trading (Make) Making orders is as simple as signing an order struct and paying a commission. ```sequence participant Alice participant NIM participant Exchange participant ETH participant Bob note left of Alice: Onboarding stage\n(as above) note left of Alice: Signalling stage Alice --> Exchange: sign_A({Order, commission}) Bob --> Exchange: sign_B({Order, commission}) ``` User story - Login using imagewallet (==insert pw & unlock keys) - Select Make Order (-> sent to exchange) - \<_Time passes_> - Get pinged (email) by exchange w ping msg that first side of swap has been inititated and link to site - Go to site, login using imagewallet - done - Send tx for second side of swap. - Send signed transaction to resolve swap to exchange - \<_Time passes_> - Get notification of trade successful, i.e. secret has been revealed or received Bob's commission due to no secret revealed. ### Trading (Take) #### Description **Constants of [Nimiq HTLC](https://github.com/nimiq-network/core/blob/60bb1671e108e9a4bcd7a0b01226405dcba47be3/src/main/generic/consensus/base/account/HashedTimeLockedContract.js):** - hashalgo: sha256 - hashCount: 1 User story: - Login using imagewallet (==insert pw & unlock keys) - Select Take Order (-> sent to exchange) - Exchange matches, and displays confirmation right away to user - Send tx to initiate first side of swap - Encrypt secret using first make orders public key and then exchange public key. Send this to exchange. Use [bitcoin library](https://ethereum.stackexchange.com/questions/3092/how-to-encrypt-a-message-with-the-public-key-of-an-ethereum-address) for encryption/decryption. If this option is selected then take orders is completed. - Send signed transaction to resolve swap to exchange - \<_Time passes_> - Get notification of trade successful, i.e. secret has been revealed or received Bobs commission due to no secret revealed. #### Alice buys NIM and sell ETH ```sequence participant Alice participant NIM participant Exchange participant ETH participant Bob note left of Alice: Onboarding stage\nSignalling stage\n(as above) note over Exchange: Exchange provides matching service.\nIf signed order matches other signed order\nthen first signed order =: make order\nand last signed order =: take order.\n Ping order owners, hold commission\n as collateral for successful execution. note left of Alice: Init atomic swap Exchange --> Bob: Ping to initiate Swap Bob --> ETH: <convertIntoHtlc> note over ETH: updates Multisig\ns.t. its now a HTLC\nw Alice as recipient,\nHash(secret_b),\nTimeout = n Bob --> Exchange: enc_pub_alice(enc_pub_ex(secret_b)) note over Exchange: Exchange proposes\n early resolve tx\n Formatted s.t. Bob \n is recipient Exchange --> Alice: Ping to complete Swap setup note over Alice: Alice signs\n EARLY_RESOLVE\nRequires double sig\nUsing signed tx\nof Exchange Alice --> NIM: Commits tx note over NIM: HTLC to Bob\n Hash(secret_b)\n Timeout = n Alice --> Exchange: enc_pub_ex(secret_b) Alice --> Exchange: enc_pub_ex(signed(regularTransfer)) note over Exchange: Decrypt\nenc_pub_ex(secret_b)\nto secret_b\nand\nenc_pub_ex(signed(regularTransfer))\n to signed(regularTransfer) note left of Alice: Execute atomic swap Exchange --> NIM: Commit Tx\nrevealing secret_b NIM -> Bob: NIM funds sent to Bob Exchange --> ETH: Commit Tx knowing secret_b ETH -> Alice: ETH funds to Alice ``` **Note:** Transaction to ethereum blockchain is offered as a service by exchange, such that Alice does not need to have gas (Ether) to execute swap. #### Alice sells NIM and buys ETH ```sequence participant Alice participant NIM participant Exchange participant ETH participant Bob note left of Alice: Onboarding stage\nSignalling stage\n(as above) note over Exchange: Exchange provides matching service.\nIf signed order matches other signed order\nthen first signed order =: make order\nand last signed order =: take order.\n Ping order owners, hold commission\n as collateral for successful execution. note left of Alice: Init atomic swap note over Exchange: Exchange proposes\n early resolve tx\n Formatted s.t. Bob \n is recipient Exchange --> Alice: Ping to initiate Swap note over Alice: Alice signs\n EARLY_RESOLVE\nRequires double sig\nUsing signed tx\nof Exchange Alice --> NIM: Commits tx note over NIM: HTLC to Bob\n Hash(secret_a)\n Timeout = n Alice --> Exchange: enc_pub_bob(enc_pub_ex(secret_a)) Alice --> Exchange: enc_pub_bob(enc_pub_ex(signed(regularTransfer))) Exchange --> Bob: Ping to complete Swap setup Bob --> ETH: Commits tx note over ETH: converts Multisig\ninto HTLC w Alice\nas recipient,\nHash(secret_a),\nTimeout = n Bob --> Exchange: enc_pub_ex(secret_a) Bob --> Exchange: enc_pub_ex(signed(regularTransfer)) note over Exchange: Decrypt\nenc_pub_ex(secret_a)\nto secret_a\nand\nenc_pub_ex(signed(regularTransfer))\n to signed(regularTransfer) note left of Alice: Execute atomic swap Exchange --> ETH: Commit Tx revealing secret_a ETH -> Alice: ETH funds to Alice Exchange --> NIM: Commit Tx signed(regularTransfer) NIM -> Bob: NIM funds sent to Bob ``` **Note:** Transaction to ethereum blockchain is offered as a service by exchange, such that Alice does not need to have gas (Ether) to execute swap. ## Partial Fills For example; Bob initiates an HTLC on Ethereum with a price that is matching Alice's price. The webapp pings Alice to let her know that there would exist a matching order which she can take. If Alice is interested in partial fill, then she refunds/resolves her first HTLC and takes the order of Bob. ## Transaction Fees ### Exchange Function: regularTransfer(bytes32 swapId, bytes32 secret) Gas Used By Txn: 35199 Gas Price: 0.00000002 Ether (20 Gwei) Actual Tx Cost/Fee: 0.00070398 Ether ($0.000000) Variable paramters - Gasprice: [1.9 Gwei](https://ethgasstation.info/) - ETH price: [482.90](https://coinmarketcap.com/currencies/ethereum/) Therefore costs of exchange are: \begin{equation} 35199*1.9*10^9*10^{-18}*$482.90 = $0.0322954 \end{equation} **3.00¢ (US cents)** ### Selling ETH convertIntoHtlc(bytes32 msigId, address beneficiary, uint256 amount, uint256 fee, uint256 expirationTime, bytes32 hashedSecret) Gas Used By Txn: 183370 Gas Price: 0.00000002 Ether (20 Gwei) Actual Tx Cost/Fee: 0.0036674 Ether ($0.000000) Variable paramters - Gasprice: [1.9 Gwei](https://ethgasstation.info/) - ETH price: [482.90](https://coinmarketcap.com/currencies/ethereum/) Therefore costs of user selling ETH are: \begin{equation} 183370*1.9*10^9*10^{-18}*$482.90 = $0.168244 \end{equation} **17.00¢ (US cents)** ### Buying NIM Transactions in Nimiq are free up to [a certain threshold](https://github.com/nimiq-network/core/blob/56f4466096f644ac52bd4a3b4b54577c081815de/src/main/generic/consensus/base/mempool/Mempool.js#L448-L452). Therefore costs of user selling NIM are: **0.00¢ (US cents)** ### Total transactions costs per agora-swap Using NIM-ETH pair, the total transcation costs per Agora swap are: **20.00¢ (US cents)** ## Exchange commission Let $t_{free}$ be a time threshold, after which user _pays fees to the exchange_. Let $c_{max}$ be the _commitment amount_ deposited in the multisig as a commitement to faithful trade execution. Note the commitment amount is the Let $t_{expiration}$ be the _expiration time_ of the initated swap. \begin{equation} f = \begin{cases} \text{exchange costs} & \text{if} \quad t \in [0, t_{free}) \\ \frac{(t - t_{free})}{t_{expiration}- t_{free}} & \text{else if} \quad t \in [t_{free}, t_{expiration}) \\ 0 & \text{else} \end{cases} \end{equation} ## API and Market Maker integration See [api.agora.trade](https://api.agora.trade). ## Update path - Imagewallet is constant around which the webapp can be modified. ## Security assumption - **Exchange**: - Exchange provides _honest_ matching service i.e. - Exchange does not front-run - Exchange does not censor - _Solution_: Matching algorithm based on secure MPC. - **Trading**: - Alice and Exchange collude. If they do they can decrypt Bob's secret and release funds to Alice without Bob receiving other side of trade. - _Solution_: Exchange (=Authority) can be replaced by not just any other Authority but by any other Authority _set_ to strenghten the security of Agora Trade. - Alice submits _false orders_. That is orders she does not intend to execute on in an attempt to probe the market. - _Solution_: Deposit as a way of guaranteeing that user has sufficient funds and _committment amount_ that can be claimed and given to Bob in case of false orders. - **User**: - User does not backup Imagewallet as genereated on [dedicated webapp](https://iw.agora.trade). - User does loses password to encrypt/decrypt keys of Imagewallet. - _Solution_: To above two is user education. - User does not lose secrets used for trading. - _Solution_: Send encrypted secret to production ready server for storage. - **Deployment**: - Deployed version is not github version. - Solution: Use IPFS. - **Hardware**: - User computer is compromised - _Solution_: Use airgapped dedicated systems ## Appendix ### Feature requests - [x] Mobile push notifications - [ ] Imagewallet integration - [ ] Web-casts for user education - [ ] Partial fills support - [ ] Batch orders support - [ ] Use [intro.js](https://introjs.com/) for user education - [ ] Allow for p2p trading, i.e trustless OTC trading - [ ] IPFS integration - [ ] Trading Bot example ## Contact For any inquires contact <a href="mailto:company@trinkler.software?Subject=Inquiry" target="_top">company@trinkler.software</a>.