Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions creator-keys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ pub mod constants {
pub const TREASURY_ADDRESS: DataKey = DataKey::TreasuryAddress;
pub const ADMIN_ADDRESS: DataKey = DataKey::AdminAddress;
pub const PROTOCOL_FEE_RECIPIENT: DataKey = DataKey::ProtocolFeeRecipient;
pub const PROTOCOL_FEE_RECIPIENT_BALANCE: DataKey = DataKey::ProtocolFeeRecipientBalance;

pub fn creator(creator: &Address) -> DataKey {
creator_key(creator)
Expand Down Expand Up @@ -337,6 +338,7 @@ pub enum DataKey {
TreasuryAddress,
AdminAddress,
ProtocolFeeRecipient,
ProtocolFeeRecipientBalance,
}

#[derive(Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -451,6 +453,53 @@ fn read_required_protocol_fee_config(env: &Env) -> Result<fee::FeeConfig, Contra
read_protocol_fee_config(env).ok_or(ContractError::FeeConfigNotSet)
}

fn read_protocol_fee_recipient_balance(env: &Env) -> i128 {
env.storage()
.persistent()
.get(&constants::storage::PROTOCOL_FEE_RECIPIENT_BALANCE)
.unwrap_or(0)
}

fn credit_protocol_fee_recipient_balance(env: &Env, amount: i128) -> Result<(), ContractError> {
if amount <= 0 {
return Ok(());
}
let updated = read_protocol_fee_recipient_balance(env)
.checked_add(amount)
.ok_or(ContractError::Overflow)?;
env.storage().persistent().set(
&constants::storage::PROTOCOL_FEE_RECIPIENT_BALANCE,
&updated,
);
Ok(())
}

fn accrue_sell_protocol_fee(env: &Env) -> Result<(), ContractError> {
if env
.storage()
.persistent()
.get::<DataKey, Address>(&constants::storage::PROTOCOL_FEE_RECIPIENT)
.is_none()
{
return Ok(());
}

let Some(price) = env
.storage()
.persistent()
.get(&constants::storage::KEY_PRICE)
else {
return Ok(());
};

if read_protocol_fee_config(env).is_none() {
return Ok(());
}

let (_, protocol_fee) = CreatorKeysContract::compute_fees_for_payment(env.clone(), price)?;
credit_protocol_fee_recipient_balance(env, protocol_fee)
}

/// Resolves and validates the shared inputs required by read-only quote methods.
///
/// Reads the key price from storage and confirms the creator is registered.
Expand Down Expand Up @@ -678,6 +727,7 @@ impl CreatorKeysContract {
// supply/holder_count invariants for subsequent reads.
env.storage().persistent().set(&key, &profile);
env.storage().persistent().set(&balance_key, &new_balance);
accrue_sell_protocol_fee(&env)?;

env.events()
.publish((events::SELL_EVENT_NAME, creator, seller), profile.supply);
Expand Down Expand Up @@ -988,6 +1038,13 @@ impl CreatorKeysContract {
.get(&constants::storage::PROTOCOL_FEE_RECIPIENT)
}

/// Read-only view: returns the accrued protocol fee balance for the configured recipient.
///
/// Returns `0` when no protocol fees have been accrued from sell execution.
pub fn get_protocol_recipient_balance(env: Env) -> i128 {
read_protocol_fee_recipient_balance(&env)
}

/// Sets the protocol fee recipient address.
///
/// Only callable by an authorized admin. Rejects the Stellar zero address
Expand Down
Loading
Loading