spl_token_2022/extension/confidential_transfer_fee/
mod.rs

1use {
2    crate::{
3        error::TokenError,
4        extension::{Extension, ExtensionType},
5    },
6    bytemuck::{Pod, Zeroable},
7    solana_program::entrypoint::ProgramResult,
8    solana_zk_sdk::encryption::pod::elgamal::{PodElGamalCiphertext, PodElGamalPubkey},
9    spl_pod::{optional_keys::OptionalNonZeroPubkey, primitives::PodBool},
10    spl_token_confidential_transfer_proof_extraction::encryption::PodFeeCiphertext,
11};
12
13/// Confidential transfer fee extension instructions
14pub mod instruction;
15
16/// Confidential transfer fee extension processor
17pub mod processor;
18
19/// Confidential Transfer Fee extension account information needed for
20/// instructions
21#[cfg(not(target_os = "solana"))]
22pub mod account_info;
23
24/// ElGamal ciphertext containing a transfer fee
25pub type EncryptedFee = PodFeeCiphertext;
26/// ElGamal ciphertext containing a withheld fee in an account
27pub type EncryptedWithheldAmount = PodElGamalCiphertext;
28
29/// Confidential transfer fee extension data for mints
30#[repr(C)]
31#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
32pub struct ConfidentialTransferFeeConfig {
33    /// Optional authority to set the withdraw withheld authority ElGamal key
34    pub authority: OptionalNonZeroPubkey,
35
36    /// Withheld fees from accounts must be encrypted with this ElGamal key.
37    ///
38    /// Note that whoever holds the ElGamal private key for this ElGamal public
39    /// key has the ability to decode any withheld fee amount that are
40    /// associated with accounts. When combined with the fee parameters, the
41    /// withheld fee amounts can reveal information about transfer amounts.
42    pub withdraw_withheld_authority_elgamal_pubkey: PodElGamalPubkey,
43
44    /// If `false`, the harvest of withheld tokens to mint is rejected.
45    pub harvest_to_mint_enabled: PodBool,
46
47    /// Withheld confidential transfer fee tokens that have been moved to the
48    /// mint for withdrawal.
49    pub withheld_amount: EncryptedWithheldAmount,
50}
51
52impl Extension for ConfidentialTransferFeeConfig {
53    const TYPE: ExtensionType = ExtensionType::ConfidentialTransferFeeConfig;
54}
55
56/// Confidential transfer fee
57#[repr(C)]
58#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
59pub struct ConfidentialTransferFeeAmount {
60    /// Amount withheld during confidential transfers, to be harvest to the mint
61    pub withheld_amount: EncryptedWithheldAmount,
62}
63
64impl Extension for ConfidentialTransferFeeAmount {
65    const TYPE: ExtensionType = ExtensionType::ConfidentialTransferFeeAmount;
66}
67
68impl ConfidentialTransferFeeAmount {
69    /// Check if a confidential transfer fee account is in a closable state.
70    pub fn closable(&self) -> ProgramResult {
71        if self.withheld_amount == EncryptedWithheldAmount::zeroed() {
72            Ok(())
73        } else {
74            Err(TokenError::ConfidentialTransferFeeAccountHasWithheldFee.into())
75        }
76    }
77}