Skip to content

Commit 9dece00

Browse files
committed
simd-0194 exemption threshold
1 parent dd52b4a commit 9dece00

File tree

1 file changed

+67
-18
lines changed

1 file changed

+67
-18
lines changed

sdk/pinocchio/src/sysvars/rent.rs

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ pub const RENT_ID: Pubkey = [
2525
/// - `$3.65` per megabyte year
2626
pub const DEFAULT_LAMPORTS_PER_BYTE_YEAR: u64 = 1_000_000_000 / 100 * 365 / (1024 * 1024);
2727

28+
/// SIMD-0194
29+
///
30+
/// This equates to the integer value of 3480. To account for 2 years of rent
31+
/// exemption, we multiply this value by 2 to make it 6960.
32+
pub const DEFAULT_LAMPORTS_PER_BYTE: u64 = 6960;
33+
2834
/// Default amount of time (in years) the balance has to include rent for the
2935
/// account to be rent exempt.
3036
pub const DEFAULT_EXEMPTION_THRESHOLD: f64 = 2.0;
@@ -38,6 +44,13 @@ const DEFAULT_EXEMPTION_THRESHOLD_AS_U64: u64 = 2;
3844
/// This is used to check whether the `f64` value can be safely cast to a `u64`.
3945
const F64_EXEMPTION_THRESHOLD_AS_U64: u64 = 4611686018427387904;
4046

47+
/// The `u64` representation of the deprecated exemption threshold.
48+
///
49+
/// This value is equivalent to `1f64`. It is only used to check whether
50+
/// the exmption threshold is the deprecated value to avoid performing
51+
/// floating-point operations on-chain.
52+
const F64_SIMD0194_EXEMPTION_THRESHOLD_AS_U64: u64 = 4607182418800017408;
53+
4154
/// Default percentage of collected rent that is burned.
4255
///
4356
/// Valid values are in the range [0, 100]. The remaining percentage is
@@ -55,9 +68,18 @@ pub const ACCOUNT_STORAGE_OVERHEAD: u64 = 128;
5568
#[derive(Clone, Copy, Debug)]
5669
pub struct Rent {
5770
/// Rental rate in lamports per byte-year
71+
#[deprecated(
72+
since = "0.9.2",
73+
note = "SIMD-0194 will rename this field to `lamports_per_byte`"
74+
)]
5875
pub lamports_per_byte_year: u64,
5976

60-
/// Exemption threshold in years
77+
/// Exemption threshold in years.
78+
///
79+
/// SIMD-0194 will deprecate this value. The current implementation checks
80+
/// the value against known defaults to avoid performing a floating-point
81+
/// operation on-chain.
82+
#[deprecated(since = "0.9.2", note = "SIMD-0194 will deprecate this value")]
6183
pub exemption_threshold: f64,
6284

6385
/// Burn percentage
@@ -149,6 +171,7 @@ impl Rent {
149171

150172
/// Rent due for account that is known to be not exempt.
151173
#[inline]
174+
#[allow(deprecated)]
152175
pub fn due_amount(&self, data_len: usize, years_elapsed: f64) -> u64 {
153176
let actual_data_len = data_len as u64 + ACCOUNT_STORAGE_OVERHEAD;
154177
let lamports_per_year = self.lamports_per_byte_year * actual_data_len;
@@ -168,15 +191,23 @@ impl Rent {
168191
///
169192
/// The minimum balance in lamports for rent exemption.
170193
#[inline]
194+
#[allow(deprecated)]
171195
pub fn minimum_balance(&self, data_len: usize) -> u64 {
172196
let bytes = data_len as u64;
173-
174-
if self.is_default_rent_threshold() {
175-
((ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year)
176-
* DEFAULT_EXEMPTION_THRESHOLD_AS_U64
177-
} else {
178-
(((ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year) as f64
179-
* self.exemption_threshold) as u64
197+
let exemption_threshold_as_u64 = u64::from_le_bytes(self.exemption_threshold.to_le_bytes());
198+
199+
match exemption_threshold_as_u64 {
200+
F64_SIMD0194_EXEMPTION_THRESHOLD_AS_U64 => {
201+
(ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year
202+
}
203+
F64_EXEMPTION_THRESHOLD_AS_U64 => {
204+
((ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year)
205+
* DEFAULT_EXEMPTION_THRESHOLD_AS_U64
206+
}
207+
_ => {
208+
(((ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year) as f64
209+
* self.exemption_threshold) as u64
210+
}
180211
}
181212
}
182213

@@ -194,15 +225,6 @@ impl Rent {
194225
pub fn is_exempt(&self, lamports: u64, data_len: usize) -> bool {
195226
lamports >= self.minimum_balance(data_len)
196227
}
197-
198-
/// Determines if the `exemption_threshold` is the default value.
199-
///
200-
/// This is used to check whether the `f64` value can be safely cast to a `u64`
201-
/// to avoid floating-point operations.
202-
#[inline]
203-
fn is_default_rent_threshold(&self) -> bool {
204-
u64::from_le_bytes(self.exemption_threshold.to_le_bytes()) == F64_EXEMPTION_THRESHOLD_AS_U64
205-
}
206228
}
207229

208230
impl Sysvar for Rent {
@@ -237,10 +259,11 @@ impl RentDue {
237259
}
238260

239261
#[cfg(test)]
262+
#[allow(deprecated)]
240263
mod tests {
241264
use crate::sysvars::rent::{
242265
ACCOUNT_STORAGE_OVERHEAD, DEFAULT_BURN_PERCENT, DEFAULT_EXEMPTION_THRESHOLD,
243-
DEFAULT_LAMPORTS_PER_BYTE_YEAR,
266+
DEFAULT_LAMPORTS_PER_BYTE, DEFAULT_LAMPORTS_PER_BYTE_YEAR,
244267
};
245268

246269
#[test]
@@ -270,4 +293,30 @@ mod tests {
270293
assert!(calculated > 0);
271294
assert_eq!(balance, calculated);
272295
}
296+
297+
#[test]
298+
pub fn test_minimum_balance_simd0194() {
299+
let mut rent = super::Rent {
300+
lamports_per_byte_year: DEFAULT_LAMPORTS_PER_BYTE,
301+
exemption_threshold: 1.0, // SIMD-0194 default
302+
burn_percent: DEFAULT_BURN_PERCENT,
303+
};
304+
305+
// Using the default exemption threshold.
306+
307+
let balance = rent.minimum_balance(100);
308+
let calculated = (ACCOUNT_STORAGE_OVERHEAD + 100) * rent.lamports_per_byte_year;
309+
310+
assert!(calculated > 0);
311+
assert_eq!(balance, calculated);
312+
313+
// Using a different lamports per byte value.
314+
rent.lamports_per_byte_year = DEFAULT_LAMPORTS_PER_BYTE * 2;
315+
316+
let balance = rent.minimum_balance(100);
317+
let calculated = (ACCOUNT_STORAGE_OVERHEAD + 100) * rent.lamports_per_byte_year;
318+
319+
assert!(calculated > 0);
320+
assert_eq!(balance, calculated);
321+
}
273322
}

0 commit comments

Comments
 (0)