Skip to content

Commit

Permalink
fix: change premium redeem calculation flow
Browse files Browse the repository at this point in the history
  • Loading branch information
nakul1010 committed Dec 11, 2023
1 parent 6e65b86 commit 4c1eb93
Show file tree
Hide file tree
Showing 19 changed files with 249 additions and 100 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

7 changes: 7 additions & 0 deletions crates/fee/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,13 @@ impl<T: Config> Pallet<T> {
<PremiumRedeemFee<T>>::get()
}

/// Get the fee share that users need to pay to redeem tokens.
///
/// # Returns
/// Returns the redeem fee.
pub fn get_redeem_fee_value() -> UnsignedFixedPoint<T> {
<RedeemFee<T>>::get()
}
/// Calculate punishment fee for a Vault that fails to execute a redeem
/// request before the expiry.
///
Expand Down
3 changes: 3 additions & 0 deletions crates/redeem/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkad
sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" }
redeem-rpc-runtime-api = { path = "runtime-api" }

[dependencies.oracle-rpc-runtime-api]
path = '../../oracle/rpc/runtime-api'
4 changes: 4 additions & 0 deletions crates/redeem/rpc/runtime-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ frame-support = { git = "https://github.com/paritytech/substrate", branch = "pol
sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false }

[dependencies.oracle-rpc-runtime-api]
default-features = false
path = '../../../oracle/rpc/runtime-api'

[features]
default = ["std"]
std = [
Expand Down
9 changes: 8 additions & 1 deletion crates/redeem/rpc/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
#![cfg_attr(not(feature = "std"), no_std)]

use codec::Codec;
use frame_support::dispatch::DispatchError;
use oracle_rpc_runtime_api::BalanceWrapper;
use sp_std::vec::Vec;

sp_api::decl_runtime_apis! {
pub trait RedeemApi<AccountId, H256, RedeemRequest> where
pub trait RedeemApi<VaultId, Balance, AccountId, H256, RedeemRequest> where
VaultId: Codec,
Balance: Codec,
AccountId: Codec,
H256: Codec,
RedeemRequest: Codec,
Expand All @@ -16,5 +20,8 @@ sp_api::decl_runtime_apis! {

/// Get all redeem requests for a particular vault
fn get_vault_redeem_requests(vault_id: AccountId) -> Vec<H256>;

/// Get all vaults below the premium redeem threshold, ordered in descending order of this amount
fn get_premium_redeem_vaults() -> Result<Vec<(VaultId, BalanceWrapper<Balance>)>, DispatchError>;
}
}
41 changes: 36 additions & 5 deletions crates/redeem/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,36 @@ use jsonrpsee::{
proc_macros::rpc,
types::error::{CallError, ErrorCode, ErrorObject},
};
use oracle_rpc_runtime_api::BalanceWrapper;
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_runtime::traits::Block as BlockT;
use sp_runtime::{
traits::{Block as BlockT, MaybeDisplay, MaybeFromStr},
DispatchError,
};
use std::sync::Arc;

pub use redeem_rpc_runtime_api::RedeemApi as RedeemRuntimeApi;

fn handle_response<T, E: std::fmt::Debug>(result: Result<Result<T, DispatchError>, E>, msg: String) -> RpcResult<T> {
result
.map_err(|err| internal_err(format!("Runtime error: {:?}: {:?}", msg, err)))?
.map_err(|err| internal_err(format!("Execution error: {:?}: {:?}", msg, err)))
}

#[rpc(client, server)]
pub trait RedeemApi<BlockHash, AccountId, H256, RedeemRequest> {
pub trait RedeemApi<BlockHash, VaultId, Balance, AccountId, H256, RedeemRequest>
where
Balance: Codec + MaybeDisplay + MaybeFromStr,
{
#[method(name = "redeem_getRedeemRequests")]
fn get_redeem_requests(&self, account_id: AccountId, at: Option<BlockHash>) -> RpcResult<Vec<H256>>;

#[method(name = "redeem_getVaultRedeemRequests")]
fn get_vault_redeem_requests(&self, vault_id: AccountId, at: Option<BlockHash>) -> RpcResult<Vec<H256>>;

#[method(name = "redeem_getPremiumRedeemVaults")]
fn get_premium_redeem_vaults(&self, at: Option<BlockHash>) -> RpcResult<Vec<(VaultId, BalanceWrapper<Balance>)>>;
}

fn internal_err<T: ToString>(message: T) -> JsonRpseeError {
Expand Down Expand Up @@ -47,12 +63,14 @@ impl<C, B> Redeem<C, B> {
}

#[async_trait]
impl<C, Block, AccountId, H256, RedeemRequest> RedeemApiServer<<Block as BlockT>::Hash, AccountId, H256, RedeemRequest>
for Redeem<C, Block>
impl<C, Block, VaultId, Balance, AccountId, H256, RedeemRequest>
RedeemApiServer<<Block as BlockT>::Hash, VaultId, Balance, AccountId, H256, RedeemRequest> for Redeem<C, Block>
where
Block: BlockT,
C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
C::Api: RedeemRuntimeApi<Block, AccountId, H256, RedeemRequest>,
C::Api: RedeemRuntimeApi<Block, VaultId, Balance, AccountId, H256, RedeemRequest>,
VaultId: Codec,
Balance: Codec + MaybeDisplay + MaybeFromStr,
AccountId: Codec,
H256: Codec,
RedeemRequest: Codec,
Expand All @@ -76,4 +94,17 @@ where
api.get_vault_redeem_requests(at, vault_id)
.map_err(|e| internal_err(format!("Unable to fetch redeem requests: {:?}", e)))
}

fn get_premium_redeem_vaults(
&self,
at: Option<<Block as BlockT>::Hash>,
) -> RpcResult<Vec<(VaultId, BalanceWrapper<Balance>)>> {
let api = self.client.runtime_api();
let at = at.unwrap_or_else(|| self.client.info().best_hash);

handle_response(
api.get_premium_redeem_vaults(at),
"Unable to find a vault below the premium redeem threshold".into(),
)
}
}
4 changes: 2 additions & 2 deletions crates/redeem/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use vault_registry::{
// Pallets
use crate::Pallet as Redeem;
use btc_relay::Pallet as BtcRelay;
use oracle::Pallet as Oracle;
use oracle::{OracleKey, Pallet as Oracle};
use security::Pallet as Security;
use sp_runtime::FixedPointNumber;
use vault_registry::Pallet as VaultRegistry;

type UnsignedFixedPoint<T> = <T as currency::Config>::UnsignedFixedPoint;

fn collateral<T: crate::Config>(amount: u32) -> Amount<T> {
Expand Down
25 changes: 14 additions & 11 deletions crates/redeem/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,22 @@ pub(crate) mod vault_registry {
use crate::DefaultVaultId;
use currency::Amount;
use frame_support::dispatch::{DispatchError, DispatchResult};
use sp_std::vec::Vec;
use vault_registry::types::{CurrencyId, CurrencySource, DefaultVault};

pub fn calculate_inclusion_fee<T: crate::Config>(
wrapped_currency: CurrencyId<T>,
redeem_transaction_size: u32,
) -> Result<Amount<T>, DispatchError> {
<vault_registry::Pallet<T>>::calculate_inclusion_fee(wrapped_currency, redeem_transaction_size)
}

pub fn get_premium_redeem_vaults<T: crate::Config>(
redeem_transaction_size: u32,
) -> Result<Vec<(DefaultVaultId<T>, Amount<T>)>, DispatchError> {
<vault_registry::Pallet<T>>::get_premium_redeem_vaults(redeem_transaction_size)
}

pub fn get_vault_max_premium_redeem<T: crate::Config>(
vault_id: &DefaultVaultId<T>,
) -> Result<Amount<T>, DispatchError> {
Expand Down Expand Up @@ -199,17 +213,6 @@ pub(crate) mod security {
}
}

#[cfg_attr(test, mockable)]
pub(crate) mod oracle {
use crate::OracleKey;
use frame_support::dispatch::DispatchError;
use oracle::types::UnsignedFixedPoint;

pub fn get_price<T: crate::Config>(key: OracleKey) -> Result<UnsignedFixedPoint<T>, DispatchError> {
<oracle::Pallet<T>>::get_price(key)
}
}

#[cfg_attr(test, mockable)]
pub(crate) mod fee {
use currency::Amount;
Expand Down
19 changes: 9 additions & 10 deletions crates/redeem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ use frame_support::{
transactional,
};
use frame_system::{ensure_root, ensure_signed};
use oracle::OracleKey;
use sp_core::H256;
use sp_runtime::{ArithmeticError, FixedPointNumber};
use sp_std::{convert::TryInto, vec::Vec};
use types::DefaultVaultId;
use vault_registry::{
Expand Down Expand Up @@ -456,7 +454,6 @@ mod self_redeem {
Ok(())
}
}

// "Internal" functions, callable by code.
#[cfg_attr(test, mockable)]
impl<T: Config> Pallet<T> {
Expand Down Expand Up @@ -505,6 +502,9 @@ impl<T: Config> Pallet<T> {
let below_premium_redeem = ext::vault_registry::is_vault_below_premium_threshold::<T>(&vault_id)?;
let currency_id = vault_id.collateral_currency();

// Calculate the premium collateral amount based on whether the redemption is below the premium redeem
// threshold. This should come before increasing the `to_be_redeemed` tokens and locking the amount to
// ensure accurate premium redeem calculations.
let premium_collateral = if below_premium_redeem {
let redeem_amount_wrapped_in_collateral = user_to_be_received_btc.convert_to(currency_id)?;
let premium_redeem_rate = ext::fee::premium_redeem_reward_rate::<T>();
Expand Down Expand Up @@ -797,13 +797,7 @@ impl<T: Config> Pallet<T> {
/// the inclusion fee rate reported by the oracle
pub fn get_current_inclusion_fee(wrapped_currency: CurrencyId<T>) -> Result<Amount<T>, DispatchError> {
let size: u32 = Self::redeem_transaction_size();
let satoshi_per_bytes = ext::oracle::get_price::<T>(OracleKey::FeeEstimation)?;

let fee = satoshi_per_bytes
.checked_mul_int(size)
.ok_or(ArithmeticError::Overflow)?;
let amount = fee.try_into().map_err(|_| Error::<T>::TryIntoIntError)?;
Ok(Amount::new(amount, wrapped_currency))
ext::vault_registry::calculate_inclusion_fee::<T>(wrapped_currency, size)
}

pub fn get_dust_value(currency_id: CurrencyId<T>) -> Amount<T> {
Expand All @@ -821,6 +815,11 @@ impl<T: Config> Pallet<T> {
.collect::<Vec<_>>()
}

pub fn get_premium_redeem_vaults() -> Result<Vec<(DefaultVaultId<T>, Amount<T>)>, DispatchError> {
let size: u32 = Self::redeem_transaction_size();
ext::vault_registry::get_premium_redeem_vaults::<T>(size)
}

/// Fetch all redeem requests for the specified vault.
///
/// # Arguments
Expand Down
3 changes: 0 additions & 3 deletions crates/vault-registry/rpc/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ sp_api::decl_runtime_apis! {
/// Get the vault's collateral (including nomination)
fn get_vault_total_collateral(vault_id: VaultId) -> Result<BalanceWrapper<Balance>, DispatchError>;

/// Get all vaults below the premium redeem threshold, ordered in descending order of this amount
fn get_premium_redeem_vaults() -> Result<Vec<(VaultId, BalanceWrapper<Balance>)>, DispatchError>;

/// Get all vaults with non-zero issuable tokens, ordered in descending order of this amount
fn get_vaults_with_issuable_tokens() -> Result<Vec<(VaultId, BalanceWrapper<Balance>)>, DispatchError>;

Expand Down
16 changes: 0 additions & 16 deletions crates/vault-registry/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ where
at: Option<BlockHash>,
) -> RpcResult<BalanceWrapper<Balance>>;

#[method(name = "vaultRegistry_getPremiumRedeemVaults")]
fn get_premium_redeem_vaults(&self, at: Option<BlockHash>) -> RpcResult<Vec<(VaultId, BalanceWrapper<Balance>)>>;

#[method(name = "vaultRegistry_getVaultsWithIssuableTokens")]
fn get_vaults_with_issuable_tokens(
&self,
Expand Down Expand Up @@ -179,19 +176,6 @@ where
)
}

fn get_premium_redeem_vaults(
&self,
at: Option<<Block as BlockT>::Hash>,
) -> RpcResult<Vec<(VaultId, BalanceWrapper<Balance>)>> {
let api = self.client.runtime_api();
let at = at.unwrap_or_else(|| self.client.info().best_hash);

handle_response(
api.get_premium_redeem_vaults(at),
"Unable to find a vault below the premium redeem threshold".into(),
)
}

fn get_vaults_with_issuable_tokens(
&self,
at: Option<<Block as BlockT>::Hash>,
Expand Down
14 changes: 14 additions & 0 deletions crates/vault-registry/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,16 @@ pub(crate) mod capacity {
}
}

#[cfg_attr(test, mockable)]
pub(crate) mod oracle {
use frame_support::dispatch::DispatchError;
use oracle::{types::UnsignedFixedPoint, OracleKey};

pub fn get_price<T: crate::Config>(key: OracleKey) -> Result<UnsignedFixedPoint<T>, DispatchError> {
<oracle::Pallet<T>>::get_price(key)
}
}

#[cfg_attr(test, mockable)]
pub(crate) mod fee {
use crate::DefaultVaultId;
Expand All @@ -123,4 +133,8 @@ pub(crate) mod fee {
pub fn premium_redeem_reward_rate<T: crate::Config>() -> UnsignedFixedPoint<T> {
<fee::Pallet<T>>::premium_redeem_reward_rate()
}

pub fn get_redeem_fee_value<T: crate::Config>() -> UnsignedFixedPoint<T> {
<fee::Pallet<T>>::get_redeem_fee_value()
}
}
Loading

0 comments on commit 4c1eb93

Please sign in to comment.