Skip to content
This repository has been archived by the owner on May 30, 2023. It is now read-only.

Commit

Permalink
Merge pull request #208 from galacticcouncil/feat/stableswap-pool-acc…
Browse files Browse the repository at this point in the history
…ount

feat: stableswap generate pool account using pool id
  • Loading branch information
mrq1911 committed May 29, 2023
2 parents 90e9669 + f453036 commit 80c9da1
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 56 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion stableswap/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = 'pallet-stableswap'
version = '1.2.0'
version = '1.3.0'
description = 'AMM for correlated assets'
authors = ['GalacticCouncil']
edition = '2021'
Expand Down
26 changes: 15 additions & 11 deletions stableswap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ pub mod pallet {
/// Multi currency mechanism
type Currency: MultiCurrency<Self::AccountId, CurrencyId = Self::AssetId, Balance = Balance>;

/// Account ID constructor
type ShareAccountId: AccountIdFor<Vec<Self::AssetId>, AccountId = Self::AccountId>;
/// Account ID constructor - pool account are derived from unique pool id
type ShareAccountId: AccountIdFor<Self::AssetId, AccountId = Self::AccountId>;

/// Asset registry mechanism
type AssetRegistry: Registry<Self::AssetId, Vec<u8>, Balance, DispatchError>;
Expand Down Expand Up @@ -462,8 +462,8 @@ pub mod pallet {

let pool = Pools::<T>::get(pool_id).ok_or(Error::<T>::PoolNotFound)?;
let asset_idx = pool.find_asset(asset_id).ok_or(Error::<T>::AssetNotInPool)?;
let pool_account = pool.pool_account::<T>();
let balances = pool.balances::<T>();
let pool_account = Self::pool_account(pool_id);
let balances = pool.balances::<T>(&pool_account);
let share_issuance = T::Currency::total_issuance(pool_id);

ensure!(
Expand Down Expand Up @@ -542,8 +542,7 @@ pub mod pallet {

ensure!(amount_out >= min_buy_amount, Error::<T>::BuyLimitNotReached);

let pool = Pools::<T>::get(pool_id).ok_or(Error::<T>::PoolNotFound)?;
let pool_account = pool.pool_account::<T>();
let pool_account = Self::pool_account(pool_id);

T::Currency::transfer(asset_in, &who, &pool_account, amount_in)?;
T::Currency::transfer(asset_out, &pool_account, &who, amount_out)?;
Expand Down Expand Up @@ -599,8 +598,7 @@ pub mod pallet {

let (amount_in, fee_amount) = Self::calculate_in_amount(pool_id, asset_in, asset_out, amount_out)?;

let pool = Pools::<T>::get(pool_id).ok_or(Error::<T>::PoolNotFound)?;
let pool_account = pool.pool_account::<T>();
let pool_account = Self::pool_account(pool_id);

ensure!(amount_in <= max_sell_amount, Error::<T>::SellLimitExceeded);

Expand Down Expand Up @@ -666,7 +664,8 @@ impl<T: Config> Pallet<T> {
let index_in = pool.find_asset(asset_in).ok_or(Error::<T>::AssetNotInPool)?;
let index_out = pool.find_asset(asset_out).ok_or(Error::<T>::AssetNotInPool)?;

let balances = pool.balances::<T>();
let pool_account = Self::pool_account(pool_id);
let balances = pool.balances::<T>(&pool_account);

ensure!(balances[index_in] > Balance::zero(), Error::<T>::InsufficientLiquidity);
ensure!(balances[index_out] > Balance::zero(), Error::<T>::InsufficientLiquidity);
Expand All @@ -693,7 +692,8 @@ impl<T: Config> Pallet<T> {
let index_in = pool.find_asset(asset_in).ok_or(Error::<T>::AssetNotInPool)?;
let index_out = pool.find_asset(asset_out).ok_or(Error::<T>::AssetNotInPool)?;

let balances = pool.balances::<T>();
let pool_account = Self::pool_account(pool_id);
let balances = pool.balances::<T>(&pool_account);

ensure!(balances[index_out] > amount_out, Error::<T>::InsufficientLiquidity);
ensure!(balances[index_in] > Balance::zero(), Error::<T>::InsufficientLiquidity);
Expand Down Expand Up @@ -777,7 +777,7 @@ impl<T: Config> Pallet<T> {
added_assets.insert(asset.asset_id, asset.amount);
}

let pool_account = pool.pool_account::<T>();
let pool_account = Self::pool_account(pool_id);
let mut initial_reserves = Vec::new();
let mut updated_reserves = Vec::new();
for pool_asset in pool.assets.iter() {
Expand Down Expand Up @@ -820,4 +820,8 @@ impl<T: Config> Pallet<T> {
fn is_asset_allowed(pool_id: T::AssetId, asset_id: T::AssetId, operation: Tradability) -> bool {
AssetTradability::<T>::get(pool_id, asset_id).contains(operation)
}

fn pool_account(pool_id: T::AssetId) -> T::AccountId {
T::ShareAccountId::from_assets(&pool_id, Some(POOL_IDENTIFIER))
}
}
9 changes: 4 additions & 5 deletions stableswap/src/tests/add_liquidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::tests::mock::*;
use crate::types::{AssetLiquidity, PoolInfo};
use crate::{assert_balance, Error};
use frame_support::{assert_noop, assert_ok};
use hydradx_traits::AccountIdFor;
use sp_runtime::Permill;

#[test]
Expand Down Expand Up @@ -35,7 +34,7 @@ fn add_initial_liquidity_should_work_when_called_first_time() {

let initial_liquidity_amount = 100 * ONE;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_ok!(Stableswap::add_liquidity(
RuntimeOrigin::signed(BOB),
Expand Down Expand Up @@ -90,7 +89,7 @@ fn add_initial_liquidity_should_fail_when_lp_has_insufficient_balance() {

let initial_liquidity_amount = 100 * ONE;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_noop!(
Stableswap::add_liquidity(
Expand Down Expand Up @@ -159,7 +158,7 @@ fn add_liquidity_should_work_when_initial_liquidity_has_been_provided() {

let amount_added = 100 * ONE;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_ok!(Stableswap::add_liquidity(
RuntimeOrigin::signed(BOB),
Expand Down Expand Up @@ -226,7 +225,7 @@ fn add_liquidity_should_work_when_order_is_not_sorted() {

let amount_added = 100 * ONE;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_ok!(Stableswap::add_liquidity(
RuntimeOrigin::signed(BOB),
Expand Down
7 changes: 3 additions & 4 deletions stableswap/src/tests/invariants.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::tests::mock::*;
use crate::types::{AssetLiquidity, PoolInfo};
use frame_support::assert_ok;
use hydradx_traits::AccountIdFor;
use sp_runtime::{FixedU128, Permill};

use hydra_dx_math::stableswap::calculate_d;
Expand Down Expand Up @@ -83,7 +82,7 @@ proptest! {
.execute_with(|| {
let pool_id = get_pool_id_at(0);

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

let asset_a_reserve = Tokens::free_balance(asset_a, &pool_account);
let asset_b_reserve = Tokens::free_balance(asset_b, &pool_account);
Expand Down Expand Up @@ -158,7 +157,7 @@ proptest! {
.execute_with(|| {
let pool_id = get_pool_id_at(0);

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

let asset_a_reserve = Tokens::free_balance(asset_a, &pool_account);
let asset_b_reserve = Tokens::free_balance(asset_b, &pool_account);
Expand Down Expand Up @@ -227,7 +226,7 @@ proptest! {

let pool_id = get_pool_id_at(0);

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

let asset_a_reserve = Tokens::free_balance(asset_a, &pool_account);
let asset_b_reserve = Tokens::free_balance(asset_b, &pool_account);
Expand Down
20 changes: 9 additions & 11 deletions stableswap/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,31 +319,29 @@ where

pub struct AccountIdConstructor;

impl AccountIdFor<Vec<u32>> for AccountIdConstructor {
impl AccountIdFor<u32> for AccountIdConstructor {
type AccountId = AccountId;

fn from_assets(assets: &Vec<u32>, _identifier: Option<&[u8]>) -> Self::AccountId {
let mut a = assets[0];
let mut b = assets[1];
if a > b {
std::mem::swap(&mut a, &mut b)
}
(a * 1000 + b) as u64
fn from_assets(asset: &u32, _identifier: Option<&[u8]>) -> Self::AccountId {
(asset * 1000) as u64
}

fn name(assets: &Vec<u32>, identifier: Option<&[u8]>) -> Vec<u8> {
fn name(asset: &u32, identifier: Option<&[u8]>) -> Vec<u8> {
let mut buf: Vec<u8> = if let Some(ident) = identifier {
ident.to_vec()
} else {
vec![]
};
buf.extend_from_slice(&(assets[0]).to_le_bytes());
buf.extend_from_slice(&(assets[1]).to_le_bytes());
buf.extend_from_slice(&(asset).to_le_bytes());

buf
}
}

pub(crate) fn pool_account(asset: u32) -> AccountId {
AccountIdConstructor::from_assets(&asset, None)
}

pub(crate) fn retrieve_current_asset_id() -> AssetId {
REGISTERED_ASSETS.with(|v| v.borrow().len() as AssetId)
}
Expand Down
7 changes: 3 additions & 4 deletions stableswap/src/tests/remove_liquidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::tests::mock::*;
use crate::types::{AssetLiquidity, PoolInfo};
use crate::{assert_balance, Error};
use frame_support::{assert_noop, assert_ok};
use hydradx_traits::AccountIdFor;
use sp_runtime::Permill;

#[test]
Expand Down Expand Up @@ -53,7 +52,7 @@ fn remove_liquidity_should_work_when_withdrawing_all_shares() {

let amount_added = 200 * ONE;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_ok!(Stableswap::add_liquidity(
RuntimeOrigin::signed(BOB),
Expand Down Expand Up @@ -130,7 +129,7 @@ fn remove_liquidity_should_apply_fee_when_withdrawing_all_shares() {

let amount_added = 200 * ONE;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_ok!(Stableswap::add_liquidity(
RuntimeOrigin::signed(BOB),
Expand Down Expand Up @@ -409,7 +408,7 @@ fn verify_remove_liquidity_against_research_impl() {

let amount_added = 100_000 * ONE;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b, asset_c, asset_d], None);
let pool_account = pool_account(pool_id);

assert_ok!(Stableswap::add_liquidity(
RuntimeOrigin::signed(BOB),
Expand Down
11 changes: 5 additions & 6 deletions stableswap/src/tests/trades.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::tests::mock::*;
use crate::types::{AssetLiquidity, PoolInfo};
use crate::{assert_balance, Error};
use hydradx_traits::AccountIdFor;

use frame_support::{assert_noop, assert_ok};
use sp_runtime::Permill;
Expand Down Expand Up @@ -51,7 +50,7 @@ fn sell_should_work_when_correct_input_provided() {

let expected = 29_950_934_311_773u128;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_balance!(BOB, asset_a, 170 * ONE);
assert_balance!(BOB, asset_b, expected);
Expand Down Expand Up @@ -105,7 +104,7 @@ fn buy_should_work_when_correct_input_provided() {

let expected_to_sell = 30049242502720u128;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_balance!(BOB, asset_a, 200 * ONE - expected_to_sell);
assert_balance!(BOB, asset_b, 30 * ONE);
Expand Down Expand Up @@ -164,7 +163,7 @@ fn sell_with_fee_should_work_when_correct_input_provided() {

let expected = expected - fee;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_balance!(BOB, asset_a, 170 * ONE);
assert_balance!(BOB, asset_b, expected);
Expand Down Expand Up @@ -222,7 +221,7 @@ fn sell_should_work_when_fee_is_small() {

let expected = expected - fee;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_balance!(BOB, asset_a, 170 * ONE);
assert_balance!(BOB, asset_b, expected);
Expand Down Expand Up @@ -280,7 +279,7 @@ fn buy_should_work_when_fee_is_set() {

let expected_to_sell = expected_to_sell + fee;

let pool_account = AccountIdConstructor::from_assets(&vec![asset_a, asset_b], None);
let pool_account = pool_account(pool_id);

assert_balance!(BOB, asset_a, 200 * ONE - expected_to_sell);
assert_balance!(BOB, asset_b, 30 * ONE);
Expand Down
16 changes: 3 additions & 13 deletions stableswap/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use crate::{Config, MAX_ASSETS_IN_POOL, POOL_IDENTIFIER};
use crate::{Config, MAX_ASSETS_IN_POOL};
use sp_runtime::Permill;
use sp_std::collections::btree_set::BTreeSet;
use sp_std::prelude::*;

use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::traits::ConstU32;
use frame_support::BoundedVec;
use hydradx_traits::AccountIdFor;
use orml_traits::MultiCurrency;
use scale_info::TypeInfo;
use sp_core::RuntimeDebug;
Expand Down Expand Up @@ -46,22 +45,13 @@ where
has_unique_elements(&mut self.assets.iter())
}

pub fn pool_account<T: Config>(&self) -> T::AccountId
pub fn balances<T: Config>(&self, account: &T::AccountId) -> Vec<Balance>
where
T::ShareAccountId: AccountIdFor<Vec<AssetId>, AccountId = T::AccountId>,
{
T::ShareAccountId::from_assets(&self.assets, Some(POOL_IDENTIFIER))
}

pub fn balances<T: Config>(&self) -> Vec<Balance>
where
T::ShareAccountId: AccountIdFor<Vec<AssetId>, AccountId = T::AccountId>,
T::AssetId: From<AssetId>,
{
let acc = self.pool_account::<T>();
self.assets
.iter()
.map(|asset| T::Currency::free_balance((*asset).into(), &acc))
.map(|asset| T::Currency::free_balance((*asset).into(), account))
.collect()
}
}
Expand Down

0 comments on commit 80c9da1

Please sign in to comment.