---
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>.