174 lines
4.4 KiB
Plaintext
174 lines
4.4 KiB
Plaintext
pub fn safe_add(a: u256, b: u256) -> u256 {
|
|
let result = a + b;
|
|
require(result >= a, "Addition overflow");
|
|
return result;
|
|
}
|
|
|
|
pub fn safe_sub(a: u256, b: u256) -> u256 {
|
|
require(a >= b, "Subtraction underflow");
|
|
return a - b;
|
|
}
|
|
|
|
pub fn safe_mul(a: u256, b: u256) -> u256 {
|
|
if a == 0 {
|
|
return 0;
|
|
}
|
|
let result = a * b;
|
|
require(result / a == b, "Multiplication overflow");
|
|
return result;
|
|
}
|
|
|
|
pub fn safe_div(a: u256, b: u256) -> u256 {
|
|
require(b > 0, "Division by zero");
|
|
return a / b;
|
|
}
|
|
|
|
pub fn safe_mod(a: u256, b: u256) -> u256 {
|
|
require(b > 0, "Modulo by zero");
|
|
return a % b;
|
|
}
|
|
|
|
pub fn max(a: u256, b: u256) -> u256 {
|
|
return if a >= b { a } else { b };
|
|
}
|
|
|
|
pub fn min(a: u256, b: u256) -> u256 {
|
|
return if a <= b { a } else { b };
|
|
}
|
|
|
|
pub fn abs_diff(a: u256, b: u256) -> u256 {
|
|
return if a >= b { a - b } else { b - a };
|
|
}
|
|
|
|
pub fn percentage(amount: u256, basis_points: u16) -> u256 {
|
|
require(basis_points <= 10000, "Basis points must be <= 10000");
|
|
return safe_mul(amount, basis_points as u256) / 10000;
|
|
}
|
|
|
|
pub fn proportion(amount: u256, numerator: u256, denominator: u256) -> u256 {
|
|
require(denominator > 0, "Denominator cannot be zero");
|
|
return safe_mul(amount, numerator) / denominator;
|
|
}
|
|
|
|
pub fn ceil_div(a: u256, b: u256) -> u256 {
|
|
require(b > 0, "Division by zero");
|
|
if a == 0 {
|
|
return 0;
|
|
}
|
|
return (a - 1) / b + 1;
|
|
}
|
|
|
|
pub fn pow(base: u256, exponent: u256) -> u256 {
|
|
if exponent == 0 {
|
|
return 1;
|
|
}
|
|
if base == 0 {
|
|
return 0;
|
|
}
|
|
let mut result: u256 = 1;
|
|
let mut b = base;
|
|
let mut e = exponent;
|
|
while e > 0 {
|
|
if e % 2 == 1 {
|
|
result = safe_mul(result, b);
|
|
}
|
|
b = safe_mul(b, b);
|
|
e = e / 2;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
pub fn sqrt(x: u256) -> u256 {
|
|
if x == 0 {
|
|
return 0;
|
|
}
|
|
if x <= 3 {
|
|
return 1;
|
|
}
|
|
let mut z = x;
|
|
let mut y = (x + 1) / 2;
|
|
while y < z {
|
|
z = y;
|
|
y = (x / y + y) / 2;
|
|
}
|
|
return z;
|
|
}
|
|
|
|
pub fn average(a: u256, b: u256) -> u256 {
|
|
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
|
|
}
|
|
|
|
pub fn weighted_average(values: Vec<u256>, weights: Vec<u256>) -> u256 {
|
|
require(values.len() == weights.len(), "Arrays length mismatch");
|
|
require(values.len() > 0, "Arrays cannot be empty");
|
|
let mut sum: u256 = 0;
|
|
let mut weight_sum: u256 = 0;
|
|
for i in 0..values.len() {
|
|
sum = safe_add(sum, safe_mul(values[i], weights[i]));
|
|
weight_sum = safe_add(weight_sum, weights[i]);
|
|
}
|
|
require(weight_sum > 0, "Weight sum cannot be zero");
|
|
return sum / weight_sum;
|
|
}
|
|
|
|
pub fn sum(values: Vec<u256>) -> u256 {
|
|
let mut result: u256 = 0;
|
|
for value in values {
|
|
result = safe_add(result, value);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
pub fn array_max(values: Vec<u256>) -> u256 {
|
|
require(values.len() > 0, "Array cannot be empty");
|
|
let mut max_value = values[0];
|
|
for value in values {
|
|
if value > max_value {
|
|
max_value = value;
|
|
}
|
|
}
|
|
return max_value;
|
|
}
|
|
|
|
pub fn array_min(values: Vec<u256>) -> u256 {
|
|
require(values.len() > 0, "Array cannot be empty");
|
|
let mut min_value = values[0];
|
|
for value in values {
|
|
if value < min_value {
|
|
min_value = value;
|
|
}
|
|
}
|
|
return min_value;
|
|
}
|
|
|
|
pub fn compound_interest(principal: u256, rate_basis_points: u16, periods: u256) -> u256 {
|
|
require(rate_basis_points <= 10000, "Rate must be <= 100%");
|
|
if periods == 0 {
|
|
return principal;
|
|
}
|
|
let rate_factor = 10000 + (rate_basis_points as u256);
|
|
let mut result = principal;
|
|
for _ in 0..periods {
|
|
result = safe_mul(result, rate_factor) / 10000;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
pub fn simple_interest(principal: u256, rate_basis_points: u16, periods: u256) -> u256 {
|
|
require(rate_basis_points <= 10000, "Rate must be <= 100%");
|
|
let interest = safe_mul(safe_mul(principal, rate_basis_points as u256), periods) / 10000;
|
|
return safe_add(principal, interest);
|
|
}
|
|
|
|
pub fn calculate_apy(initial_value: u256, final_value: u256, days: u256) -> u16 {
|
|
require(initial_value > 0, "Initial value must be positive");
|
|
require(days > 0, "Days must be positive");
|
|
if final_value <= initial_value {
|
|
return 0;
|
|
}
|
|
let gain = final_value - initial_value;
|
|
let return_rate = safe_mul(gain, 10000) / initial_value;
|
|
let apy = safe_mul(return_rate, 365) / days;
|
|
return min(apy, 10000) as u16;
|
|
}
|