ggxchain / ggxnode

Apache License 2.0
6 stars 5 forks source link

DEX: use Decimal for price, calculate it automatically #263

Open Warchant opened 1 month ago

Warchant commented 1 month ago

Current make_order has this interface:

pub fn make_order(
    origin: OriginFor<T>,
    asset_id_1: u32,
    asset_id_2: u32,
    offered_amount: BalanceOf<T>,
    requested_amount: BalanceOf<T>,
    price: BalanceOf<T>,
    order_type: OrderType,
    expiration_block: BlockNumberFor<T>,
) -> DispatchResultWithPostInfo {

BalanceOf here is u128 - an integer.

A little bit further in this function this check is executed:

match order_type {
    OrderType::SELL => {
        ensure!(
            offered_amount * price == requested_amount,
            Error::<T>::PriceDoNotMatchOfferedRequestedAmount
        );
    }
    OrderType::BUY => {
        ensure!(
            offered_amount == requested_amount * price,
            Error::<T>::PriceDoNotMatchOfferedRequestedAmount
        );
    }
}

We should not do this check because offered_amount and requested_amount can be integers which represent assets with different precisions. We must convert them to a common precision before we can do multiplication or division.

Example: I create assets A and B, and I want to SELL 5000A for 500B. With current design it is not possible, because:

offered_amount * price == requested_amount,
5000 * price == 500

price would have to be 0.1, but it has an integer type! So this trade is impossible.

The task contains these sub-tasks: