Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit ab04ad3

Browse files
author
Squirrel
authored
Merge pull request #1 from paritytech/giles-more
Pool assets in separate instance
2 parents 3c8fb00 + 0883485 commit ab04ad3

File tree

5 files changed

+115
-28
lines changed

5 files changed

+115
-28
lines changed

frame/dex/rpc/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ impl From<Error> for i32 {
7070
}
7171
}
7272

73-
#[async_trait]
7473
impl<Client, Block, Balance> DexApiServer<Balance> for Dex<Client, Block>
7574
where
7675
Block: BlockT,

frame/dex/src/lib.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@ pub use types::*;
3030

3131
// https://docs.uniswap.org/protocol/V2/concepts/protocol-overview/smart-contracts#minimum-liquidity
3232
// TODO: make it configurable
33+
// TODO: weights and benchmarking.
34+
// TODO: more specific error codes.
35+
// TODO: remove setup.
3336
pub const MIN_LIQUIDITY: u64 = 1;
3437

3538
#[frame_support::pallet]
3639
pub mod pallet {
3740
use super::*;
38-
3941
use frame_support::pallet_prelude::*;
4042
use frame_system::pallet_prelude::*;
4143

@@ -47,7 +49,7 @@ pub mod pallet {
4749
},
4850
Currency, ExistenceRequirement, ReservableCurrency,
4951
},
50-
transactional, PalletId,
52+
PalletId,
5153
};
5254
use sp_runtime::traits::{
5355
AccountIdConversion, AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub,
@@ -93,6 +95,13 @@ pub mod pallet {
9395
+ MutateMetadata<Self::AccountId>
9496
+ Transfer<Self::AccountId>;
9597

98+
type PoolAssets: Inspect<Self::AccountId, AssetId = Self::AssetId, Balance = Self::AssetBalance>
99+
+ Create<Self::AccountId>
100+
+ InspectEnumerable<Self::AccountId>
101+
+ Mutate<Self::AccountId>
102+
+ MutateMetadata<Self::AccountId>
103+
+ Transfer<Self::AccountId>;
104+
96105
/// The dex's pallet id, used for deriving its sovereign account ID.
97106
#[pallet::constant]
98107
type PalletId: Get<PalletId>;
@@ -192,7 +201,6 @@ pub mod pallet {
192201
#[pallet::call]
193202
impl<T: Config> Pallet<T> {
194203
#[pallet::weight(0)]
195-
#[transactional]
196204
pub fn setup(origin: OriginFor<T>, amount: BalanceOf<T>) -> DispatchResult {
197205
let sender = ensure_signed(origin)?;
198206
let pallet_account = Self::account_id();
@@ -216,7 +224,6 @@ pub mod pallet {
216224
}
217225

218226
#[pallet::weight(0)]
219-
#[transactional]
220227
pub fn create_pool(
221228
origin: OriginFor<T>,
222229
asset1: AssetIdOf<T>, // TODO: convert into MultiToken
@@ -231,8 +238,8 @@ pub mod pallet {
231238
ensure!(!Pools::<T>::contains_key(&pool_id), Error::<T>::PoolExists);
232239

233240
let pallet_account = Self::account_id();
234-
T::Assets::create(lp_token, pallet_account.clone(), true, MIN_LIQUIDITY.into())?;
235-
T::Assets::set(lp_token, &pallet_account, "LP".into(), "LP".into(), 0)?;
241+
T::PoolAssets::create(lp_token, pallet_account.clone(), true, MIN_LIQUIDITY.into())?;
242+
T::PoolAssets::set(lp_token, &pallet_account, "LP".into(), "LP".into(), 0)?;
236243

237244
let pool_info = PoolInfo {
238245
owner: sender.clone(),
@@ -251,7 +258,6 @@ pub mod pallet {
251258
}
252259

253260
#[pallet::weight(0)]
254-
#[transactional]
255261
pub fn add_liquidity(
256262
origin: OriginFor<T>,
257263
asset1: AssetIdOf<T>,
@@ -311,7 +317,7 @@ pub mod pallet {
311317
T::Assets::transfer(asset1, &sender, &pallet_account, amount1, false)?;
312318
T::Assets::transfer(asset2, &sender, &pallet_account, amount2, false)?;
313319

314-
let total_supply = T::Assets::total_issuance(pool.lp_token);
320+
let total_supply = T::PoolAssets::total_issuance(pool.lp_token);
315321

316322
let liquidity: AssetBalanceOf<T>;
317323
if total_supply.is_zero() {
@@ -321,7 +327,7 @@ pub mod pallet {
321327
.integer_sqrt()
322328
.checked_sub(&MIN_LIQUIDITY.into())
323329
.ok_or(Error::<T>::Overflow)?;
324-
T::Assets::mint_into(pool.lp_token, &pallet_account, MIN_LIQUIDITY.into())?;
330+
T::PoolAssets::mint_into(pool.lp_token, &pallet_account, MIN_LIQUIDITY.into())?;
325331
} else {
326332
let side1 = amount1
327333
.checked_mul(&total_supply)
@@ -340,7 +346,7 @@ pub mod pallet {
340346

341347
ensure!(liquidity > MIN_LIQUIDITY.into(), Error::<T>::InsufficientLiquidityMinted);
342348

343-
T::Assets::mint_into(pool.lp_token, &mint_to, liquidity)?;
349+
T::PoolAssets::mint_into(pool.lp_token, &mint_to, liquidity)?;
344350

345351
pool.balance1 = reserve1 + amount1;
346352
pool.balance2 = reserve2 + amount2;
@@ -360,7 +366,6 @@ pub mod pallet {
360366
}
361367

362368
#[pallet::weight(0)]
363-
#[transactional]
364369
pub fn remove_liquidity(
365370
origin: OriginFor<T>,
366371
asset1: AssetIdOf<T>,
@@ -385,12 +390,12 @@ pub mod pallet {
385390
let pool = maybe_pool.as_mut().ok_or(Error::<T>::PoolNotFound)?;
386391

387392
let pallet_account = Self::account_id();
388-
T::Assets::transfer(pool.lp_token, &sender, &pallet_account, liquidity, false)?;
393+
T::PoolAssets::transfer(pool.lp_token, &sender, &pallet_account, liquidity, false)?;
389394

390395
let reserve1 = pool.balance1;
391396
let reserve2 = pool.balance2;
392397

393-
let total_supply = T::Assets::total_issuance(pool.lp_token);
398+
let total_supply = T::PoolAssets::total_issuance(pool.lp_token);
394399

395400
let amount1 = liquidity
396401
.checked_mul(&reserve1)
@@ -413,7 +418,7 @@ pub mod pallet {
413418
Error::<T>::InsufficientAmount
414419
);
415420

416-
T::Assets::burn_from(pool.lp_token, &pallet_account, liquidity)?;
421+
T::PoolAssets::burn_from(pool.lp_token, &pallet_account, liquidity)?;
417422

418423
T::Assets::transfer(asset1, &pallet_account, &withdraw_to, amount1, false)?;
419424
T::Assets::transfer(asset2, &pallet_account, &withdraw_to, amount2, false)?;
@@ -436,7 +441,6 @@ pub mod pallet {
436441
}
437442

438443
#[pallet::weight(0)]
439-
#[transactional]
440444
pub fn swap_exact_tokens_for_tokens(
441445
origin: OriginFor<T>,
442446
asset1: AssetIdOf<T>,
@@ -500,7 +504,6 @@ pub mod pallet {
500504
}
501505

502506
#[pallet::weight(0)]
503-
#[transactional]
504507
pub fn swap_tokens_for_exact_tokens(
505508
origin: OriginFor<T>,
506509
asset1: AssetIdOf<T>,
@@ -630,6 +633,7 @@ pub mod pallet {
630633
}
631634

632635
// TODO: extract 0.3% into config
636+
// TODO: could use Permill type
633637
let amount_in_with_fee =
634638
amount_in.checked_mul(&997u64.into()).ok_or(Error::<T>::Overflow)?;
635639

frame/dex/src/mock.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ use super::*;
2121
use crate as pallet_dex;
2222

2323
use frame_support::{
24-
construct_runtime, parameter_types,
24+
construct_runtime,
25+
instances::{Instance1, Instance2},
26+
parameter_types,
2527
traits::{ConstU32, ConstU64},
2628
PalletId,
2729
};
@@ -44,7 +46,8 @@ construct_runtime!(
4446
{
4547
System: frame_system,
4648
Balances: pallet_balances,
47-
Assets: pallet_assets,
49+
Assets: pallet_assets::<Instance1>,
50+
PoolAssets: pallet_assets::<Instance2>,
4851
Dex: pallet_dex,
4952
}
5053
);
@@ -88,7 +91,7 @@ impl pallet_balances::Config for Test {
8891
type ReserveIdentifier = [u8; 8];
8992
}
9093

91-
impl pallet_assets::Config for Test {
94+
impl pallet_assets::Config<Instance1> for Test {
9295
type Event = Event;
9396
type Balance = u64;
9497
type AssetId = u32;
@@ -105,6 +108,24 @@ impl pallet_assets::Config for Test {
105108
type Extra = ();
106109
}
107110

111+
//TODO: limit creation only to dex pallet
112+
impl pallet_assets::Config<Instance2> for Test {
113+
type Event = Event;
114+
type Balance = u64;
115+
type AssetId = u32;
116+
type Currency = Balances;
117+
type ForceOrigin = frame_system::EnsureRoot<u64>;
118+
type AssetDeposit = ConstU64<0>;
119+
type AssetAccountDeposit = ConstU64<0>;
120+
type MetadataDepositBase = ConstU64<0>;
121+
type MetadataDepositPerByte = ConstU64<0>;
122+
type ApprovalDeposit = ConstU64<0>;
123+
type StringLimit = ConstU32<50>;
124+
type Freezer = ();
125+
type WeightInfo = ();
126+
type Extra = ();
127+
}
128+
108129
parameter_types! {
109130
pub const DexPalletId: PalletId = PalletId(*b"py/dexer");
110131
}
@@ -114,6 +135,7 @@ impl Config for Test {
114135
type Currency = Balances;
115136
type AssetBalance = <Self as pallet_balances::Config>::Balance;
116137
type Assets = Assets;
138+
type PoolAssets = PoolAssets;
117139
type AssetId = u32;
118140
type PalletId = DexPalletId;
119141
}

frame/dex/src/tests.rs

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use crate::{mock::*, *};
1919

2020
use frame_support::{
21-
assert_ok,
21+
assert_noop, assert_ok,
2222
traits::{fungibles::InspectEnumerable, Currency},
2323
};
2424

@@ -27,7 +27,7 @@ fn events() -> Vec<Event<Test>> {
2727
.into_iter()
2828
.map(|r| r.event)
2929
.filter_map(|e| if let mock::Event::Dex(inner) = e { Some(inner) } else { None })
30-
.collect::<Vec<_>>();
30+
.collect();
3131

3232
System::reset_events();
3333

@@ -48,6 +48,14 @@ fn assets() -> Vec<u32> {
4848
s
4949
}
5050

51+
fn pool_assets() -> Vec<u32> {
52+
// if the storage would be public:
53+
// let mut s: Vec<_> = pallet_assets::pallet::PoolAsset::<Test>::iter().map(|x| x.0).collect();
54+
let mut s: Vec<_> = <<Test as Config>::PoolAssets>::assets().collect();
55+
s.sort();
56+
s
57+
}
58+
5159
fn create_tokens(owner: u64, tokens: Vec<u32>) {
5260
for token_id in tokens {
5361
assert_ok!(Assets::force_create(Origin::root(), token_id, owner, true, 1));
@@ -63,6 +71,10 @@ fn balance(owner: u64, token_id: u32) -> u64 {
6371
<<Test as Config>::Assets>::balance(token_id, owner)
6472
}
6573

74+
fn pool_balance(owner: u64, token_id: u32) -> u64 {
75+
<<Test as Config>::PoolAssets>::balance(token_id, owner)
76+
}
77+
6678
#[test]
6779
fn create_pool_should_work() {
6880
new_test_ext().execute_with(|| {
@@ -79,7 +91,8 @@ fn create_pool_should_work() {
7991

8092
assert_eq!(events(), [Event::<Test>::PoolCreated { creator: user, pool_id, lp_token }]);
8193
assert_eq!(pools(), vec![pool_id]);
82-
assert_eq!(assets(), vec![token_1, token_2, lp_token]);
94+
assert_eq!(assets(), vec![token_1, token_2]);
95+
assert_eq!(pool_assets(), vec![lp_token]);
8396
});
8497
}
8598

@@ -124,7 +137,7 @@ fn add_liquidity_should_work() {
124137
let pallet_account = Dex::account_id();
125138
assert_eq!(balance(pallet_account, token_1), 10);
126139
assert_eq!(balance(pallet_account, token_2), 10);
127-
assert_eq!(balance(user, lp_token), 9);
140+
assert_eq!(pool_balance(user, lp_token), 9);
128141
});
129142
}
130143

@@ -171,11 +184,11 @@ fn remove_liquidity_should_work() {
171184
let pallet_account = Dex::account_id();
172185
assert_eq!(balance(pallet_account, token_1), 1);
173186
assert_eq!(balance(pallet_account, token_2), 1);
174-
assert_eq!(balance(pallet_account, lp_token), 1);
187+
assert_eq!(pool_balance(pallet_account, lp_token), 1);
175188

176189
assert_eq!(balance(user, token_1), 999);
177190
assert_eq!(balance(user, token_2), 999);
178-
assert_eq!(balance(user, lp_token), 0);
191+
assert_eq!(pool_balance(user, lp_token), 0);
179192
});
180193
}
181194

@@ -260,3 +273,52 @@ fn swap_should_work() {
260273
assert_eq!(balance(pallet_account, token_2), liquidity2 + exchange_amount);
261274
});
262275
}
276+
277+
#[test]
278+
fn same_asset_swap_should_fail() {
279+
new_test_ext().execute_with(|| {
280+
let user = 1;
281+
let token_1 = 1;
282+
let lp_token = 3;
283+
topup_pallet();
284+
285+
create_tokens(user, vec![token_1]);
286+
assert_noop!(
287+
Dex::create_pool(Origin::signed(user), token_1, token_1, lp_token),
288+
Error::<Test>::EqualAssets
289+
);
290+
291+
assert_ok!(Assets::mint(Origin::signed(user), token_1, user, 1000));
292+
293+
let liquidity1 = 1000;
294+
let liquidity2 = 20;
295+
assert_noop!(
296+
Dex::add_liquidity(
297+
Origin::signed(user),
298+
token_1,
299+
token_1,
300+
liquidity1,
301+
liquidity2,
302+
1,
303+
1,
304+
user,
305+
2
306+
),
307+
Error::<Test>::PoolNotFound
308+
);
309+
310+
let exchange_amount = 10;
311+
assert_noop!(
312+
Dex::swap_exact_tokens_for_tokens(
313+
Origin::signed(user),
314+
token_1,
315+
token_1,
316+
exchange_amount,
317+
1,
318+
user,
319+
3
320+
),
321+
Error::<Test>::PoolNotFound
322+
);
323+
});
324+
}

frame/dex/src/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ pub struct PoolInfo<AccountId, AssetId, Balance> {
2828
pub asset1: AssetId,
2929
/// The second asset supported by the pool
3030
pub asset2: AssetId,
31-
/// Pool balance1
31+
/// Pool balance of asset1
3232
pub balance1: Balance,
33-
/// Pool balance2
33+
/// Pool balance of asset2
3434
pub balance2: Balance,
3535
}

0 commit comments

Comments
 (0)