econia-labs / econia

Hyper-parallelized on-chain order book for the Aptos blockchain
https://econia.dev
Other
134 stars 47 forks source link

Add recognized market list #9

Closed alnoki closed 2 years ago

alnoki commented 2 years ago

Through its permissionless market registration paradigm, Econia allows anyone to register a market for any arbitrary B, Q, E tuple. Hence it is anticipated that Econia will end up facilitating a suite of illiquid long-tail altcoin markets, subject to extreme price volatility and thus participation risk.

In the interest of 1) ensuring a user-friendly retail trading environment, and 2) attracting market makers, it is suggested that a recognized market list be established, which will inform traders of markets meeting the following conditions:

For intance, the recognized market list would likely include L1/stablecoin pairs such as APT/USDC (or APTOS/USDC, depending on Aptos' chosen native coin symbol), wBTC/USDC, and wETH, USDT, as well as protocol token/stablecoin pairs for major Aptos DeFi projects, e.g. USDC-denominated Econia protocol coins.

alnoki commented 2 years ago

Per #13 , Econia no longer uses a B, Q, E paradigm, but instead uses <BaseType, QuoteType> along with lot_size and tick_size to designate individual markets. Market registration is still permissionless, which prohibits malicious actors from attempting to register backwards trading pairs:

For instance if Econia enforced a "canonical ordering", then someone would have to decide the canonical ordering. If the decision process is to be decentralized, then a straightforward solution is for the first registrant to decide canonical ordering. But in this case malicious actors could set up bots to register intentionally-reversed markets in an attempt to block out trading activity, e.g. USDC/wBTC instead of wBTC/USDC. Hence by using a permissionless registration system and a recognized market list, purportedly malicious behavior ends up just being a waste of gas for the actor.

alnoki commented 2 years ago

Econia now implements a market_id, which will make such a list even more straightforward:

Market ID Base Quote Host Lot Size Tick Size
213 APT USDC 0xabc123... 1000 25
789 wBTC USDT 0xdef456... 1 10
243 ETH USDC 0x123abc... 10 100
alnoki commented 2 years ago

Should the recognized market list be implemented on-chain, it could be instituted as a lookup table from {BaseType, QuoteType} to {market_ID, host, lot_size, tick_size}:

struct AssetPair has store {
    /// Base asset type info. When trading an
    /// `aptos_framework::coin::Coin`, corresponds to the phantom
    /// `CoinType`, for instance `MyCoin` rather than
    /// `Coin<MyCoin>`. Otherwise corresponds to `GenericAsset`, or
    /// a non-coin asset indicated by the market host.
    base_type_info: type_info::TypeInfo,
    /// Quote asset type info. When trading an
    /// `aptos_framework::coin::Coin`, corresponds to the phantom
    /// `CoinType`, for instance `MyCoin` rather than
    /// `Coin<MyCoin>`. Otherwise corresponds to `GenericAsset`, or
    /// a non-coin asset indicated by the market host.
    quote_type_info: type_info::TypeInfo,
}

struct MarketMetadata has store {
    /// 0-indexed market ID from `econia::Registry::registry.markets`
    market_id: u64,
    /// Account hosting corresponding `OrderBook`
    host: address,
    /// Number of base units exchanged per lot
    lot_size: u64,
    /// Number of quote units exchanged per tick
    tick_size: u64
}

struct RecognizedMarkets has key {
    /// Map from unique asset pair to recognized market metadata
    map: open_table::OpenTable<AssetPair, MarketMetadata>
}

Here, the lookup table can have public getters that do not result in transaction collisions with the registry.

Additions to the table could be handled by a multisignature account comprised of multiple protocols/integrators, who could additionally revise the MarketMetadata when asset prices change enough to warrant a new recognized lot/tick size. When updating, the setter will need to compare against the registry to verify that lot/tick size are updated correctly.

Should an open table be used, in the interest of allowing inspection of all recognized markets, it may be necessary to update the OpenTable to allow removal of elements. Here, the OpenTable implementation may require an additional wrapper inside:

struct WrappedValue<V> has store {
    /// Value inserted to the table
    value: V,
    /// Vector index in `OpenTable.keys` vector. Necessary for
    /// element removal, via `vector::swap_remove()`
    keys_vector_index: u64
}

/// Extended version of `aptos_framework::table` with vector of
/// contained keys
struct OpenTable<K: copy + drop, V> has store {
    /// Standard table type
    base_table: table::Table<K, WrappedValue<V>>,
    /// Vector of keys contained in table
    keys: vector<K>
}
alnoki commented 2 years ago

Per #19 , an IterableTable with registration events may be more practical