Skip to content

Commit

Permalink
[cu-23v2xng][Pablo] Integrate Liquidity Bootstrapping Pool (#781)
Browse files Browse the repository at this point in the history
* [cu-23v2xng][Pablo] Integrate Liquidity Bootstrapping Pool

* visualizations

* Review

* Fix for main

* Try fix

* Try fix
  • Loading branch information
vimukthi-git authored Mar 19, 2022
1 parent e35e0f0 commit 00a9ea6
Show file tree
Hide file tree
Showing 12 changed files with 1,145 additions and 22 deletions.
2 changes: 1 addition & 1 deletion frame/composable-support/src/validation.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Module for validating extrinsic inputs
//!
//! This module is made of two main parts that are needed to validate an
//! extrinsic input, the `Validated` struct and the `Valitate` trait.
//! extrinsic input, the `Validated` struct and the `Validate` trait.
//!
//! # Example
//! ## Single Validation
Expand Down
102 changes: 99 additions & 3 deletions frame/composable-traits/src/dex.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use crate::{
defi::CurrencyPair,
math::{SafeAdd, SafeSub},
};
use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::{traits::Get, BoundedVec, RuntimeDebug};
use scale_info::TypeInfo;
use sp_runtime::{DispatchError, Permill};
use sp_arithmetic::traits::Saturating;
use sp_runtime::{
traits::{CheckedMul, CheckedSub},
ArithmeticError, DispatchError, Permill,
};
use sp_std::vec::Vec;

use crate::defi::CurrencyPair;

/// Trait for automated market maker.
pub trait Amm {
/// The asset ID type
Expand Down Expand Up @@ -144,6 +150,96 @@ pub struct ConstantProductPoolInfo<AccountId, AssetId> {
pub owner_fee: Permill,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum SaleState {
NotStarted,
Ongoing,
Ended,
}

#[derive(RuntimeDebug, Encode, Decode, MaxEncodedLen, Copy, Clone, PartialEq, Eq, TypeInfo)]
pub struct Sale<BlockNumber> {
/// Block at which the sale start.
pub start: BlockNumber,
/// Block at which the sale stop.
pub end: BlockNumber,
/// Initial weight of the base asset of the current pair.
pub initial_weight: Permill,
/// Final weight of the base asset of the current pair.
pub final_weight: Permill,
}

impl<BlockNumber: TryInto<u64> + Ord + Copy + Saturating + SafeAdd + SafeSub> Sale<BlockNumber> {
// TODO unit test
pub fn current_weights(
&self,
current_block: BlockNumber,
) -> Result<(Permill, Permill), DispatchError> {
/* NOTE(hussein-aitlahcen): currently only linear
Linearly decrease the base asset initial_weight to final_weight.
Quote asset weight is simple 1-base_asset_weight
Assuming final_weight < initial_weight
current_weight = initial_weight - (current - start) / (end - start) * (initial_weight - final_weight)
= initial_weight - normalized_current / sale_duration * weight_range
= initial_weight - point_in_sale * weight_range
*/
let normalized_current_block = current_block.safe_sub(&self.start)?;
let point_in_sale = Permill::from_rational(
normalized_current_block.try_into().map_err(|_| ArithmeticError::Overflow)?,
self.duration().try_into().map_err(|_| ArithmeticError::Overflow)?,
);
let weight_range = self
.initial_weight
.checked_sub(&self.final_weight)
.ok_or(ArithmeticError::Underflow)?;
let current_base_weight = self
.initial_weight
.checked_sub(
&point_in_sale.checked_mul(&weight_range).ok_or(ArithmeticError::Overflow)?,
)
.ok_or(ArithmeticError::Underflow)?;
let current_quote_weight = Permill::one()
.checked_sub(&current_base_weight)
.ok_or(ArithmeticError::Underflow)?;
Ok((current_base_weight, current_quote_weight))
}
}

impl<BlockNumber: Copy + Saturating> Sale<BlockNumber> {
pub fn duration(&self) -> BlockNumber {
// NOTE(hussein-aitlahcen): end > start as previously checked by PoolIsValid.
self.end.saturating_sub(self.start)
}
}

impl<BlockNumber: Ord> Sale<BlockNumber> {
pub fn state(&self, current_block: BlockNumber) -> SaleState {
if current_block < self.start {
SaleState::NotStarted
} else if current_block >= self.end {
SaleState::Ended
} else {
SaleState::Ongoing
}
}
}

#[derive(RuntimeDebug, Encode, Decode, MaxEncodedLen, Copy, Clone, PartialEq, Eq, TypeInfo)]
pub struct LiquidityBootstrappingPoolInfo<AccountId, AssetId, BlockNumber> {
/// Owner of the pool
pub owner: AccountId,
/// Asset pair of the pool along their weight.
/// Base asset is the project token.
/// Quote asset is the collateral token.
pub pair: CurrencyPair<AssetId>,
/// Sale period of the LBP.
pub sale: Sale<BlockNumber>,
/// Trading fees.
pub fee: Permill,
}

#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Eq, RuntimeDebug)]
pub enum DexRouteNode<PoolId> {
Curve(PoolId),
Expand Down
Binary file added frame/pablo/plots/lbp/lbp_buy_project.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frame/pablo/plots/lbp/lbp_sell_project.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frame/pablo/plots/lbp/lbp_spot_price.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frame/pablo/plots/lbp/lbp_weights.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions frame/pablo/src/common_test_functions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
mock::{Pablo, *},
PoolConfiguration::{ConstantProduct, StableSwap},
PoolConfiguration::{ConstantProduct, LiquidityBootstrapping, StableSwap},
PoolInitConfiguration,
};
use frame_support::{
Expand All @@ -11,7 +11,7 @@ use frame_support::{
/// `expected_lp_check` takes base_amount, quote_amount and lp_tokens in order and returns
/// true if lp_tokens are expected for given base_amount, quote_amount.
pub fn common_add_remove_lp(
init_config: PoolInitConfiguration<AssetId>,
init_config: PoolInitConfiguration<AccountId, AssetId, BlockNumber>,
init_base_amount: Balance,
init_quote_amount: Balance,
base_amount: Balance,
Expand All @@ -22,6 +22,7 @@ pub fn common_add_remove_lp(
let pair = match init_config {
PoolInitConfiguration::StableSwap { pair, .. } => pair,
PoolInitConfiguration::ConstantProduct { pair, .. } => pair,
PoolInitConfiguration::LiquidityBootstrapping(pool) => pool.pair,
};
// Mint the tokens
assert_ok!(Tokens::mint_into(pair.base, &ALICE, init_base_amount));
Expand All @@ -41,6 +42,7 @@ pub fn common_add_remove_lp(
let lp_token = match pool {
StableSwap(pool) => pool.lp_token,
ConstantProduct(pool) => pool.lp_token,
LiquidityBootstrapping(_) => panic!("Not implemented"),
};
// Mint the tokens
assert_ok!(Tokens::mint_into(pair.base, &BOB, base_amount));
Expand Down
Loading

0 comments on commit 00a9ea6

Please sign in to comment.