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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
//! configuration for network rent #[derive(Serialize, Deserialize, PartialEq, Clone, Copy, Debug)] pub struct Rent { /// Rental rate pub lamports_per_byte_year: u64, /// exemption threshold, in years pub exemption_threshold: f64, // What portion of collected rent are to be destroyed, percentage-wise pub burn_percent: u8, } /// default rental rate in lamports/byte-year, based on: /// 2^^34 lamports per Sol /// $1 per Sol /// $0.01 per megabyte day /// $3.65 per megabyte year pub const DEFAULT_LAMPORTS_PER_BYTE_YEAR: u64 = 0; //17_179_869_184 / 100 * 365 / (1024 * 1024); /// default amount of time (in years) the balance has to include rent for pub const DEFAULT_EXEMPTION_THRESHOLD: f64 = 2.0; /// default amount of rent to burn, as a fraction of std::u8::MAX pub const DEFAULT_BURN_PERCENT: u8 = ((50usize * std::u8::MAX as usize) / 100usize) as u8; impl Default for Rent { fn default() -> Self { Self { lamports_per_byte_year: DEFAULT_LAMPORTS_PER_BYTE_YEAR, exemption_threshold: DEFAULT_EXEMPTION_THRESHOLD, burn_percent: DEFAULT_BURN_PERCENT, } } } impl Rent { /// minimum balance due for a given size Account::data.len() pub fn minimum_balance(&self, data_len: usize) -> u64 { let bytes = data_len as u64; bytes * (self.exemption_threshold * self.lamports_per_byte_year as f64) as u64 } /// whether a given balance and data_len would be exempt pub fn is_exempt(&self, balance: u64, data_len: usize) -> bool { balance >= self.minimum_balance(data_len) } /// rent due on account's data_len with balance pub fn due(&self, balance: u64, data_len: usize, years_elapsed: f64) -> (u64, bool) { if self.is_exempt(balance, data_len) { (0, true) } else { ( ((self.lamports_per_byte_year * data_len as u64) as f64 * years_elapsed) as u64, false, ) } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_due() { let rent = Rent::default(); assert_eq!( rent.due(0, 1, 1.0), ( DEFAULT_LAMPORTS_PER_BYTE_YEAR, DEFAULT_LAMPORTS_PER_BYTE_YEAR == 0 ) ); assert_eq!( rent.due( DEFAULT_LAMPORTS_PER_BYTE_YEAR * DEFAULT_EXEMPTION_THRESHOLD as u64, 1, 1.0 ), (0, true) ); } // uncomment me and make my eprintlns macros // #[test] // fn test_rent_model() { // use crate::timing::*; // // const SECONDS_PER_YEAR: f64 = (365.25 * 24.0 * 60.0 * 60.0); // const SLOTS_PER_YEAR: f64 = // SECONDS_PER_YEAR / (DEFAULT_TICKS_PER_SLOT as f64 / DEFAULT_TICKS_PER_SECOND as f64); // // let rent = Rent::default(); // // eprintln(); // // lamports charged per byte per slot at $1/MByear, rent per slot is zero // eprintln( // "{} lamports per byte-slot, rent.due(): {}", // (1.0 / SLOTS_PER_YEAR) * DEFAULT_LAMPORTS_PER_BYTE_YEAR as f64, // rent.due(0, 1, 1.0 / SLOTS_PER_YEAR).0, // ); // // lamports charged per byte per _epoch_ starts to have some significant digits // eprintln( // "{} lamports per byte-epoch, rent.due(): {}", // (1.0 / SLOTS_PER_YEAR) // * (DEFAULT_LAMPORTS_PER_BYTE_YEAR * DEFAULT_SLOTS_PER_EPOCH) as f64, // rent.due( // 0, // 1, // (1.0 / SLOTS_PER_YEAR) * DEFAULT_SLOTS_PER_EPOCH as f64 // ) // .0, // ); // // have a look at what a large-ish sysvar would cost, were it a real account... // eprintln( // "stake_history: {}kB == {} lamports per epoch", // crate::sysvar::stake_history::StakeHistory::size_of() / 1024, // rent.due( // 0, // crate::sysvar::stake_history::StakeHistory::size_of(), // (1.0 / SLOTS_PER_YEAR) * DEFAULT_SLOTS_PER_EPOCH as f64 // ) // .0, // ); // } }