1. Summary
Tokenlon is imToken's decentralized trading platform, designed to provide imToken users with "faster transaction", "better price", and reliable trading service with "wider selection". The platform applies traditional OTC RFQ/RFS model as its core trading protocol. Users can easily exchange Tokens at Tokenlon without having to transfer the Tokens out of the wallet. For how-to, please click imToken APP and navigate to "Market" at the bottom accessing "Tokenlon" module. You can select the tokens and then start trading.
1. Quotation Mode
Tokenlon applies RFQ(Request-For-Quote)/RFS(Request-For-Stream) mode. The process is similar to a traditional forex OTC desk. Users go to Tokenlon looking for best bid/offer by RFQ. The user requests are sent over to all market makers and the return quotes are aggregated for the best rates. Once the rates are confirmed by the user, the transactions will be sent over to market makers for execution.
The above figure shows the RFQ process. Upon user request, the Tokenlon Server will request different market makers to return the best quotes to the user.
2. Market Maker Quotation
After the user session is established, the Tokenlon Server starts RFQ per Token pair for every 4 seconds, and the prices of all the market makers will be aggregated, then returned to the users.
The market maker side handling is as follows:
The market maker's proxy contract (MMProxy) is the operational balance placeholder of the market maker, and requires the market maker to store a certain amount of Token in the MMProxy. After the user submits the order, the smart contract will automatically deduct the corresponding balance in the MMProxy and transfers the user's traded asset to MMProxy.
MMSK is the SDK that connects the market maker with the Tokenlon system. MMSK converts the quotation of the market maker into a signed order on the chain according to the request of the Tokenlon Server. It then sends the result back to the Tokenlon Server.
Trading engines such as Quoting engine and Hedging system are developed by market makers, which can be connected to the MMSK.
The above MMProxy and MMSK are provided by imToken, and need to be deployed and managed by market makers themselves. The MMProxy will be deployed on Ethereum in advance by imToken.
3. Off-chain Quotation, On-chain Settlement
Tokenlon uses off-chain quotation and on-chain settlement to improve the matching efficiency, as the significant amount of frequent user requests are discarded according to the RFQ/RFS.
Advantages of off-chain quotation:
High efficiency: The existing on-chain quotation models are limited by the block processing time (except algorithmic quotation, which for other reasons fails to meet our demand).
Precision: The price determined by off-chain is guaranteed to settle on-chain, as "you get what you click" for the users. A design of quoting on-chain, however will be problematic, relies on speed of blocks, front-running, and uncertain (even failed) final transaction prices.
Users can choose the most recent quote among stream of real-time off-chain offers. The order is signed by the user and sent to the Ethereum blockchain. In the end, the smart contract on Ethereum handles the trade, exchanging the assets of users' with those of market makers' to complete the trade.
2. Contracts
1. Overall Architecture
The Tokenlon protocol is designed and based on 0x protocol which is used to complete atomic token exchange. It supports ERC20, ETH/Token, Token/ETH and Token/Token trades.
The protocol consists of TokenlonExchange, MarketMakerProxy and UserProxy.
- TokenlonExchange (TE for short) is the entrance of the whole protocol and the main processor of trades.
- MarketMakerProxy (abbreviated as MMProxy) is equivalent to the wallet of a market maker. The market maker needs to store tokens in MMProxy so that TE and 0x protocol can operate.
- UserProxy is the user's proxy contract, which actively transfers user tokens during the trade. The UserProxy also replaces the user to complete the conversion between WETH/ETH carrying out the tedious WETH wrap work for the user.
As shown in the above figure, the entire trade will be sent to TE contract. After the contract is checked, the transaction will be sent to 0x Exchange (0x protocol). As can be seen in the figure, the 0x Exchange is followed by the 0xERC20Proxy contract, which is used to execute the token exchange. After 0x Exchange confirms that the transaction is correct (usually the signature verification and balance check of both parties, etc.), the 0xERC20Proxy will exchange the token from UserProxy and MMProxy according to the amount specified in the order.
2. MMProxy
Each market maker has an independent MMProxy contract to manage token deposit. This means that when a trade occurs, the token required by the user will be deducted from the MMProxy, and accordingly, the token deducted from the user will be stored in the MMProxy. Therefore, market makers should always keep sufficient token deposit in MMProxy. If the balance of some token is insufficient during the trade, the trade will eventually fail, and no funds in the user or contract will be deducted at all.
How is token deduction made in the transaction?
As we learned in the previous section, the tokens are ultimately exchanged by the 0xERC20Proxy contract. How does this exchange take place?
The order is generated by MMSK according to the quotation engine of the market maker. The order will be signed by a wallet address called SIGNER, which cryptographically guarantees the legitimacy of the order. This order will contain basic information of tokenA-tokenB, such as tokenA's amount = 1 and tokenB's amount = 100, then the price at this time is actually 100/1 = 100.00 (i.e. one tokenA can be exchanged for 100 tokenBs).
The user confirmed that the order was completed at a price of 100.0. The USER will sign the order with his user wallet and send the transaction to the TE contract. As shown in the previous section, this transaction will be transferred to 0x Exchange contract.
0x Exchange verifies the signature of the order after receiving the transaction. Exchange calls isValidSignatrue methods of UserProxy and MMProxy respectively. If these two methods return true, the signature verification is successful and the token clearing phase of 0xERC20Proxy is entered.
- Please note:In order to implement isValidSignature, the market maker needs to set the address of SIGNER wallet in the MMProxy contract. IsValidSignature checks whether the SIGNER address of the signature is equal to the SIGNER in the current MMProxy to return the check result.
Next, the 0xERC20Proxy will transfer one token from UserProxy to MMProxy and 100 tokens from MMProxy to UserProxy according to the information in the order.
- Please note: How does 0xERC20Proxy deduct tokens from the MMProxy? Will this be a security concern if anyone can deduct token from MMProxy? The key answer is its approval mechanism. It is to authorize another person's address so that another person's address can transfer funds to his token. In short, it is to allow others to transfer on behalf of my account. Therefore, this operation must be authorized to safe and reliable "others". In the whole system, 0xERC20Proxy is a "reliable other person". In order to realize our trading system, market makers need to authorize certain token operation permissions of MMProxy to the 0xERC20Proxy. Token authorization is an advance condition for a successful transaction.
How to rebalance funds?
If users continue to buy TokenA with TokenB, there will be more and more token A in MMProxy and fewer TokenB, which requires to have two token accounts rebalanced.
The withdraw interface is provided in the MMProxy contract, which market makers can call to withdraw a tokenA from the MMProxy. For the tokenB with insufficient balance, the market maker can use any wallet to transfer tokenB to the MMProxy contract address.
For example, KNC token and cash withdrawal and collection address exist in the Kovan environment:
- KNC:
0x25570c5f2058efc52ff34e47631f41b5f6595d42
- TO:
0x2Ff3b0AD5d1a0F8dA12F7dBFba55f7E78206125F
Use Withdraw in DApp to carry out cash withdrawal. The corresponding parameters in the DApp are shown in the following figure:
Among them, the first item is the token address to be withdrawn, the second item is the collection address to be withdrawn to, and the third item is the withdrawal amount.
Please note: Withdrawal limit is of the uint type. If 1 WETH is withdrawn, it is 1 * pow(10,18), i.e. 10000000000000000, and 18 in pow is decimals of WETH.
How to ensure MMProxy's security?
In the contract, we set up three kinds of permissions, namely owner, operator and signer.
- The owner obtains the highest authority of the contract. It can set the specified wallet as operator.
- The operator is the basic operation authority of the contract. It can set the signer, the token authorization (the authorization of tokens to the 0xERC20Proxy mentioned above) and cash withdrawal and other operations.
- The signer holds signing authority of the contract. 0x Exchange needs isValidSignature for signer signature authentication before it can call 0xERC20Proxy to deduct token in MMProxy.
Reasonable use of three permissions can ensure the security of MMProxy. Reference
- MMProxy contract will be uniformly deployed by imToken and distributed to market makers. And handed over the highest authority (owner) of MMProxy to the market maker.
3.Market Maker Access
The market maker access is divided into two parts, one is to configure the contract and transfer tokens to the contract; The second is to deploy MMSK and provide quotation to MMSK.
1. Configure MMProxy contract
MMProxy is the capital pool of market makers. All token used by market makers for market making need to be recharged into the contract.
Tokenlon-MMProxy contract document
How to configure the MMProxy contract
- Ethereum blockchain has the Ethereum mainnet and Kovan testnet. ETH token on each network is independent from each other. All ETH tokens on Kovan have no value and are only used for testing.
Use imToken to create a wallet, then copy the Ethereum address and provide it to imToken. Wallet tutorial.
If it is a test environment, imToken needs to be switched to developer mode (kovan environment) for configuration. For Prod/Staging environment skip this step.
- In the imToken 2.0 app, go to "My Profile" - "About Us", click the imToken logo 10 times, to open developer mode
- Go to "My Profile" - "Settings" - "Node Settings" - "Ethereum", and select Development. Click save to switch to Kovan testnet. You can also use this setting when switching from Kovan to Prod/Staging.
Use the imToken DApp Browswer to open the permissions and settings DApp:
https://consenlabs.github.io/contract-admin/mmp.html?addr={contract address provided by imToken}
, DApp browser usage tutorial.Set the operator in the DApp, and the operator has all the operation rights of the contract.
- In a test environment, you can set owner\operator\signer to the same wallet address. In production environment, we suggest to use different wallets for the permissions. (Refer to 合约安全操作). Note: Only the wallet with the corresponding permission can enter the DApp to perform the corresponding operation of the contract. Otherwise, the button is not available. Even if the contract operation transaction is sent, the transaction will fail.
Go back to the imToken wallet and switch the wallet to the operator wallet you just set. If the operator is the current wallet, you don't need to switch. Re-enter the DApp after switching the wallet.
Use operator wallet to set signer. signer should be consistent with what you set as marketMakerSigner in MMSK.
As mentioned in Section 2 of Chapter 2, the supported tokens need to be authorized with 0xERC20Proxy. Therefore, a token authorization operation is required. Take the kovan environment as an example (the following are the addresses of the kovan environment, Production/Staging requires the mainnet address):
- WETH:
0xd0a1e359811322d97991e03f863a0c30c2cf029c
// Note: The contract does not support ETH deposits, but WETH - KNC:
0x25570c5f2058efc52ff34e47631f41b5f6595d42
- Spender:
0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e
// Note: This is the Kovan address of 0xERC20Proxy contract Use SetAllowance in the DApp for authorization, and the corresponding parameters in DApp are shown in the following configuration:
Among them, the first item is the token address, which can be filled in batch and separated by
,
. The spender address in item 2 is the 0xERC20Proxy address. After filling the fields, click the SetAllwance button. Note: SetAllowance is only required once per token, and repeated setting may result in transaction failure.
- WETH:
Deposit tokens to MMProxy. Use any wallet to transfer the specified ERC20 token to the MMProxy address. Note: Non-ERC20 tokens cannot be retrieved after being transferred into MMProxy.
2. Deploy MMSK
The function of MMSK is to automatically sign the quotation into an order and feed back the price information to Tokenlon Server.
For installation steps of MMSK, see: tokenlon-mmsk
Note: The contract configuration should be completed before deploying MMSK. Other MMSK related configuration information needs to be synchronized with the imToken team.
Basic Requirements for MMSK Service
- MMSK Interface Minimum Response Time (i.e. Market Maker Quotation Engine Maximum Delay): 1s
- Relying on server deployment areas, it is recommended to deploy in Hong Kong, Japan, Singapore, Taiwan and other APAC locations.
- Depending on the implementation of market makers
indicativePrice
andprice
interface implementation (i.e. the processing efficiency of the quotation engine, considering the network delay, it is recommended that the calculation period is less than 400 milliseconds) - Depending on the market maker interface: zerorpc is recommended; Even if it is provided by http, the internal network request method is needed to reduce the time consumption of external network requests.
- In
indicativePrice
、price
interfaces- Price provision via
base
andquote
, for example,ETH/USDT
exists in thepairs
interface. Market makers need to support price return of the following four transaction parameters (where the amount is always the number ofbase
tokens)base: 'ETH', quote: 'USDT', side: 'BUY', amount: xxx
base: 'ETH', quote: 'USDT', side: 'SELL', amount: xxx
base: 'USDT', quote: 'ETH', side: 'BUY', amount: xxx
base: 'USDT', quote: 'ETH', side: 'SELL', amount: xxx
- Support
minAmount
,maxAmount
returns, and quantitive directionsminAmount
,maxAmount
always represents the minimum and maximum transactable quantity ofbase
tokenbase
minAmount
is always less thanmaxAmount
, and furtherminAmount
andmaxAmount
have a certain quantity input interval in betweenresult: false, exchangeable: false
cases, always returnminAmount
,maxAmount
- When the returned
amount
is smaller than the market maker'sminAmount
or greater than the market maker'smaxAmount
, the market maker needs to returnresult: false, exchangeable: false, message: 'xxx'
, in response to failure to quote
- Price provision via
3. FAQ
MMSK Relevant Information
1. Is the wallet address for MMSK deployment and the private key configuration both the signer wallet?
Yes, the wallet address set via setSigner and MMProxy proxy contract is the same and belongs to the hot wallet. According to the contract security proposal, a cold wallet is also required to be configured for the MMProxy proxy contract setting operation (operator) role.
2. Which protocol should I use for the MMSK API
The interface supports both http and zerorpc. We recommend zerorpc for faster performance.
3. In case 2 market makers reported the same quotation. Who is the preferred one?
Based on Price/Time priority, who comes first will be served first.
4. If the user submits an order for 1000 ETH, but all the markets do not have a quote for 1000 ETH, how can I handle this situation?
We require market makers to give the maximum and minimum acceptable quantities. If the maximum is exceeded, we will directly prompt that orders cannot be placed.
5. Do I need to deploy multiple MMSK based on for trading pairs?
No, only one MMSK needs to be deployed. Market makers provide all trading pairs through one pairs interface.
6. When will maximum and minimum quantities be returned?
The maximum and minimum quantity must be returned to minAmount and maxAmount under any circumstances (no matter whether price is returned normally, exchangeable is true or false), and minAmount must have a certain range with maxAmount. These two quantities are the maximum and minimum quantities that the market maker can support for this trade. On the one hand, they are used for the user to feed back in real time on the imToken operation interface and guide the user to input the quantity that meets the conditions. On the other hand, they are also a protection for the market maker's single transaction volume and position.
7. base and quote in the price and indicativePrice interfaces, for e.g. KNC/ETH, are different for buying and selling directions. Does base and quote change for directions?
Yes, the quote changes for the buying and selling directions, because Tokenlon doesn't have fixed trading pairs. Instead every token trade has a corresponding direction. The MMSK doesn't convert between directions internally to prevent errors in the quotations of market makers.
Considering SNT and ETH, let's assume that the fair value of the exchange rate we calculated is 1 ETH = 7 SNT.
Base = ETH, Quote = SNT, Buy price => 7.01
Base = ETH, Quote = SNT, Sell price => 6.99
Base = SNT, Quote = ETH, Buy price => 0.1429
Base = SNT, Quote = ETH, Sell price => 0.1428
8. If there's no pair besides ETH->SNT and SNT->ETH and users want to exchange ETH for SNT, and there's two different prices: 0.1429 and 6.99 (converted to 0.1431). How will this price be finally decided?
For example, the left is ETH and the right is SNT. At this time, if the user inputs the quantity on the left, ETH will be used as BASE, SNT will be used as Quote, and side will be SELL, which means the user wants to sell ETH for SNT, and the amount is ETH(base) quantity. If the user inputs the quantity on the right, SNT will be used as BASE, ETH will be used as Quote, and side will be used as BUY, which means the user wants to buy SNT with ETH, and the amount is the number of SNT(base). Although there is no big difference in the interface display and user exchange results, it is mainly for the sake of consistency of our user input. For example, the user has entered the quantity on the right side. However, we always use one SNT as the base, so there is bound to be intermediate price conversion. On the one hand, such price conversion may have price errors for market makers. On the other hand, the user may have entered 1,000 SNT because he intended to have 1,000 SNTs in his hand. However, after such conversion, he may not be able to obtain the complete 1,000 SNT in the end, which may be 998.12727463
Contract Relevant Information
1. How do I get the correct contract address of each currency? For example, how do we know the address for adding the new coin OMG and setAllowance?
You can confirm the contract address with the imToken team first.
2. How do I withdraw money from the contract or transfer money to the address in the contract?
Deposit trading Tokens to the MMProxy proxy contract, but do not deposit non-ERC20 which cannot be withdrawn. You cannot transfer ETH, you can only transfer WETH.
3. In the test environment, ETH is converted to WETH and then transferred to the contract address. In the production environment, how does ETH of the exchange transfer
The same operation also needs to be done to convert ETH to WETH, which needs to be first withdrawn from the exchange to imToken or another non-custodial wallet. Then use the wallet to transfer to the WETH contract 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
. The smart contract will automatically return WETH to your wallet address at 1:1 (withdraw ETH to the wallet. Send ETH to WETH Contract to receive the equivalent WETH and send it to the contract.
4. If the contract security best practice requires the owner to be a cold wallet, how do I setOperator
Check imToken cold wallet. It can be used to set the wallet MMProxy via the DAPP: https://consenlabs.github.io/contract-admin/mmp.html.
5. Is there any deduction of handling fees during a trade?
At present, a Tokenlon trade does not require a handling fee, but the final payment of the order requires miners' fee, which is paid by the person who made the final payment. The miners' fee a ETH-to-token trade is paid by the user. The miners' fee for a token-to-ETH trade is paid by imToken, to ensure a fast transaction. The market maker's signer wallet only signs and authorizes operations, and does not need to spend miners' fees.
6. To rebalance, is there any place for operation apart from withdraw call in the MMProxy contract?
Recharge: You can transfer money directly from the exchange or wallet to MMProxy agency contract, but be careful not to withdraw non-ERC20. Non-ERC20 cannot be withdrawn from the contract. ETH cannot be transferred, only WETH can be transferred.
Withdrawal: You can use imToken to open the DApp for graphical operation. The DApp provided by imToken is actually an interface tool for the real contract interface MMProxy. Market makers who are familiar with Ethereum can also encode the ABI by themselves and send it to MMProxy contract to realize relevant functions such as cash withdrawal.