Skip to content

Commit

Permalink
dex amm (#1122)
Browse files Browse the repository at this point in the history
* dex amm

Signed-off-by: zqhxuyuan <zqhxuyuan@gmail.com>

* remove xcm

Signed-off-by: zqhxuyuan <zqhxuyuan@gmail.com>

* remove location

Signed-off-by: zqhxuyuan <zqhxuyuan@gmail.com>

* fix

Signed-off-by: zqhxuyuan <zqhxuyuan@gmail.com>

* add WeightInfo

Signed-off-by: zqhxuyuan <zqhxuyuan@gmail.com>

* benchmark

Signed-off-by: zqhxuyuan <zqhxuyuan@gmail.com>

---------

Signed-off-by: zqhxuyuan <zqhxuyuan@gmail.com>
Co-authored-by: ferrell-code <charlie@manta.network>
Co-authored-by: Georgi Zlatarev <45011053+ghzlatarev@users.noreply.github.com>
  • Loading branch information
3 people committed Jun 1, 2023
1 parent 823ff54 commit b71ab07
Show file tree
Hide file tree
Showing 18 changed files with 1,174 additions and 38 deletions.
51 changes: 51 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ jsonrpsee = { version = "0.16.2", features = ["server"] }
pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" }
sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" }

zenlink-protocol = { git = 'https://github.com/manta-network/Zenlink', branch = "polkadot-v0.9.37" }
zenlink-protocol-rpc = { git = 'https://github.com/manta-network/Zenlink', branch = "polkadot-v0.9.37" }
zenlink-protocol-runtime-api = { git = 'https://github.com/manta-network/Zenlink', branch = "polkadot-v0.9.37" }

# Substrate client dependencies
sc-basic-authorship = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.37" }
sc-chain-spec = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.37" }
Expand Down
11 changes: 10 additions & 1 deletion node/src/rpc/calamari.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ use pallet_manta_sbt::{
rpc::{SBTPull, SBTPullApiServer},
runtime::SBTPullLedgerDiffApi,
};
use zenlink_protocol::AssetId as ZenlinkAssetId;
use zenlink_protocol_rpc::{ZenlinkProtocol, ZenlinkProtocolApiServer};
use zenlink_protocol_runtime_api::ZenlinkProtocolApi as ZenlinkProtocolRuntimeApi;

/// Instantiate all RPC extensions for calamari.
pub fn create_calamari_full<C, P>(deps: FullDeps<C, P>) -> Result<RpcExtension, sc_service::Error>
Expand All @@ -41,6 +44,7 @@ where
C::Api: BlockBuilder<Block>,
C::Api: PullLedgerDiffApi<Block>,
C::Api: SBTPullLedgerDiffApi<Block>,
C::Api: ZenlinkProtocolRuntimeApi<Block, AccountId, ZenlinkAssetId>,
P: TransactionPool + Sync + Send + 'static,
{
use frame_rpc_system::{System, SystemApiServer};
Expand All @@ -65,10 +69,15 @@ where
.merge(manta_pay_rpc)
.map_err(|e| sc_service::Error::Other(e.to_string()))?;

let manta_sbt_rpc: jsonrpsee::RpcModule<SBTPull<Block, C>> = SBTPull::new(client).into_rpc();
let manta_sbt_rpc: jsonrpsee::RpcModule<SBTPull<Block, C>> =
SBTPull::new(client.clone()).into_rpc();
module
.merge(manta_sbt_rpc)
.map_err(|e| sc_service::Error::Other(e.to_string()))?;

module
.merge(ZenlinkProtocol::new(client).into_rpc())
.map_err(|e| sc_service::Error::Other(e.to_string()))?;

Ok(module)
}
15 changes: 14 additions & 1 deletion pallets/asset-manager/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ benchmarks! {
set_min_xcm_fee {
let assets_count = 1000;
for i in 8..assets_count + 8 {

let location: MultiLocation = MultiLocation::new(0, X1(Parachain(i)));
let location = T::Location::from(location.clone());
let metadata = <T::AssetConfig as AssetConfig<T>>::AssetRegistryMetadata::testing_default();
Expand Down Expand Up @@ -154,6 +153,20 @@ benchmarks! {
assert_last_event::<T>(crate::Event::AssetLocationFilteredForOutgoingTransfers { filtered_location: location.into() }.into());
}

register_lp_asset {
let assets_count = 10;
for i in 8..assets_count {
let location: MultiLocation = MultiLocation::new(0, X1(Parachain(i)));
let location = T::Location::from(location.clone());
let metadata = <T::AssetConfig as AssetConfig<T>>::AssetRegistryMetadata::testing_default();
Pallet::<T>::register_asset(RawOrigin::Root.into(), location.clone(), metadata.clone())?;
}
let lp_metadata = <T::AssetConfig as AssetConfig<T>>::AssetRegistryMetadata::testing_default();
}: _(RawOrigin::Root, <T as Config>::AssetId::from(8), <T as Config>::AssetId::from(9), lp_metadata)
verify {
assert_eq!(Pallet::<T>::asset_id_pair_to_lp((<T as Config>::AssetId::from(8), <T as Config>::AssetId::from(9))), Some(<T as Config>::AssetId::from(10)));
assert_eq!(Pallet::<T>::lp_to_asset_id_pair(<T as Config>::AssetId::from(10)), Some((<T as Config>::AssetId::from(8), <T as Config>::AssetId::from(9))));
}
}

impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Runtime);
156 changes: 136 additions & 20 deletions pallets/asset-manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ pub mod pallet {
};
use frame_system::pallet_prelude::*;
use manta_primitives::assets::{
self, AssetConfig, AssetIdLocationMap, AssetIdType, AssetMetadata, AssetRegistry,
FungibleLedger, LocationType,
self, AssetConfig, AssetIdLocationMap, AssetIdLpMap, AssetIdType, AssetMetadata,
AssetRegistry, FungibleLedger, LocationType,
};
use orml_traits::GetByKey;
use sp_runtime::{
Expand Down Expand Up @@ -152,6 +152,22 @@ pub mod pallet {
}
}

impl<T> AssetIdLpMap for Pallet<T>
where
T: Config,
{
fn lp_asset_id(
asset_id0: &Self::AssetId,
asset_id1: &Self::AssetId,
) -> Option<Self::AssetId> {
AssetIdPairToLp::<T>::get((asset_id0, asset_id1))
}

fn lp_asset_pool(pool_id: &Self::AssetId) -> Option<Self::AssetId> {
LpToAssetIdPair::<T>::get(pool_id).map(|_| *pool_id)
}
}

impl<T> assets::UnitsPerSecond for Pallet<T>
where
T: Config,
Expand Down Expand Up @@ -208,6 +224,21 @@ pub mod pallet {
metadata: <T::AssetConfig as AssetConfig<T>>::AssetRegistryMetadata,
},

/// A LP asset was registered
LPAssetRegistered {
/// Asset Id of new Asset
asset_id0: T::AssetId,

/// Asset Id of new Asset
asset_id1: T::AssetId,

/// Asset Id of new Asset
asset_id: T::AssetId,

/// Metadata Registered to Asset Manager
metadata: <T::AssetConfig as AssetConfig<T>>::AssetRegistryMetadata,
},

/// Updated the location of an asset
AssetLocationUpdated {
/// Asset Id of the updated Asset
Expand Down Expand Up @@ -275,7 +306,7 @@ pub mod pallet {
/// Location Already Exists
LocationAlreadyExists,

/// An error occured while creating a new asset at the [`AssetRegistry`].
/// An error occurred while creating a new asset at the [`AssetRegistry`].
ErrorCreatingAsset,

/// There was an attempt to update a non-existent asset.
Expand All @@ -292,6 +323,12 @@ pub mod pallet {

/// An error occurred while updating the parachain id.
UpdateParaIdError,

/// Two asset that used for generate LP asset should different
AssetIdNotDifferent,

/// Two asset that used for generate LP asset should exist
AssetIdNotExist,
}

/// [`AssetId`](AssetConfig::AssetId) to [`MultiLocation`] Map
Expand Down Expand Up @@ -345,11 +382,23 @@ pub mod pallet {
pub type FilteredOutgoingAssetLocations<T: Config> =
StorageMap<_, Blake2_128Concat, Option<MultiLocation>, ()>;

/// AssetId pair to LP asset id mapping.
#[pallet::storage]
#[pallet::getter(fn asset_id_pair_to_lp)]
pub(super) type AssetIdPairToLp<T: Config> =
StorageMap<_, Blake2_128Concat, (T::AssetId, T::AssetId), T::AssetId>;

/// LP asset id to asset id pair mapping.
#[pallet::storage]
#[pallet::getter(fn lp_to_asset_id_pair)]
pub(super) type LpToAssetIdPair<T: Config> =
StorageMap<_, Blake2_128Concat, T::AssetId, (T::AssetId, T::AssetId)>;

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Register a new asset in the asset manager.
///
/// * `origin`: Caller of this extrinsic, the access control is specified by `ForceOrigin`.
/// * `origin`: Caller of this extrinsic, the access control is specified by `ModifierOrigin`.
/// * `location`: Location of the asset.
/// * `metadata`: Asset metadata.
/// * `min_balance`: Minimum balance to keep an account alive, used in conjunction with `is_sufficient`.
Expand All @@ -364,21 +413,8 @@ pub mod pallet {
metadata: <T::AssetConfig as AssetConfig<T>>::AssetRegistryMetadata,
) -> DispatchResult {
T::ModifierOrigin::ensure_origin(origin)?;
ensure!(
!LocationAssetId::<T>::contains_key(&location),
Error::<T>::LocationAlreadyExists
);
let asset_id = Self::next_asset_id_and_increment()?;
<T::AssetConfig as AssetConfig<T>>::AssetRegistry::create_asset(
asset_id,
metadata.clone().into(),
metadata.min_balance().clone(),
metadata.is_sufficient(),
)
.map_err(|_| Error::<T>::ErrorCreatingAsset)?;
AssetIdLocation::<T>::insert(asset_id, &location);
AssetIdMetadata::<T>::insert(asset_id, &metadata);
LocationAssetId::<T>::insert(&location, asset_id);

let asset_id = Self::do_register_asset(Some(&location), &metadata)?;

// If it's a new para id, which will be inserted with AssetCount as 1.
// If not, AssetCount will increased by 1.
Expand All @@ -398,7 +434,7 @@ pub mod pallet {

/// Update an asset by its asset id in the asset manager.
///
/// * `origin`: Caller of this extrinsic, the access control is specified by `ForceOrigin`.
/// * `origin`: Caller of this extrinsic, the access control is specified by `ModifierOrigin`.
/// * `asset_id`: AssetId to be updated.
/// * `location`: `location` to update the asset location.
#[pallet::call_index(1)]
Expand Down Expand Up @@ -598,12 +634,83 @@ pub mod pallet {
}
Ok(())
}

/// Register a LP(liquidity provider) asset in the asset manager based on two given already exist asset.
///
/// * `origin`: Caller of this extrinsic, the access control is specified by `ModifierOrigin`.
/// * `asset_0`: First assetId.
/// * `asset_1`: Second assetId.
/// * `location`: Location of the LP asset.
/// * `metadata`: LP Asset metadata.
#[pallet::call_index(7)]
#[pallet::weight(T::WeightInfo::register_lp_asset())]
#[transactional]
pub fn register_lp_asset(
origin: OriginFor<T>,
asset_0: T::AssetId,
asset_1: T::AssetId,
metadata: <T::AssetConfig as AssetConfig<T>>::AssetRegistryMetadata,
) -> DispatchResult {
T::ModifierOrigin::ensure_origin(origin)?;
ensure!(asset_0 != asset_1, Error::<T>::AssetIdNotDifferent);
ensure!(
AssetIdLocation::<T>::contains_key(asset_0)
&& AssetIdLocation::<T>::contains_key(asset_1),
Error::<T>::AssetIdNotExist
);

let (asset_id0, asset_id1) = Self::sort_asset_id(asset_0, asset_1);
ensure!(
!AssetIdPairToLp::<T>::contains_key((&asset_id0, &asset_id1)),
Error::<T>::AssetAlreadyRegistered
);

let asset_id = Self::do_register_asset(None, &metadata)?;

AssetIdPairToLp::<T>::insert((asset_id0, asset_id1), asset_id);
LpToAssetIdPair::<T>::insert(asset_id, (asset_id0, asset_id1));

Self::deposit_event(Event::<T>::LPAssetRegistered {
asset_id0,
asset_id1,
asset_id,
metadata,
});
Ok(())
}
}

impl<T> Pallet<T>
where
T: Config,
{
/// Register asset by providing optional location and metadata.
pub fn do_register_asset(
location: Option<&T::Location>,
metadata: &<T::AssetConfig as AssetConfig<T>>::AssetRegistryMetadata,
) -> Result<T::AssetId, DispatchError> {
if let Some(location) = location {
ensure!(
!LocationAssetId::<T>::contains_key(location),
Error::<T>::LocationAlreadyExists
);
}
let asset_id = Self::next_asset_id_and_increment()?;
<T::AssetConfig as AssetConfig<T>>::AssetRegistry::create_asset(
asset_id,
metadata.clone().into(),
metadata.min_balance().clone(),
metadata.is_sufficient(),
)
.map_err(|_| Error::<T>::ErrorCreatingAsset)?;
AssetIdMetadata::<T>::insert(asset_id, metadata);
if let Some(location) = location {
AssetIdLocation::<T>::insert(asset_id, location);
LocationAssetId::<T>::insert(location, asset_id);
}
Ok(asset_id)
}

/// Returns and increments the [`NextAssetId`] by one.
#[inline]
fn next_asset_id_and_increment() -> Result<T::AssetId, DispatchError> {
Expand Down Expand Up @@ -654,6 +761,15 @@ pub mod pallet {
pub fn check_outgoing_assets_filter(asset_location: &Option<MultiLocation>) -> bool {
FilteredOutgoingAssetLocations::<T>::contains_key(asset_location)
}

/// Sorted the assets pair
pub fn sort_asset_id(asset_0: T::AssetId, asset_1: T::AssetId) -> (T::AssetId, T::AssetId) {
if asset_0 < asset_1 {
(asset_0, asset_1)
} else {
(asset_1, asset_0)
}
}
}

/// Check the multilocation destination is supported by calamari/manta.
Expand Down
Loading

0 comments on commit b71ab07

Please sign in to comment.