use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ServiceFeeSchedule {
pub human_identity_registration: u128,
pub machine_identity_registration: u128,
pub agent_registration: u128,
pub credential_issuance: u128,
pub identity_verification: u128,
pub model_registration: u128,
pub bridge_transfer_base: u128,
}
impl Default for ServiceFeeSchedule {
fn default() -> Self {
const TNZO_DECIMALS: u32 = 18;
const ONE_TNZO: u128 = 10u128.pow(TNZO_DECIMALS);
Self {
human_identity_registration: 10 * ONE_TNZO, machine_identity_registration: 5 * ONE_TNZO, agent_registration: 5 * ONE_TNZO, credential_issuance: 2 * ONE_TNZO, identity_verification: ONE_TNZO, model_registration: 50 * ONE_TNZO, bridge_transfer_base: ONE_TNZO, }
}
}
impl ServiceFeeSchedule {
pub fn new(
human_identity_registration: u128,
machine_identity_registration: u128,
agent_registration: u128,
credential_issuance: u128,
identity_verification: u128,
model_registration: u128,
bridge_transfer_base: u128,
) -> Self {
Self {
human_identity_registration,
machine_identity_registration,
agent_registration,
credential_issuance,
identity_verification,
model_registration,
bridge_transfer_base,
}
}
pub fn calculate_total_collected(
&self,
human_identity_count: u128,
machine_identity_count: u128,
agent_count: u128,
credential_count: u128,
verification_count: u128,
model_count: u128,
bridge_count: u128,
) -> Option<u128> {
let total = self.human_identity_registration
.checked_mul(human_identity_count)?
.checked_add(self.machine_identity_registration.checked_mul(machine_identity_count)?)?
.checked_add(self.agent_registration.checked_mul(agent_count)?)?
.checked_add(self.credential_issuance.checked_mul(credential_count)?)?
.checked_add(self.identity_verification.checked_mul(verification_count)?)?
.checked_add(self.model_registration.checked_mul(model_count)?)?
.checked_add(self.bridge_transfer_base.checked_mul(bridge_count)?)?;
Some(total)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct NetworkCommissionRates {
pub inference_commission_bps: u32,
pub tee_commission_bps: u32,
pub custody_commission_bps: u32,
pub model_hosting_commission_bps: u32,
}
impl Default for NetworkCommissionRates {
fn default() -> Self {
Self {
inference_commission_bps: 500, tee_commission_bps: 500, custody_commission_bps: 500, model_hosting_commission_bps: 500, }
}
}
impl NetworkCommissionRates {
pub fn new(
inference_commission_bps: u32,
tee_commission_bps: u32,
custody_commission_bps: u32,
model_hosting_commission_bps: u32,
) -> Self {
Self {
inference_commission_bps,
tee_commission_bps,
custody_commission_bps,
model_hosting_commission_bps,
}
}
pub fn calculate_inference_commission(&self, payment_amount: u128) -> Option<u128> {
self.calculate_commission(payment_amount, self.inference_commission_bps)
}
pub fn calculate_tee_commission(&self, payment_amount: u128) -> Option<u128> {
self.calculate_commission(payment_amount, self.tee_commission_bps)
}
pub fn calculate_custody_commission(&self, payment_amount: u128) -> Option<u128> {
self.calculate_commission(payment_amount, self.custody_commission_bps)
}
pub fn calculate_model_hosting_commission(&self, payment_amount: u128) -> Option<u128> {
self.calculate_commission(payment_amount, self.model_hosting_commission_bps)
}
fn calculate_commission(&self, amount: u128, bps: u32) -> Option<u128> {
amount
.checked_mul(bps as u128)?
.checked_div(10000)
}
pub fn validate(&self) -> Result<(), &'static str> {
const MAX_BPS: u32 = 10000;
if self.inference_commission_bps > MAX_BPS {
return Err("Inference commission exceeds 100%");
}
if self.tee_commission_bps > MAX_BPS {
return Err("TEE commission exceeds 100%");
}
if self.custody_commission_bps > MAX_BPS {
return Err("Custody commission exceeds 100%");
}
if self.model_hosting_commission_bps > MAX_BPS {
return Err("Model hosting commission exceeds 100%");
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_service_fee_schedule_defaults() {
let fees = ServiceFeeSchedule::default();
const ONE_TNZO: u128 = 1_000_000_000_000_000_000;
assert_eq!(fees.human_identity_registration, 10 * ONE_TNZO);
assert_eq!(fees.machine_identity_registration, 5 * ONE_TNZO);
assert_eq!(fees.agent_registration, 5 * ONE_TNZO);
assert_eq!(fees.credential_issuance, 2 * ONE_TNZO);
assert_eq!(fees.identity_verification, ONE_TNZO);
assert_eq!(fees.model_registration, 50 * ONE_TNZO);
assert_eq!(fees.bridge_transfer_base, ONE_TNZO);
}
#[test]
fn test_service_fee_schedule_total_collected() {
let fees = ServiceFeeSchedule::default();
const ONE_TNZO: u128 = 1_000_000_000_000_000_000;
let total = fees.calculate_total_collected(1, 1, 1, 1, 1, 1, 1).unwrap();
let expected = 10 + 5 + 5 + 2 + 1 + 50 + 1; assert_eq!(total, expected * ONE_TNZO);
}
#[test]
fn test_network_commission_rates_defaults() {
let rates = NetworkCommissionRates::default();
assert_eq!(rates.inference_commission_bps, 500);
assert_eq!(rates.tee_commission_bps, 500);
assert_eq!(rates.custody_commission_bps, 500);
assert_eq!(rates.model_hosting_commission_bps, 500);
}
#[test]
fn test_commission_calculation() {
let rates = NetworkCommissionRates::default();
const ONE_HUNDRED_TNZO: u128 = 100_000_000_000_000_000_000;
let commission = rates.calculate_inference_commission(ONE_HUNDRED_TNZO).unwrap();
assert_eq!(commission, 5_000_000_000_000_000_000);
}
#[test]
fn test_commission_validation() {
let valid_rates = NetworkCommissionRates::default();
assert!(valid_rates.validate().is_ok());
let invalid_rates = NetworkCommissionRates::new(15000, 500, 500, 500);
assert!(invalid_rates.validate().is_err());
}
#[test]
fn test_commission_overflow_protection() {
let rates = NetworkCommissionRates::default();
let result = rates.calculate_inference_commission(u128::MAX);
assert!(result.is_none());
}
}