Skip to main content

light_client/
fee.rs

1use solana_keypair::Keypair;
2use solana_pubkey::Pubkey;
3
4use crate::rpc::{Rpc, RpcError};
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct FeeConfig {
8    pub state_merkle_tree_rollover: u64,
9    pub address_queue_rollover: u64,
10    // TODO: refactor to allow multiple state and address tree configs
11    // pub state_tree_configs: Vec<StateMerkleTreeConfig>,
12    // pub address_tree_configs: Vec<AddressMerkleTreeConfig>,
13    pub network_fee: u64,
14    pub address_network_fee: u64,
15    pub solana_network_fee: i64,
16}
17
18impl Default for FeeConfig {
19    fn default() -> Self {
20        Self {
21            // rollover fee plus additional lamports for the cpi account
22            state_merkle_tree_rollover: 300,
23            address_queue_rollover: 392,
24            // TODO: refactor to allow multiple state and address tree configs
25            // state_tree_configs: vec![StateMerkleTreeConfig::default()],
26            // address_tree_configs: vec![AddressMerkleTreeConfig::default()],
27            network_fee: 5000,
28            address_network_fee: 5000,
29            solana_network_fee: 5000,
30        }
31    }
32}
33
34impl FeeConfig {
35    pub fn test_batched() -> Self {
36        Self {
37            // rollover fee plus additional lamports for the cpi account
38            state_merkle_tree_rollover: 1,
39            address_queue_rollover: 392, // not batched
40            network_fee: 5000,
41            address_network_fee: 10000,
42            solana_network_fee: 5000,
43        }
44    }
45}
46
47#[derive(Debug, Clone, PartialEq)]
48pub struct TransactionParams {
49    pub v1_input_compressed_accounts: u8,
50    pub v2_input_compressed_accounts: bool,
51    pub v1_output_compressed_accounts: u8,
52    pub num_output_compressed_accounts: u8,
53    pub num_new_addresses: u8,
54    pub compress: i64,
55    pub fee_config: FeeConfig,
56}
57
58pub async fn assert_transaction_params(
59    rpc: &mut impl Rpc,
60    payer: &Pubkey,
61    signers: &[&Keypair],
62    pre_balance: u64,
63    params: Option<TransactionParams>,
64) -> Result<(), RpcError> {
65    if let Some(transaction_params) = params {
66        let mut deduped_signers = signers.to_vec();
67        deduped_signers.dedup();
68        let post_balance = rpc.get_account(*payer).await?.unwrap().lamports;
69
70        // Network fee is charged per input and per address
71        let mut network_fee: i64 = 0;
72
73        // Charge per input compressed account
74        if transaction_params.v1_input_compressed_accounts != 0 {
75            network_fee += transaction_params.fee_config.network_fee as i64
76                * transaction_params.v1_input_compressed_accounts as i64;
77        } else if transaction_params.v2_input_compressed_accounts {
78            network_fee += transaction_params.fee_config.network_fee as i64;
79        }
80        // Charge per V1 output tree
81        if transaction_params.v1_output_compressed_accounts != 0 {
82            network_fee += transaction_params.fee_config.network_fee as i64
83                * transaction_params.v1_output_compressed_accounts as i64;
84        }
85        // Charge per address created
86        if transaction_params.num_new_addresses != 0 {
87            network_fee += transaction_params.fee_config.address_network_fee as i64
88                * transaction_params.num_new_addresses as i64;
89        }
90        let expected_post_balance = pre_balance as i64
91            - i64::from(transaction_params.num_new_addresses)
92                * transaction_params.fee_config.address_queue_rollover as i64
93            - i64::from(transaction_params.num_output_compressed_accounts)
94                * transaction_params.fee_config.state_merkle_tree_rollover as i64
95            - transaction_params.compress
96            - transaction_params.fee_config.solana_network_fee * deduped_signers.len() as i64
97            - network_fee;
98
99        if post_balance as i64 != expected_post_balance {
100            println!("transaction_params: {:?}", transaction_params);
101            println!("pre_balance: {}", pre_balance);
102            println!("post_balance: {}", post_balance);
103            println!("expected post_balance: {}", expected_post_balance);
104            println!(
105                "diff post_balance: {}",
106                post_balance as i64 - expected_post_balance
107            );
108            println!(
109                "rollover fee: {}",
110                transaction_params.fee_config.state_merkle_tree_rollover
111            );
112            println!(
113                "address_network_fee: {}",
114                transaction_params.fee_config.address_network_fee
115            );
116            println!("network_fee: {}", network_fee);
117            println!("num signers {}", deduped_signers.len());
118            println!(
119                "transaction_params.fee_config {:?}",
120                transaction_params.fee_config
121            );
122            return Err(RpcError::CustomError("Transaction fee error.".to_string()));
123        }
124    }
125    Ok(())
126}