Author | Dmitry Kiselev <[email protected]> |
Last update | 2019-09-23 |
1. Abstract
We propose adding functionality for paying order placing fees in assets other than WAVES. The matcher will specify in what assets matcher fees can be accepted. For this purpose, we propose creating several modes for the matcher.
2. Motivation and Purposes
When an order is created on Waves DEX, the user pays the matcher fee for placing the order and finding a suitable counter-order. Subsequently, the matcher pays a network fee when recording an exchange transaction to the blockchain. Currently, the matcher fee is paid in WAVES tokens. However, it’s not always convenient for users because they may not have WAVES in their balance at that moment, among other reasons.
We believe that each matcher should decide which assets it will accept as fees for placing orders. To that purpose, we would like to broaden the functionality for matcher configuration: each matcher will be able to indicate in which assets the matcher fees can be accepted. For users to be able to pay their orders in assets other than WAVES, a new order version (order version 3) will be created, in which the field matcherFeeAsset will be added.
Using the new functionality, we plan to allow paying matcher fees for Waves DEX matcher not only in WAVES, but also in BTC and ETH (other matchers will be able to adjust those parameters). We hope this will make trading more flexible and convenient.
3. Specification
3.1. Blockchain Level
The blockchain will accept all exchange transactions that contain orders with a specified matcher fee asset (sent by Waves’ matcher, a custom matcher or any user). After the broadcast, an exchange transaction will be validated by scripts of all smart accounts and smart assets participating in the transaction. In an utmost case, invocation of 7 scripts is possible: 3 account scripts (matcher, seller, buyer) + 2 asset scripts from the traded pair (amountAsset, priceAsset) + 2 asset scripts of matcher fee assets.
3.2. Matcher Level
For each matcher, a mode can be chosen:
Matcher mode | Description | Configuration |
---|---|---|
dynamic | The matcher accepts fees in one or several assets, and the minimum fee for placing an order is calculated as follows:
min-fee = rate * (base-fee + 0.004 * n), where rate is the value of WAVES in the asset used to pay the fee, base-fee is a base fee in WAVES, n is the number of scripts invoked in the process of validation, except account scripts of the orders’ senders. |
The matcher configuration contains a base-fee in WAVES (currently 0.003).
The API method
returns a list of rates for assets currently accepted for paying the fee:
Admin API methods (for managing the rate list):
|
fixed | The matcher accepts fees in one specific asset, and the minimum order placing fee, min-fee, is fixed. There are no surcharges for script invocation. | The matcher configuration contains:
|
percent | The fee is paid as a percentage of the deal value. There are no surcharges for script invocation. | The matcher configuration indicates:
|
If a user attempts to place an order with an incorrect amount or fees in the wrong asset, they will receive an error message.
4. Rationale
The suggested improvements facilitate paying order fees in assets other than WAVES and flexible configuration of the matcher, specifying in what assets the matcher fee can be accepted.
The dynamic mode is a generalisation of Waves DEX’s matcher’s current mode. This mode allows the matcher to accept fees in tokens other than WAVES. The fee amount depends on the number of scripts that will be invoked in the validation process: each script invocation for validation increases order fee by 0.004 WAVES (converted into the equivalent in matcherFeeAsset).
In fixed mode, the matcher is paid a flat fee in a specified asset, with no extra charges.
In percent mode, the minimum fee amount is stated as a percentage of the deal value. The percent-spending mode enables guaranteed purchase of at least a certain amount. In that mode, a user won’t have to buy an extra amount or make another purchase to receive a precise amount of an asset. The percent-receiving mode enables selling/buying of the maximum possible amount of an asset. It’s most suitable for users who want to buy assets for the entire amount they have in another asset.
In fixed and percent modes, there are no surcharges for script invocation. If a flat fee is implemented (https://forum.wavesplatform.com/t/proposal-new-fee-calculation-model/13601), the surcharge in dynamic mode will be cancelled, and the formula for calculating the minimum fee will be simplified:
min-fee = rate * base-fee
Also, we will be able to discard fixed mode as it will be fully covered by dynamic mode.
5. Backwards Compatibility
After the introduction of order version 3, smart assets can be set as the matcher fee. Smart asset scripts have to validate all transactions with these assets, so if a smart asset is indicated as matcherFeeAssetId, that asset’s script will be invoked in the validation process.
5.1. Whitelist-like smart assets
As an example, we’ll consider whiteListAsset, an asset that can be traded only by whitelisted addresses:
{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE EXPRESSION #-}
{-# SCRIPT_TYPE ASSET #-}
let whiteList = Address(base58'3Mv61qe6egMSjRDZiiuvJDnf3Q1qW9tTZDB')
func isWhitelisted(address : Address) = {
match(getBoolean(whiteList, toBase58String(address.bytes))) {
case b : Boolean => extract(b)
case _ => false
}
}
func checkOrder(order : Order) = {
isWhitelisted(order.sender)
}
match tx {
case tx: ExchangeTransaction =>
checkOrder(tx.sellOrder) && checkOrder(tx.buyOrder)
case _ => false
}
If an option for setting this asset as matcherFeeAsset is introduced, non-whitelisted addresses will be able to bypass the restriction on owning this asset.
Let’s assume Alice and Bob are whitelisted and Carol is not. They will be able to send an exchange transaction, in which Carol is the sender (acts as the matcher), matcherFeeAsset = whiteListAsset, and order senders are Alice and Bob. That transaction will be accepted, even if it is validated by matcherFeeAsset’s script as both orders’ senders are whitelisted. As a result, WhiteListAsset will be transferred to Carol’s account, which is not whitelisted and shouldn’t be able to own that asset.
So, the use of smart assets as matcherFee should be kept in mind at the asset script developing stage:
{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE EXPRESSION #-}
{-# SCRIPT_TYPE ASSET #-}
let thisAsset = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
let whiteList = Address(base58'3Mv61qe6egMSjRDZiiuvJDnf3Q1qW9tTZDB')
func isWhitelisted(address : Address) = {
match(getBoolean(whiteList, toBase58String(address.bytes))) {
case b : Boolean => extract(b)
case _ => false
}
}
func checkOrder(order : Order) = {
let exhcangeTransferIsAllowed = {
let pair = order.assetPair
if (pair.amountAsset == thisAsset || pair.priceAsset == thisAsset) then
isWhitelisted(order.sender)
else true
}
let feeTransferIsAllowed =
if (order.matcherFeeAssetId == thisAsset) then {
let matcher = addressFromPublicKey(order.matcherPublicKey)
isWhitelisted(matcher)
}
else true
exhcangeTransferIsAllowed && feeTransferIsAllowed
}
match tx {
case tx: ExchangeTransaction =>
checkOrder(tx.sellOrder) && checkOrder(tx.buyOrder)
case _ => false
}
We amended the original asset script, adding an extra check:
if (order.matcherFeeAssetId == thisAsset) then {
isWhitelisted(matcher)
}
else true
5.2. Smart assets restricting trading parameters
Let’s consider a situation in which a smart asset that can only be sold at the price of 1 WAVES is indicated as matcherFeeAsset:
{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE EXPRESSION #-}
{-# SCRIPT_TYPE ASSET #-}
match tx {
case tx: ExchangeTransaction =>
let pair = tx.sellOrder.assetPair
(tx.price == 100000000) && (pair.priceAsset == unit)
case _ => false
}
If the matcher wants to accept fees for placing orders in this asset, only exchange transactions with any asset at a price of 1 WAVES will be valid (as all exchange transactions will be validated by this asset script as well), and all other exchange transactions in which the matcher fee was paid in this asset will be invalid. So, while developing smart assets, one should distinguish the situations when an asset is present in a traded asset pair, and when it is used as the matcher fee asset:
{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE EXPRESSION #-}
{-# SCRIPT_TYPE ASSET #-}
let thisAsset = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
match tx {
case tx: ExchangeTransaction =>
let pair = tx.sellOrder.assetPair
if (pair.amountAsset == thisAsset) then
(tx.price == 100000000) && (pair.priceAsset == unit)
else true
case _ => false
}
We amended the original asset script, adding an extra check:
if (pair.amountAsset == thisAsset) then
(tx.price == 100000000) && (pair.priceAsset == unit)
else true
6. Examples and Implementation
6.1. Configuration file example
# Set of allowed order versions
allowed-order-versions = [1, 2, 3]
# Settings for matcher's fee in order
order-fee {
mode = "dynamic" # | "fixed" | "percent"
dynamic {
base-fee = 300000
}
fixed {
asset = "WAVES" # | "some issued asset (base58)"
min-fee = 300000
}
percent {
asset-type = "amount" # | "price" | "spending" | "receiving"
min-fee = 0.1 # in percents
}
}
6.2. Example of calculating final balances for a deal with different matcher modes
Let’s see what fees the buyer, seller and matcher will pay in a sale of 10,000 WAVES at 0.0006 BTC in different matcher modes.
We’ll use the following scheme for asset transfers:
Mode | Config | Sell Matcher Fee | Buy Matcher Fee | Buyer Total | Seller Total | Matcher Total |
---|---|---|---|---|---|---|
dynamic | base-fee = 0.003 | 0.003 WAVES | 0.003 WAVES | +9999.997 WAVES
-6 BTC |
+6 BTC
-10000.003 WAVES |
+0.003 WAVES |
dynamic | base-fee = 0.003 WAVES, rate = 0.015 ETH/WAVES | 0.000045 ETH | 0.000045 ETH | +10000 WAVES -6 BTC -0.000045 ETH | +6 BTC -10000 WAVES -0.000045 ETH | +0.00009 ETH -0.003 WAVES |
dynamic | base-fee = 0.003 WAVES, rate = 0.015 ETH/WAVES | 0.003 WAVES | 0.000045 ETH | +10000 WAVES -6 BTC -0.000045 ETH | +6 BTC -10000.003 WAVES | +0.000045 ETH |
fixed | min-fee = 0.003 WAVES | 0.003 WAVES | 0.003 WAVES | +9999.997 WAVES -6 BTC | +6 BTC -10000.003 WAVES | +0.003 WAVES |
fixed | min-fee = 0.006 BTC | 0.006 BTC | 0.006 BTC | +10000 WAVES -6.006 BTC | +5.994 BTC -10000 WAVES | +0.012 BTC -0.003 WAVES |
fixed | min-fee = 0.000045 ETH | 0.000045 ETH | 0.000045 ETH | +10000 WAVES -6 BTC -0.000045 ETH | +6 BTC -10000 WAVES -0.000045 ETH | +0.00009 ETH -0.003 WAVES |
perccent-amount | min-fee = 0.1% | 10 WAVES | 10 WAVES | +10000 WAVES -6.006 BTC | +5.994 BTC -10000 WAVES | +0.012 BTC -0.003 WAVES |
percent-price | min-fee = 0.1% | 0.006 BTC | 0.006 BTC | +9990 WAVES -6 BTC | +6 BTC -10010 WAVES | +19.997 WAVES |
percent-spending | min-fee = 0.1% | 10 WAVES | 0.006 BTC | +10000 WAVES -6.006 BTC | +6 BTC -10010 WAVES | +9.997 WAVES +0.006 BTC |
percent-receiving | min-fee = 0.1% | 0.006 BTC | 10 WAVES | +9990 WAVES -6 BTC | +5.994 BTC -10000 WAVES | +9.997 WAVES +0.006 BTC |
In all cases the miner receives Miner Total = ExchangeTx Fee = +0.003 WAVES.