diff --git a/Cargo.lock b/Cargo.lock index 8494e93f..afa7f118 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7908,6 +7908,7 @@ dependencies = [ "scale-info", "serai-coins-pallet", "serai-dex-pallet", + "serai-emissions-pallet", "serai-genesis-liquidity-pallet", "serai-in-instructions-primitives", "serai-primitives", diff --git a/substrate/emissions/pallet/src/lib.rs b/substrate/emissions/pallet/src/lib.rs index b21e02eb..9b2ecca7 100644 --- a/substrate/emissions/pallet/src/lib.rs +++ b/substrate/emissions/pallet/src/lib.rs @@ -7,7 +7,7 @@ pub mod pallet { use frame_system::pallet_prelude::*; use frame_support::{pallet_prelude::*, sp_runtime::SaturatedConversion}; - use sp_std::{vec, vec::Vec, collections::btree_map::BTreeMap}; + use sp_std::{vec, vec::Vec, ops::Mul, collections::btree_map::BTreeMap}; use sp_runtime; use coins_pallet::{Config as CoinsConfig, Pallet as Coins, AllowMint}; @@ -44,7 +44,8 @@ pub mod pallet { #[pallet::error] pub enum Error { - MintFailed, + NetworkHasEconomicSecurity, + NoValueForCoin, } #[pallet::event] @@ -336,13 +337,36 @@ pub mod pallet { ) .unwrap(); - Coins::::mint(p, Balance { coin: Coin::Serai, amount: Amount(p_reward) }) - .map_err(|_| Error::::MintFailed)?; + Coins::::mint(p, Balance { coin: Coin::Serai, amount: Amount(p_reward) })?; ValidatorSets::::deposit_stake(n, p, Amount(p_reward))?; } Ok(()) } + + pub fn swap_to_staked_sri( + to: PublicKey, + network: NetworkId, + balance: Balance, + ) -> DispatchResult { + // check the network didn't reach the economic security yet + if Self::economic_security_reached(network) { + Err(Error::::NetworkHasEconomicSecurity)?; + } + + // calculate how much SRI the balance makes + let value = + Dex::::security_oracle_value(balance.coin).ok_or(Error::::NoValueForCoin)?; + // TODO: may panic? It might be best for this math ops to return the result as is instead of + // doing an unwrap so that it can be properly dealt with. + let sri_amount = balance.amount.mul(value); + + // Mint & stake the SRI for the network. + Coins::::mint(to, Balance { coin: Coin::Serai, amount: sri_amount })?; + // TODO: deposit_stake lets staking less than per key share. Should we allow that here? + ValidatorSets::::deposit_stake(network, to, sri_amount)?; + Ok(()) + } } } diff --git a/substrate/in-instructions/pallet/Cargo.toml b/substrate/in-instructions/pallet/Cargo.toml index c91c3250..f35ddf2c 100644 --- a/substrate/in-instructions/pallet/Cargo.toml +++ b/substrate/in-instructions/pallet/Cargo.toml @@ -38,6 +38,7 @@ coins-pallet = { package = "serai-coins-pallet", path = "../../coins/pallet", de dex-pallet = { package = "serai-dex-pallet", path = "../../dex/pallet", default-features = false } validator-sets-pallet = { package = "serai-validator-sets-pallet", path = "../../validator-sets/pallet", default-features = false } genesis-liquidity-pallet = { package = "serai-genesis-liquidity-pallet", path = "../../genesis-liquidity/pallet", default-features = false } +emissions-pallet = { package = "serai-emissions-pallet", path = "../../emissions/pallet", default-features = false } [features] std = [ @@ -60,5 +61,6 @@ std = [ "dex-pallet/std", "validator-sets-pallet/std", "genesis-liquidity-pallet/std", + "emissions-pallet/std", ] default = ["std"] diff --git a/substrate/in-instructions/pallet/src/lib.rs b/substrate/in-instructions/pallet/src/lib.rs index 007147d6..a154405c 100644 --- a/substrate/in-instructions/pallet/src/lib.rs +++ b/substrate/in-instructions/pallet/src/lib.rs @@ -34,12 +34,18 @@ pub mod pallet { }; use genesis_liquidity_pallet::{Pallet as GenesisLiq, Config as GenesisLiqConfig}; + use emissions_pallet::{Pallet as Emissions, Config as EmissionsConfig}; use super::*; #[pallet::config] pub trait Config: - frame_system::Config + CoinsConfig + DexConfig + ValidatorSetsConfig + GenesisLiqConfig + frame_system::Config + + CoinsConfig + + DexConfig + + ValidatorSetsConfig + + GenesisLiqConfig + + EmissionsConfig { type RuntimeEvent: From> + IsType<::RuntimeEvent>; } @@ -207,6 +213,9 @@ pub mod pallet { InInstruction::GenesisLiquidity(address) => { GenesisLiq::::add_coin_liquidity(address.into(), instruction.balance)?; } + InInstruction::SwapToStakedSRI(address, network) => { + Emissions::::swap_to_staked_sri(address.into(), network, instruction.balance)?; + } } Ok(()) } diff --git a/substrate/in-instructions/primitives/src/lib.rs b/substrate/in-instructions/primitives/src/lib.rs index 87d9ce37..1455e423 100644 --- a/substrate/in-instructions/primitives/src/lib.rs +++ b/substrate/in-instructions/primitives/src/lib.rs @@ -79,6 +79,7 @@ pub enum InInstruction { Transfer(SeraiAddress), Dex(DexCall), GenesisLiquidity(SeraiAddress), + SwapToStakedSRI(SeraiAddress, NetworkId), } #[derive(Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebug)] diff --git a/substrate/validator-sets/pallet/src/lib.rs b/substrate/validator-sets/pallet/src/lib.rs index 72ca67d5..0f02661f 100644 --- a/substrate/validator-sets/pallet/src/lib.rs +++ b/substrate/validator-sets/pallet/src/lib.rs @@ -797,12 +797,19 @@ pub mod pallet { total_required } + // TODO: make the increase_allocation public instead? pub fn deposit_stake( network: NetworkId, account: T::AccountId, amount: Amount, ) -> DispatchResult { - // TODO: make the increase_allocation public instead? + // TODO: Should this call be part of the `increase_allocation` since we have to have it + // before each call to it? + Coins::::transfer_internal( + account, + Self::account(), + Balance { coin: Coin::Serai, amount }, + )?; Self::increase_allocation(network, account, amount, true) }