Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cu-23v2xng][Pablo] Integrate Liquidity Bootstrapping Pool #781

Merged
merged 6 commits into from
Mar 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ jobs:
/home/runner/.cargo/bin/rustup show
- name: Run Test (with coverage)
run: |
/home/runner/.cargo/bin/cargo install -f cargo-llvm-cov
/home/runner/.cargo/bin/cargo +nightly-2021-11-08 install -f cargo-llvm-cov
/home/runner/.cargo/bin/rustup component add llvm-tools-preview --toolchain=nightly-2021-11-08
SKIP_WASM_BUILD=1 /home/runner/.cargo/bin/cargo +nightly llvm-cov --workspace --locked --release --verbose --features=runtime-benchmarks --lcov --output-path lcov.info
SKIP_WASM_BUILD=1 /home/runner/.cargo/bin/cargo +nightly-2021-11-08 llvm-cov --workspace --locked --release --verbose --features=runtime-benchmarks --lcov --output-path lcov.info
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
with:
Expand Down
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