#[repr(C)]pub struct Metrics {
pub last_updated: i64,
pub weekly_active_users: u32,
pub weekly_activity_count: u32,
pub weekly_retention_rate: u16,
pub community_score: u16,
pub user_weight: u16,
pub activity_weight: u16,
pub retention_weight: u16,
pub customer_reward_share: u16,
pub merchant_reward_share: u16,
pub _padding: [u8; 2],
}
Expand description
Metrics stores weekly community health data used for reward decay calculation.
This struct implements the Enhanced Community-Driven Decay model which adjusts daily rewards based on community health metrics. The community score is calculated using a weighted geometric mean approach combining weekly active users, weekly activity count, and weekly retention rate with dynamic weights based on community age.
§Formula
user_score = min((weekly_active_users / TARGET_WEEKLY_USERS) * 10000, 10000)
activity_score = min((weekly_activity_count / TARGET_WEEKLY_ACTIVITY) * 10000, 10000)
retention_score = min((weekly_retention_rate / TARGET_RETENTION_RATE) * 10000, 10000)
weights = oracle_provided_weights (no longer fixed phases)
community_score = weighted_geometric_mean([user_score, activity_score, retention_score], weights)
decay_factor = smooth_function(community_score) // 0.5 + 0.5 * (1 - (score/10000)^2)
daily_rewards = BASE_DAILY_REWARDS * decay_factor * time_decay / 100_000_000
customer_pool = daily_rewards * customer_reward_share / 10000
merchant_pool = daily_rewards * merchant_reward_share / 10000
§Targets
- TARGET_WEEKLY_USERS: 10,000 active users per week
- TARGET_WEEKLY_ACTIVITY: 50,000 transactions per week (replaces volume-based target)
- TARGET_RETENTION_RATE: 70% retention rate (7000 basis points)
§Dynamic Weight Strategy (Oracle Configurable)
- Launch Phase: [6000, 3000, 1000] - User focus, encourage activity
- Growth Phase: [4000, 3500, 2500] - Balanced metrics
- Maturity Phase: [3000, 3000, 4000] - Quality focus
§Customer/Merchant Split
- Launch: 70% customers, 30% merchants (drive adoption)
- Growth: 60% customers, 40% merchants (balanced)
- Maturity: 50% customers, 50% merchants (equal partnership)
§Decay Factors
- Smooth Decay: Gradual transition from 100% to 50% rewards based on community score
- Time Decay: Linear decay over 5 years, reaching 10% minimum
- Formula: 0.5 + 0.5 * (1 - (score/10000)^2)
- No sharp thresholds, eliminates gaming incentives
§Daily Rewards Impact
- Healthy Community (score = 100%): 50,000 MIRACLE/day (50% of 100,000)
- Growing Community (score = 50%): 87,500 MIRACLE/day (87.5% of 100,000)
- Struggling Community (score = 0%): 100,000 MIRACLE/day (100% of 100,000)
§Edge Cases
- Initial Launch (score = 0%): 100,000 MIRACLE/day (100% of base rewards)
- Zero Activity (no users/activity): 100,000 MIRACLE/day (100% of base rewards)
- Oracle Failure (stale data): Uses last known community score
- New Project: Full rewards encourage early adoption and community growth
§Memory Layout
Optimized for 8-byte alignment with explicit padding to ensure consistent cross-platform behavior and minimal account size (48 bytes total).
Fields§
§last_updated: i64
Last update timestamp (Unix timestamp). Tracks when the metrics were last updated by the oracle.
weekly_active_users: u32
Weekly active users count. Used to calculate user score component of community health.
weekly_activity_count: u32
Weekly activity count (number of transactions, not amounts). Used to calculate activity score component of community health. Replaces volume-based counting for fair mediator platform rewards.
weekly_retention_rate: u16
Weekly retention rate in basis points (0-10000, 0-100%). Percentage of users who return week-over-week.
community_score: u16
Calculated community score (0-10000 basis points). Represents overall community health as percentage (0-100%).
user_weight: u16
User weight in basis points (0-10000) for weighted geometric mean. Determines importance of user count in community score calculation.
activity_weight: u16
Activity weight in basis points (0-10000) for weighted geometric mean. Determines importance of transaction count in community score calculation.
retention_weight: u16
Retention weight in basis points (0-10000) for weighted geometric mean. Determines importance of retention rate in community score calculation.
Customer reward share in basis points (0-10000, 0-100%). Percentage of daily rewards allocated to customers.
Merchant reward share in basis points (0-10000, 0-100%). Percentage of daily rewards allocated to merchants. Must sum to 10000 with customer_reward_share.
_padding: [u8; 2]
Padding to ensure proper alignment (2 bytes to maintain 48-byte struct size)
Implementations§
Trait Implementations§
Source§impl AccountValidation for Metrics
impl AccountValidation for Metrics
fn assert<F>(&self, condition: F) -> Result<&Self, ProgramError>
fn assert_err<F>( &self, condition: F, err: ProgramError, ) -> Result<&Self, ProgramError>
fn assert_msg<F>(&self, condition: F, msg: &str) -> Result<&Self, ProgramError>
fn assert_mut<F>(&mut self, condition: F) -> Result<&mut Self, ProgramError>
fn assert_mut_err<F>( &mut self, condition: F, err: ProgramError, ) -> Result<&mut Self, ProgramError>
fn assert_mut_msg<F>( &mut self, condition: F, msg: &str, ) -> Result<&mut Self, ProgramError>
Source§impl Discriminator for Metrics
impl Discriminator for Metrics
fn discriminator() -> u8
impl Copy for Metrics
impl Pod for Metrics
impl StructuralPartialEq for Metrics
Auto Trait Implementations§
impl Freeze for Metrics
impl RefUnwindSafe for Metrics
impl Send for Metrics
impl Sync for Metrics
impl Unpin for Metrics
impl UnwindSafe for Metrics
Blanket Implementations§
Source§impl<T> AccountDeserialize for Twhere
T: Discriminator + Pod,
impl<T> AccountDeserialize for Twhere
T: Discriminator + Pod,
fn try_from_bytes(data: &[u8]) -> Result<&T, ProgramError>
fn try_from_bytes_mut(data: &mut [u8]) -> Result<&mut T, ProgramError>
Source§impl<T> AccountHeaderDeserialize for Twhere
T: Discriminator + Pod,
impl<T> AccountHeaderDeserialize for Twhere
T: Discriminator + Pod,
fn try_header_from_bytes(data: &[u8]) -> Result<(&T, &[u8]), ProgramError>
fn try_header_from_bytes_mut( data: &mut [u8], ) -> Result<(&mut T, &mut [u8]), ProgramError>
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CheckedAs for T
impl<T> CheckedAs for T
Source§fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
Source§impl<T> CheckedBitPattern for Twhere
T: AnyBitPattern,
impl<T> CheckedBitPattern for Twhere
T: AnyBitPattern,
Source§type Bits = T
type Bits = T
Self
must have the same layout as the specified Bits
except for
the possible invalid bit patterns being checked during
is_valid_bit_pattern
.Source§fn is_valid_bit_pattern(_bits: &T) -> bool
fn is_valid_bit_pattern(_bits: &T) -> bool
bits
as &Self
.Source§impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
Source§fn checked_cast_from(src: Src) -> Option<Dst>
fn checked_cast_from(src: Src) -> Option<Dst>
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more