Skip to content

Commit

Permalink
Merge branch 'tomas/masp-total-rewards' (#3375)
Browse files Browse the repository at this point in the history
* tomas/masp-total-rewards:
  changelog: add #3375
  client/rpc: print MASP total rewards in conversions query
  sdk: add a query for MASP total rewards
  shielded_token: store the total rewards minted by MASP
  • Loading branch information
brentstone committed Jun 7, 2024
2 parents 7368256 + b0f851f commit e6e9ba1
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .changelog/unreleased/bug-fixes/3375-masp-total-rewards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Update native token total supply with MASP rewards.
([\#3375](https://github.com/anoma/namada/pull/3375))
2 changes: 2 additions & 0 deletions .changelog/unreleased/improvements/3375-masp-total-rewards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Store total MASP rewards and print them in the conversions query.
([\#3375](https://github.com/anoma/namada/pull/3375))
13 changes: 13 additions & 0 deletions crates/apps_lib/src/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,19 @@ pub async fn query_conversions(
) {
// The chosen token type of the conversions
let target_token = args.token;

if target_token.as_ref().is_none() {
// Query and print the total rewards first
let total_rewards = rpc::query_masp_total_rewards(context.client())
.await
.expect("MASP total rewards should be present");
display!(
context.io(),
"Total rewards of native token minted for shielded pool: {}",
total_rewards.to_string_native()
);
}

// To facilitate human readable token addresses
let tokens = context
.wallet()
Expand Down
25 changes: 24 additions & 1 deletion crates/sdk/src/queries/vp/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub mod client_only_methods {
use borsh::BorshDeserialize;
use namada_core::address::Address;
use namada_core::token;
use namada_token::storage_key::balance_key;
use namada_token::storage_key::{balance_key, masp_total_rewards};

use super::Token;
use crate::queries::{Client, RPC};
Expand Down Expand Up @@ -79,5 +79,28 @@ pub mod client_only_methods {
};
Ok(balance)
}

/// Get the total rewards minted by MASP.
pub async fn masp_total_rewards<CLIENT>(
&self,
client: &CLIENT,
) -> Result<token::Amount, <CLIENT as Client>::Error>
where
CLIENT: Client + Sync,
{
let total_rewards_key = masp_total_rewards();
let response = RPC
.shell()
.storage_value(client, None, None, false, &total_rewards_key)
.await?;

let tokens = if response.data.is_empty() {
token::Amount::zero()
} else {
token::Amount::try_from_slice(&response.data)
.unwrap_or_default()
};
Ok(tokens)
}
}
}
7 changes: 7 additions & 0 deletions crates/sdk/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,13 @@ pub async fn query_conversions<C: crate::queries::Client + Sync>(
convert_response::<C, _>(RPC.shell().read_conversions(client).await)
}

/// Query the total rewards minted by MASP
pub async fn query_masp_total_rewards<C: crate::queries::Client + Sync>(
client: &C,
) -> Result<token::Amount, error::Error> {
convert_response::<C, _>(RPC.vp().token().masp_total_rewards(client).await)
}

/// Query to read the tokens that earn masp rewards.
pub async fn query_masp_reward_tokens<C: crate::queries::Client + Sync>(
client: &C,
Expand Down
11 changes: 4 additions & 7 deletions crates/shielded_token/src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,14 @@ where
use namada_parameters as parameters;
use namada_storage::conversion_state::ConversionLeaf;
use namada_storage::{Error, OptionExt, ResultExt};
use namada_trans_token::storage_key::balance_key;
use namada_trans_token::{MaspDigitPos, NATIVE_MAX_DECIMAL_PLACES};
use rayon::iter::{
IndexedParallelIterator, IntoParallelIterator, ParallelIterator,
};
use rayon::prelude::ParallelSlice;

use crate::mint_rewards;

// The derived conversions will be placed in MASP address space
let masp_addr = MASP;

Expand Down Expand Up @@ -566,12 +567,8 @@ where

// Update the MASP's transparent reward token balance to ensure that it
// is sufficiently backed to redeem rewards
let reward_key = balance_key(&native_token, &masp_addr);
let addr_bal: Amount = storage.read(&reward_key)?.unwrap_or_default();
let new_bal = addr_bal
.checked_add(total_reward)
.ok_or_else(|| Error::new_const("Balance with reward overflow"))?;
storage.write(&reward_key, new_bal)?;
mint_rewards(storage, total_reward)?;

// Try to distribute Merkle tree construction as evenly as possible
// across multiple cores
// Merkle trees must have exactly 2^n leaves to be mergeable
Expand Down
31 changes: 30 additions & 1 deletion crates/shielded_token/src/storage.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use namada_core::address::Address;
use namada_core::address::{self, Address};
use namada_core::arith::checked;
use namada_core::token;
use namada_core::token::Amount;
use namada_core::uint::Uint;
use namada_storage as storage;
use namada_storage::{StorageRead, StorageWrite};
use namada_trans_token::credit_tokens;
use storage::ResultExt;

use crate::storage_key::*;
Expand Down Expand Up @@ -40,3 +41,31 @@ where
storage.write(&masp_locked_amount_target_key(address), raw_target)?;
Ok(())
}

/// Mint MASP rewards tokens and increment the stored total rewards.
pub fn mint_rewards<S>(
storage: &mut S,
amount: token::Amount,
) -> storage::Result<()>
where
S: StorageRead + StorageWrite,
{
let native_token = storage.get_native_token()?;
credit_tokens(storage, &native_token, &address::MASP, amount)?;

let total_rewards_key = masp_total_rewards();
let mut total_rewards = read_total_rewards(storage)?;
checked!(total_rewards += amount)?;
storage.write(&total_rewards_key, total_rewards)
}

/// Read the total rewards minted by MASP.
pub fn read_total_rewards<S>(storage: &S) -> storage::Result<token::Amount>
where
S: StorageRead,
{
let total_rewards_key = masp_total_rewards();
let total_rewards: token::Amount =
storage.read(&total_rewards_key)?.unwrap_or_default();
Ok(total_rewards)
}
9 changes: 9 additions & 0 deletions crates/shielded_token/src/storage_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub const MASP_KD_GAIN_KEY: &str = "derivative_gain";
pub const MASP_LOCKED_AMOUNT_TARGET_KEY: &str = "locked_amount_target";
/// The key for the max reward rate for a given asset
pub const MASP_MAX_REWARD_RATE_KEY: &str = "max_reward_rate";
/// The key for the total inflation rewards minted by MASP
pub const MASP_TOTAL_REWARDS: &str = "max_total_rewards";

/// Obtain the nominal proportional key for the given token
pub fn masp_kp_gain_key(token_addr: &Address) -> storage::Key {
Expand Down Expand Up @@ -163,3 +165,10 @@ pub fn masp_assets_hash_key() -> storage::Key {
.push(&MASP_ASSETS_HASH_KEY.to_owned())
.expect("Cannot obtain a storage key")
}

/// The max reward rate key for the given token
pub fn masp_total_rewards() -> storage::Key {
storage::Key::from(address::MASP.to_db_key())
.push(&MASP_TOTAL_REWARDS.to_owned())
.expect("Cannot obtain a storage key")
}

0 comments on commit e6e9ba1

Please sign in to comment.