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

Add Farming functionality to Lottery #1261

Merged
merged 12 commits into from
Nov 22, 2023
7 changes: 6 additions & 1 deletion Cargo.lock

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

1 change: 1 addition & 0 deletions node/src/chain_specs/calamari.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ fn calamari_dev_genesis(
min_deposit: 5_000 * KMA,
min_withdraw: 5_000 * KMA,
gas_reserve: 10_000 * KMA,
farming_pool_params: Default::default(),
},
}
}
Expand Down
1 change: 1 addition & 0 deletions node/src/chain_specs/manta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ fn manta_devnet_genesis(genesis_collators: Vec<Collator>) -> GenesisConfig {
min_deposit: 500 * MANTA,
min_withdraw: 10 * MANTA,
gas_reserve: 1_000 * MANTA,
farming_pool_params: Default::default(),
},
parachain_info: manta_runtime::ParachainInfoConfig {
parachain_id: MANTA_PARACHAIN_ID.into(),
Expand Down
188 changes: 109 additions & 79 deletions pallets/farming/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,51 +430,7 @@ pub mod pallet {
) -> DispatchResult {
let exchanger = ensure_signed(origin)?;

let mut pool_info = Self::pool_infos(pool_id).ok_or(Error::<T>::PoolDoesNotExist)?;
ensure!(
PoolState::state_valid(Action::Deposit, pool_info.state),
Error::<T>::InvalidPoolState
);

if let PoolState::Charged = pool_info.state {
let n: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
ensure!(
n >= pool_info.after_block_to_start,
Error::<T>::CanNotDeposit
);
}

// basic token proportion * add_value * token_proportion
// if basic token proportion and token_proportion both equals to 100%, then the final amount to transfer is equal to add_value
let native_amount = pool_info.basic_token.1.saturating_reciprocal_mul(add_value);
pool_info.tokens_proportion.iter().try_for_each(
|(token, proportion)| -> DispatchResult {
T::MultiCurrency::transfer(
*token,
&exchanger,
&pool_info.keeper,
*proportion * native_amount,
)
},
)?;
Self::add_share(&exchanger, pool_id, &mut pool_info, add_value);

if let Some((gauge_value, gauge_block)) = gauge_info {
Self::gauge_add(
&exchanger,
pool_info.gauge.ok_or(Error::<T>::GaugePoolNotExist)?,
gauge_value,
gauge_block,
)?;
}

Self::deposit_event(Event::Deposited {
who: exchanger,
pid: pool_id,
add_value,
gauge_info,
});
Ok(())
Self::deposit_farming(exchanger, pool_id, add_value, gauge_info)
}

/// `Withdraw` operation only remove share and get claim rewards, then update `withdraw_list` of user share info.
Expand All @@ -488,32 +444,7 @@ pub mod pallet {
) -> DispatchResult {
let exchanger = ensure_signed(origin)?;

let pool_info = Self::pool_infos(pool_id).ok_or(Error::<T>::PoolDoesNotExist)?;
ensure!(
PoolState::state_valid(Action::Withdraw, pool_info.state),
Error::<T>::InvalidPoolState
);

let share_info = Self::shares_and_withdrawn_rewards(pool_id, &exchanger)
.ok_or(Error::<T>::ShareInfoNotExists)?;
ensure!(
share_info.withdraw_list.len() < pool_info.withdraw_limit_count.into(),
Error::<T>::WithdrawLimitCountExceeded
);

Self::remove_share(
&exchanger,
pool_id,
remove_value,
pool_info.withdraw_limit_time,
)?;

Self::deposit_event(Event::Withdrawn {
who: exchanger,
pid: pool_id,
remove_value,
});
Ok(())
Self::withdraw_amount(exchanger, pool_id, remove_value)
}

/// `claim` operation can claim rewards and also un-stake if user share info has `withdraw_list`.
Expand Down Expand Up @@ -555,14 +486,7 @@ pub mod pallet {
pub fn withdraw_claim(origin: OriginFor<T>, pool_id: PoolId) -> DispatchResult {
let exchanger = ensure_signed(origin)?;

let pool_info = Self::pool_infos(pool_id).ok_or(Error::<T>::PoolDoesNotExist)?;
Self::process_withdraw_list(&exchanger, pool_id, &pool_info, false)?;

Self::deposit_event(Event::WithdrawClaimed {
who: exchanger,
pid: pool_id,
});
Ok(())
Self::withdraw_farming(exchanger, pool_id)
}

#[pallet::call_index(6)]
Expand Down Expand Up @@ -942,4 +866,110 @@ impl<T: Config> Pallet<T> {
.saturated_into();
total_reward_proportion
}

pub fn deposit_farming(
exchanger: T::AccountId,
pool_id: PoolId,
add_value: BalanceOf<T>,
gauge_info: Option<(BalanceOf<T>, BlockNumberFor<T>)>,
) -> DispatchResult {
let mut pool_info = Self::pool_infos(pool_id).ok_or(Error::<T>::PoolDoesNotExist)?;
ensure!(
PoolState::state_valid(Action::Deposit, pool_info.state),
Error::<T>::InvalidPoolState
);

if let PoolState::Charged = pool_info.state {
let n: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
ensure!(
n >= pool_info.after_block_to_start,
Error::<T>::CanNotDeposit
);
}

// basic token proportion * add_value * token_proportion
// if basic token proportion and token_proportion both equals to 100%, then the final amount to transfer is equal to add_value
let native_amount = pool_info.basic_token.1.saturating_reciprocal_mul(add_value);
pool_info.tokens_proportion.iter().try_for_each(
|(token, proportion)| -> DispatchResult {
T::MultiCurrency::transfer(
*token,
&exchanger,
&pool_info.keeper,
*proportion * native_amount,
)
},
)?;
Self::add_share(&exchanger, pool_id, &mut pool_info, add_value);

if let Some((gauge_value, gauge_block)) = gauge_info {
Self::gauge_add(
&exchanger,
pool_info.gauge.ok_or(Error::<T>::GaugePoolNotExist)?,
gauge_value,
gauge_block,
)?;
}

Self::deposit_event(Event::Deposited {
who: exchanger,
pid: pool_id,
add_value,
gauge_info,
});
Ok(())
}

pub fn withdraw_farming(exchanger: T::AccountId, pool_id: PoolId) -> DispatchResult {
let pool_info = Self::pool_infos(pool_id).ok_or(Error::<T>::PoolDoesNotExist)?;
Self::process_withdraw_list(&exchanger, pool_id, &pool_info, false)?;

Self::deposit_event(Event::WithdrawClaimed {
who: exchanger,
pid: pool_id,
});
Ok(())
}

pub fn withdraw_amount(
exchanger: T::AccountId,
pool_id: PoolId,
remove_value: Option<BalanceOf<T>>,
) -> DispatchResult {
let pool_info = Self::pool_infos(pool_id).ok_or(Error::<T>::PoolDoesNotExist)?;
ensure!(
PoolState::state_valid(Action::Withdraw, pool_info.state),
Error::<T>::InvalidPoolState
);

let share_info = Self::shares_and_withdrawn_rewards(pool_id, &exchanger)
.ok_or(Error::<T>::ShareInfoNotExists)?;
ensure!(
share_info.withdraw_list.len() < pool_info.withdraw_limit_count.into(),
Error::<T>::WithdrawLimitCountExceeded
);

Self::remove_share(
&exchanger,
pool_id,
remove_value,
pool_info.withdraw_limit_time,
)?;

Self::deposit_event(Event::Withdrawn {
who: exchanger,
pid: pool_id,
remove_value,
});
Ok(())
}

pub fn withdraw_and_unstake(
exchanger: T::AccountId,
pool_id: PoolId,
remove_value: Option<BalanceOf<T>>,
) -> DispatchResult {
Self::withdraw_amount(exchanger.clone(), pool_id, remove_value)?;
Self::withdraw_farming(exchanger, pool_id)
}
}
9 changes: 8 additions & 1 deletion pallets/pallet-lottery/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ function_name = "0.3"
jsonrpsee = { version = "0.16.2", features = ["server", "macros"], optional = true }
log = { version = "0.4.0", default-features = false }
scale-info = { version = "2.1.2", default-features = false, features = ["derive"] }
serde = { version = "1.0.136", default-features = false, optional = true }

# Substrate dependencies
frame-support = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" }
frame-system = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" }
orml-traits = { git = "https://github.com/manta-network/open-runtime-module-library.git", branch = "polkadot-v0.9.37", default-features = false }
sp-api = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" }
sp-arithmetic = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" }
sp-blockchain = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37", optional = true }
Expand All @@ -28,6 +30,7 @@ sp-std = { git = 'https://github.com/paritytech/substrate.git', default-features

# Self dependencies
manta-primitives = { path = "../../primitives/manta", default-features = false }
pallet-farming = { path = '../farming', default-features = false }
pallet-parachain-staking = { path = '../parachain-staking', default-features = false }
runtime-common = { path = "../../runtime/common", default-features = false }
session-key-primitives = { path = '../../primitives/session-keys', default-features = false }
Expand All @@ -38,8 +41,9 @@ rand = { version = "0.8.5", default-features = false, optional = true }

[dev-dependencies]
calamari-runtime = { path = "../../runtime/calamari", default-features = false }
lazy_static = "1.4.0"
manta-collator-selection = { path = "../collator-selection", default-features = false }
pallet-asset-manager = { path = "../asset-manager", default-features = false }
pallet-assets = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" }
pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" }
pallet-preimage = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" }
pallet-randomness = { path = '../randomness', default-features = false }
Expand All @@ -48,6 +52,7 @@ pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.gi
rand = "0.8"
similar-asserts = "1.1.0"
sp-staking = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" }
xcm = { git = "https://github.com/paritytech/polkadot.git", branch = "release-v0.9.37", default-features = false }

[features]
default = ["std"]
Expand Down Expand Up @@ -75,6 +80,8 @@ std = [
'frame-benchmarking/std',
"frame-support/std",
"frame-system/std",
"serde/std",
"pallet-farming/std",
]
try-runtime = [
"frame-support/try-runtime",
Expand Down
Loading
Loading