1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use anchor_lang::prelude::Rent;
use super::{Lamports, MicroLamports};
/// The expected fees for a blob upload, broken down by source.
#[derive(Debug, Copy, Clone)]
pub struct Fee {
/// The number of signatures required, summed across all transactions.
pub num_signatures: u16,
/// The price per signature, in lamports. 5000 lamports by default.
pub price_per_signature: Lamports,
/// The compute unit limit, summed across all transactions.
pub compute_unit_limit: u32,
/// The prioritization fee rate, in micro-lamports.
pub prioritization_fee_rate: MicroLamports,
/// The required size of the blober account, in bytes.
pub blob_account_size: usize,
}
impl Fee {
pub const ZERO: Fee = Fee {
num_signatures: 0,
price_per_signature: Lamports::ZERO,
compute_unit_limit: 0,
prioritization_fee_rate: MicroLamports::ZERO,
blob_account_size: 0,
};
/// Calculate the static part of the fee for a blob upload.
/// It is proportional to the number of signatures.
pub fn static_fee(&self) -> Lamports {
self.price_per_signature
.checked_mul(self.num_signatures as u32)
.expect("multiplication overflow")
}
/// Calculate the recommended prioritization fee for a blob upload at the given priority.
/// It is proportional to the compute unit limit, *not* the actual consumed compute units.
/// The value is rounded up to the nearest lamport.
pub fn prioritization_fee(&self) -> Lamports {
self.prioritization_fee_rate
.checked_mul(self.compute_unit_limit as u64)
.expect("multiplication overflow")
.try_into()
.expect("failed to convert from micro-lamports to lamports")
}
/// Calculate the total fee for a blob upload, including the static fee and the prioritization fee.
/// Does not include rent.
pub fn total_fee(&self) -> Lamports {
self.static_fee()
.checked_add(self.prioritization_fee())
.expect("addition overflow")
}
/// Calculate the required rent used as a deposit for the blober account.
/// Solana programs must hold on to a certain amount of lamports (SOL) in order to exist on-chain.
/// This rent is paid upfront whenever an account is created or resized, and is proportional to
/// the size of the account.
pub fn rent(&self) -> Lamports {
let minimum_balance = Rent::default().minimum_balance(self.blob_account_size) as u32;
Lamports::new(minimum_balance)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn less_than_one_lamport_prioritization_fee_is_ok() {
let fee = Fee {
num_signatures: 1,
price_per_signature: Lamports::new(5000),
compute_unit_limit: 1,
prioritization_fee_rate: MicroLamports::new(999_999),
blob_account_size: 100,
};
assert_eq!(fee.prioritization_fee(), Lamports::new(1));
}
}