solana_compute_budget/
prioritization_fee.rs

1/// There are 10^6 micro-lamports in one lamport
2const MICRO_LAMPORTS_PER_LAMPORT: u64 = 1_000_000;
3
4type MicroLamports = u128;
5
6pub enum PrioritizationFeeType {
7    ComputeUnitPrice(u64),
8}
9
10#[derive(Default, Debug, PartialEq, Eq)]
11pub struct PrioritizationFeeDetails {
12    fee: u64,
13    compute_unit_price: u64,
14}
15
16impl PrioritizationFeeDetails {
17    pub fn new(fee_type: PrioritizationFeeType, compute_unit_limit: u64) -> Self {
18        match fee_type {
19            PrioritizationFeeType::ComputeUnitPrice(compute_unit_price) => {
20                let micro_lamport_fee: MicroLamports =
21                    (compute_unit_price as u128).saturating_mul(compute_unit_limit as u128);
22                let fee = micro_lamport_fee
23                    .saturating_add(MICRO_LAMPORTS_PER_LAMPORT.saturating_sub(1) as u128)
24                    .checked_div(MICRO_LAMPORTS_PER_LAMPORT as u128)
25                    .and_then(|fee| u64::try_from(fee).ok())
26                    .unwrap_or(u64::MAX);
27
28                Self {
29                    fee,
30                    compute_unit_price,
31                }
32            }
33        }
34    }
35
36    pub fn get_fee(&self) -> u64 {
37        self.fee
38    }
39
40    pub fn get_compute_unit_price(&self) -> u64 {
41        self.compute_unit_price
42    }
43}
44
45#[cfg(test)]
46mod test {
47    use super::{PrioritizationFeeDetails as FeeDetails, PrioritizationFeeType as FeeType, *};
48
49    #[test]
50    fn test_new_with_no_fee() {
51        for compute_units in [0, 1, MICRO_LAMPORTS_PER_LAMPORT, u64::MAX] {
52            assert_eq!(
53                FeeDetails::new(FeeType::ComputeUnitPrice(0), compute_units),
54                FeeDetails::default(),
55            );
56        }
57    }
58
59    #[test]
60    fn test_new_with_compute_unit_price() {
61        assert_eq!(
62            FeeDetails::new(FeeType::ComputeUnitPrice(MICRO_LAMPORTS_PER_LAMPORT - 1), 1),
63            FeeDetails {
64                fee: 1,
65                compute_unit_price: MICRO_LAMPORTS_PER_LAMPORT - 1,
66            },
67            "should round up (<1.0) lamport fee to 1 lamport"
68        );
69
70        assert_eq!(
71            FeeDetails::new(FeeType::ComputeUnitPrice(MICRO_LAMPORTS_PER_LAMPORT), 1),
72            FeeDetails {
73                fee: 1,
74                compute_unit_price: MICRO_LAMPORTS_PER_LAMPORT,
75            },
76        );
77
78        assert_eq!(
79            FeeDetails::new(FeeType::ComputeUnitPrice(MICRO_LAMPORTS_PER_LAMPORT + 1), 1),
80            FeeDetails {
81                fee: 2,
82                compute_unit_price: MICRO_LAMPORTS_PER_LAMPORT + 1,
83            },
84            "should round up (>1.0) lamport fee to 2 lamports"
85        );
86
87        assert_eq!(
88            FeeDetails::new(FeeType::ComputeUnitPrice(200), 100_000),
89            FeeDetails {
90                fee: 20,
91                compute_unit_price: 200,
92            },
93        );
94
95        assert_eq!(
96            FeeDetails::new(
97                FeeType::ComputeUnitPrice(MICRO_LAMPORTS_PER_LAMPORT),
98                u64::MAX
99            ),
100            FeeDetails {
101                fee: u64::MAX,
102                compute_unit_price: MICRO_LAMPORTS_PER_LAMPORT,
103            },
104        );
105
106        assert_eq!(
107            FeeDetails::new(FeeType::ComputeUnitPrice(u64::MAX), u64::MAX),
108            FeeDetails {
109                fee: u64::MAX,
110                compute_unit_price: u64::MAX,
111            },
112        );
113    }
114}