94 lines
2.5 KiB
Rust
94 lines
2.5 KiB
Rust
//! State types
|
|
|
|
mod lending_market;
|
|
mod obligation;
|
|
mod reserve;
|
|
|
|
pub use lending_market::*;
|
|
pub use obligation::*;
|
|
pub use reserve::*;
|
|
|
|
use crate::math::{Decimal, WAD};
|
|
use arrayref::{array_refs, mut_array_refs};
|
|
use solana_program::{
|
|
clock::{DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT, SECONDS_PER_DAY},
|
|
program_error::ProgramError,
|
|
program_option::COption,
|
|
pubkey::Pubkey,
|
|
};
|
|
|
|
/// Collateral tokens are initially valued at a ratio of 5:1 (collateral:liquidity)
|
|
pub const INITIAL_COLLATERAL_RATIO: u64 = 5;
|
|
const INITIAL_COLLATERAL_RATE: u64 = INITIAL_COLLATERAL_RATIO * WAD;
|
|
|
|
/// Current version of the program and all new accounts created
|
|
pub const PROGRAM_VERSION: u8 = 1;
|
|
|
|
/// Accounts are created with data zeroed out, so uninitialized state instances
|
|
/// will have the version set to 0.
|
|
pub const UNINITIALIZED_VERSION: u8 = 0;
|
|
|
|
/// Number of slots per year
|
|
pub const SLOTS_PER_YEAR: u64 =
|
|
DEFAULT_TICKS_PER_SECOND / DEFAULT_TICKS_PER_SLOT * SECONDS_PER_DAY * 365;
|
|
|
|
/// Token converter
|
|
pub trait TokenConverter {
|
|
/// Return best price for specified token
|
|
fn best_price(&mut self, token_mint: &Pubkey) -> Result<Decimal, ProgramError>;
|
|
|
|
/// Convert between two different tokens
|
|
fn convert(
|
|
self,
|
|
from_amount: Decimal,
|
|
from_token_mint: &Pubkey,
|
|
) -> Result<Decimal, ProgramError>;
|
|
}
|
|
|
|
// Helpers
|
|
fn pack_coption_key(src: &COption<Pubkey>, dst: &mut [u8; 36]) {
|
|
let (tag, body) = mut_array_refs![dst, 4, 32];
|
|
match src {
|
|
COption::Some(key) => {
|
|
*tag = [1, 0, 0, 0];
|
|
body.copy_from_slice(key.as_ref());
|
|
}
|
|
COption::None => {
|
|
*tag = [0; 4];
|
|
}
|
|
}
|
|
}
|
|
|
|
fn unpack_coption_key(src: &[u8; 36]) -> Result<COption<Pubkey>, ProgramError> {
|
|
let (tag, body) = array_refs![src, 4, 32];
|
|
match *tag {
|
|
[0, 0, 0, 0] => Ok(COption::None),
|
|
[1, 0, 0, 0] => Ok(COption::Some(Pubkey::new_from_array(*body))),
|
|
_ => Err(ProgramError::InvalidAccountData),
|
|
}
|
|
}
|
|
|
|
fn pack_decimal(decimal: Decimal, dst: &mut [u8; 16]) {
|
|
*dst = decimal
|
|
.to_scaled_val()
|
|
.expect("could not pack decimal")
|
|
.to_le_bytes();
|
|
}
|
|
|
|
fn unpack_decimal(src: &[u8; 16]) -> Decimal {
|
|
Decimal::from_scaled_val(u128::from_le_bytes(*src))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn initial_collateral_rate_sanity() {
|
|
assert_eq!(
|
|
INITIAL_COLLATERAL_RATIO.checked_mul(WAD).unwrap(),
|
|
INITIAL_COLLATERAL_RATE
|
|
);
|
|
}
|
|
}
|