From b62021e1689e2116649f7c4306e424b7463d6319 Mon Sep 17 00:00:00 2001 From: Kevin Rodriguez <_@kevinrodriguez.io> Date: Thu, 5 Sep 2024 12:29:45 -0600 Subject: [PATCH] feat: adds more docs --- CHANGELOG.md | 12 +++ Cargo.lock | 18 ----- crates/magic-curves/Cargo.toml | 1 - crates/magic-curves/src/core/exponential.rs | 60 +++++++++++++++ crates/magic-curves/src/core/linear.rs | 84 +++++++++++++++++++++ crates/magic-curves/src/core/logarithmic.rs | 79 +++++++++++++++---- crates/magic-curves/src/core/quadratic.rs | 80 ++++++++++++++++++++ crates/magic-curves/src/core/sigmoid.rs | 63 +++++++++++++--- crates/magic-curves/src/core/tools.rs | 44 +++++++++++ crates/magic-curves/src/core/types.rs | 76 +++++++++++++++++++ 10 files changed, 476 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2b7ada..26ca619 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,18 @@ Note: Version 0 of Semantic Versioning is handled differently from version 1 and ### Breaking +## [1.0.0] - 2024-09-05 + +### Features + +- Added `calculate_price_many` and `calculate_price_many_checked` to all bonding curves. + +### Fixes + +### Breaking + +- Removed "lossy" suffix on `f64` curves: Exponential, Logarithmic, and Sigmoid. + ## [0.1.0] - 2024-08-21 ### Features diff --git a/Cargo.lock b/Cargo.lock index e00ca3a..8313254 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,24 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - [[package]] name = "magic-curves" version = "0.1.0" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] diff --git a/crates/magic-curves/Cargo.toml b/crates/magic-curves/Cargo.toml index 8f463b7..57116f9 100644 --- a/crates/magic-curves/Cargo.toml +++ b/crates/magic-curves/Cargo.toml @@ -13,4 +13,3 @@ keywords = ["blockchain", "financial", "solana", "defi", "finance"] categories = ["finance", "cryptography"] [dependencies] -num-traits = "^0.2.19" diff --git a/crates/magic-curves/src/core/exponential.rs b/crates/magic-curves/src/core/exponential.rs index 40b3362..f9dae73 100644 --- a/crates/magic-curves/src/core/exponential.rs +++ b/crates/magic-curves/src/core/exponential.rs @@ -2,6 +2,14 @@ use std::f64::consts::E; use super::{BondingCurve, OperationSide}; +/// Represents an exponential bonding curve. +/// +/// This struct defines an exponential bonding curve with a base price and a growth rate. +/// +/// # Fields +/// +/// * `base`: The base price, which is the initial price for the first token. +/// * `growth`: The growth rate that determines how quickly the price increases. #[derive(Copy, Clone, Debug, PartialEq)] pub struct ExponentialBondingCurve { pub base: f64, @@ -9,15 +17,67 @@ pub struct ExponentialBondingCurve { } impl ExponentialBondingCurve { + /// Creates a new `ExponentialBondingCurve` with the specified base price and growth rate. + /// + /// # Arguments + /// + /// * `base` - The base price, which is the initial price for the first token. + /// * `growth` - The growth rate that determines how quickly the price increases. + /// + /// # Returns + /// + /// A new instance of `ExponentialBondingCurve`. + /// + /// # Example + /// + /// ``` + /// use magic_curves::ExponentialBondingCurve; + /// + /// let curve = ExponentialBondingCurve::new(0.01, 0.02); + /// ``` pub fn new(base: f64, growth: f64) -> Self { Self { base, growth } } } impl BondingCurve for ExponentialBondingCurve { + /// Calculates the price based on the supply. + /// + /// # Formula + /// + /// ```ignore + /// f(x) = base * e^(growth * x) + /// ``` + /// + /// # Arguments + /// + /// * `supply` - The current supply of tokens. + /// + /// # Returns + /// + /// The price of the token based on the supply. fn calculate_price(&self, supply: u64) -> f64 { self.base * E.powf(self.growth * supply as f64) } + + /// Calculates the price for a given amount of tokens. + /// + /// # Formula + /// + /// The integral of the exponential function is used: + /// ```ignore + /// F(x) = (base / growth) * (e^(growth * x) - e^(growth * start)) + /// ``` + /// + /// # Arguments + /// + /// * `starting_supply` - The current supply of tokens. + /// * `amount` - The amount of tokens to calculate the price for. + /// * `side` - The side of the operation (add or remove). + /// + /// # Returns + /// + /// The total price for the given amount of tokens. fn calculate_price_many(&self, starting_supply: u64, amount: u64, side: OperationSide) -> f64 { let start = starting_supply as f64; let end = match side { diff --git a/crates/magic-curves/src/core/linear.rs b/crates/magic-curves/src/core/linear.rs index 8db4fdc..3564942 100644 --- a/crates/magic-curves/src/core/linear.rs +++ b/crates/magic-curves/src/core/linear.rs @@ -1,5 +1,13 @@ use super::{BondingCurve, BondingCurveError, BondingCurveWithCheckedOperations, OperationSide}; +/// Represents a linear bonding curve. +/// +/// This struct defines a linear bonding curve with a linear coefficient and a base price. +/// +/// # Fields +/// +/// * `linear`: The linear coefficient that determines the rate of price increase. +/// * `base`: The base price, which is the minimum price for the first token. #[derive(Copy, Clone, Debug, PartialEq)] pub struct LinearBondingCurve { pub linear: u64, @@ -7,15 +15,71 @@ pub struct LinearBondingCurve { } impl LinearBondingCurve { + /// Creates a new `LinearBondingCurve` with the specified linear coefficient and base price. + /// + /// # Arguments + /// + /// * `linear` - The linear coefficient that determines the rate of price increase. + /// * `base` - The base price, which is the minimum price for the first token. + /// + /// # Returns + /// + /// A new instance of `LinearBondingCurve`. + /// + /// # Example + /// + /// ``` + /// use magic_curves::LinearBondingCurve; + /// + /// let curve = LinearBondingCurve::new(100, 1000); + /// ``` pub fn new(linear: u64, base: u64) -> Self { Self { linear, base } } } impl BondingCurve for LinearBondingCurve { + /// Calculates the price based on the supply. + /// + /// # Formula + /// + /// ```ignore + /// f(x) = linear * x + base + /// ``` + /// + /// # Arguments + /// + /// * `supply` - The current supply of tokens. + /// + /// # Returns + /// + /// The price of the token based on the supply. fn calculate_price(&self, supply: u64) -> u64 { self.linear * supply + self.base } + + /// Calculates the price for a given amount of tokens. + /// + /// # Formula + /// + /// ```ignore + /// f(x) = (amount * (a1 + an)) / 2 + /// ``` + /// + /// where: + /// + /// - a1 = linear * starting_supply + base + /// - an = linear * (starting_supply + amount - 1) + base + /// + /// # Arguments + /// + /// * `starting_supply` - The current supply of tokens. + /// * `amount` - The amount of tokens to calculate the price for. + /// * `side` - The side of the operation (add or remove). + /// + /// # Returns + /// + /// The total price for the given amount of tokens. fn calculate_price_many(&self, starting_supply: u64, amount: u64, side: OperationSide) -> u64 { let a1 = self.linear * starting_supply + self.base; let an = match side { @@ -27,6 +91,15 @@ impl BondingCurve for LinearBondingCurve { } impl BondingCurveWithCheckedOperations for LinearBondingCurve { + /// Calculates the price based on the supply. + /// + /// # Arguments + /// + /// * `supply` - The current supply of tokens. + /// + /// # Returns + /// + /// The price of the token based on the supply. If the operation would cause an overflow, it returns an error. fn calculate_price_checked(&self, supply: u64) -> Result { let result = self .linear @@ -36,6 +109,17 @@ impl BondingCurveWithCheckedOperations for LinearBondingCurve { result.ok_or(BondingCurveError::Overflow) } + /// Calculates the price for a given amount of tokens. + /// + /// # Arguments + /// + /// * `starting_supply` - The current supply of tokens. + /// * `amount` - The amount of tokens to calculate the price for. + /// * `side` - The side of the operation (add or remove). + /// + /// # Returns + /// + /// The total price for the given amount of tokens. If the operation would cause an overflow, it returns an error. fn calculate_price_many_checked( &self, starting_supply: u64, diff --git a/crates/magic-curves/src/core/logarithmic.rs b/crates/magic-curves/src/core/logarithmic.rs index 779e2a2..8bf59d0 100644 --- a/crates/magic-curves/src/core/logarithmic.rs +++ b/crates/magic-curves/src/core/logarithmic.rs @@ -1,5 +1,13 @@ -use super::BondingCurve; +use super::{BondingCurve, OperationSide}; +/// Represents a logarithmic bonding curve. +/// +/// This struct defines a logarithmic bonding curve with a base price and a growth rate. +/// +/// # Fields +/// +/// * `base`: The base price, which is the initial price for the first token. +/// * `growth`: The growth rate that determines how quickly the price increases. #[derive(Copy, Clone, Debug, PartialEq)] pub struct LogarithmicBondingCurve { pub base: f64, @@ -7,12 +15,45 @@ pub struct LogarithmicBondingCurve { } impl LogarithmicBondingCurve { + /// Creates a new `LogarithmicBondingCurve` with the specified base price and growth rate. + /// + /// # Arguments + /// + /// * `base` - The base price, which is the initial price for the first token. + /// * `growth` - The growth rate that determines how quickly the price increases. + /// + /// # Returns + /// + /// A new instance of `LogarithmicBondingCurve`. + /// + /// # Example + /// + /// ``` + /// use magic_curves::LogarithmicBondingCurve; + /// + /// let curve = LogarithmicBondingCurve::new(0.02, 0.01); + /// ``` pub fn new(base: f64, growth: f64) -> Self { Self { base, growth } } } impl BondingCurve for LogarithmicBondingCurve { + /// Calculates the price based on the supply. + /// + /// # Formula + /// + /// ```ignore + /// f(x) = growth * ln(x) + base + /// ``` + /// + /// # Arguments + /// + /// * `supply` - The current supply of tokens. + /// + /// # Returns + /// + /// The price of the token based on the supply. fn calculate_price(&self, supply: u64) -> f64 { if supply == 0 { return self.base; // Avoid taking the log of 0 @@ -20,30 +61,42 @@ impl BondingCurve for LogarithmicBondingCurve { self.growth * (supply as f64).ln() + self.base } - fn calculate_price_many( - &self, - starting_supply: u64, - amount: u64, - side: super::OperationSide, - ) -> f64 { + /// Calculates the price for a given amount of tokens. + /// + /// # Formula + /// + /// The integral of the logarithmic function is used: + /// ```ignore + /// F(x) = growth * x * ln(x) - growth * x + base * x + /// ``` + /// + /// # Arguments + /// + /// * `starting_supply` - The current supply of tokens. + /// * `amount` - The amount of tokens to calculate the price for. + /// * `side` - The side of the operation (add or remove). + /// + /// # Returns + /// + /// The total price for the given amount of tokens. + fn calculate_price_many(&self, starting_supply: u64, amount: u64, side: OperationSide) -> f64 { let start = starting_supply as f64; let end = match side { - super::OperationSide::Add => (starting_supply + amount) as f64, - super::OperationSide::Remove => (starting_supply - amount) as f64, + OperationSide::Add => (starting_supply + amount) as f64, + OperationSide::Remove => (starting_supply - amount) as f64, }; // Calculate the integral of the logarithmic function - // The integral of (a * ln(x) + b) is (a * x * ln(x) - a * x + b * x) let integral = |x: f64| self.growth * x * x.ln() - self.growth * x + self.base * x; // Calculate the difference between the integrals at the end and start points let price = match side { - super::OperationSide::Add => integral(end) - integral(start), - super::OperationSide::Remove => integral(start) - integral(end), + OperationSide::Add => integral(end) - integral(start), + OperationSide::Remove => integral(start) - integral(end), }; // Handle the case where starting_supply is 0 for Add operation - if starting_supply == 0 && side == super::OperationSide::Add { + if starting_supply == 0 && side == OperationSide::Add { price + self.base // Add base price for the first token } else { price diff --git a/crates/magic-curves/src/core/quadratic.rs b/crates/magic-curves/src/core/quadratic.rs index fa08836..e254e67 100644 --- a/crates/magic-curves/src/core/quadratic.rs +++ b/crates/magic-curves/src/core/quadratic.rs @@ -1,5 +1,14 @@ use super::{BondingCurve, BondingCurveError, BondingCurveWithCheckedOperations, OperationSide}; +/// Represents a quadratic bonding curve. +/// +/// This struct defines a quadratic bonding curve with quadratic, linear, and base coefficients. +/// +/// # Fields +/// +/// * `quadratic`: The quadratic coefficient that determines the rate of price increase. +/// * `linear`: The linear coefficient that affects the price linearly. +/// * `base`: The base price, which is the minimum price for the first token. #[derive(Copy, Clone, Debug, PartialEq)] pub struct QuadraticBondingCurve { pub quadratic: u64, @@ -8,6 +17,25 @@ pub struct QuadraticBondingCurve { } impl QuadraticBondingCurve { + /// Creates a new `QuadraticBondingCurve` with the specified coefficients. + /// + /// # Arguments + /// + /// * `quadratic` - The quadratic coefficient that determines the rate of price increase. + /// * `linear` - The linear coefficient that affects the price linearly. + /// * `base` - The base price, which is the minimum price for the first token. + /// + /// # Returns + /// + /// A new instance of `QuadraticBondingCurve`. + /// + /// # Example + /// + /// ``` + /// use magic_curves::QuadraticBondingCurve; + /// + /// let curve = QuadraticBondingCurve::new(10, 100, 1000); + /// ``` pub fn new(quadratic: u64, linear: u64, base: u64) -> Self { Self { quadratic, @@ -18,10 +46,40 @@ impl QuadraticBondingCurve { } impl BondingCurve for QuadraticBondingCurve { + /// Calculates the price based on the supply. + /// + /// # Formula + /// + /// ```ignore + /// f(x) = quadratic * x^2 + linear * x + base + /// ``` + /// + /// # Arguments + /// + /// * `supply` - The current supply of tokens. + /// + /// # Returns + /// + /// The price of the token based on the supply. fn calculate_price(&self, supply: u64) -> u64 { self.quadratic * supply * supply + self.linear * supply + self.base } + /// Calculates the price for a given amount of tokens. + /// + /// # Formula + /// + /// The formula uses the sum of quadratic, linear, and constant terms based on the operation side. + /// + /// # Arguments + /// + /// * `starting_supply` - The current supply of tokens. + /// * `amount` - The amount of tokens to calculate the price for. + /// * `side` - The side of the operation (add or remove). + /// + /// # Returns + /// + /// The total price for the given amount of tokens. fn calculate_price_many(&self, starting_supply: u64, amount: u64, side: OperationSide) -> u64 { let n = amount; let a = starting_supply; @@ -59,6 +117,16 @@ impl BondingCurve for QuadraticBondingCurve { } impl BondingCurveWithCheckedOperations for QuadraticBondingCurve { + /// Calculates the price based on the supply with overflow checking. + /// + /// # Arguments + /// + /// * `supply` - The current supply of tokens. + /// + /// # Returns + /// + /// A `Result` containing the price of the token based on the supply, + /// or a `BondingCurveError` if the calculation overflows. fn calculate_price_checked(&self, supply: u64) -> Result { let result = self .quadratic @@ -69,6 +137,18 @@ impl BondingCurveWithCheckedOperations for QuadraticBondingCurve { result.ok_or(BondingCurveError::Overflow) } + /// Calculates the price for a given amount of tokens with overflow checking. + /// + /// # Arguments + /// + /// * `starting_supply` - The current supply of tokens. + /// * `amount` - The amount of tokens to calculate the price for. + /// * `side` - The side of the operation (add or remove). + /// + /// # Returns + /// + /// A `Result` containing the total price for the given amount of tokens, + /// or a `BondingCurveError` if the calculation overflows. fn calculate_price_many_checked( &self, starting_supply: u64, diff --git a/crates/magic-curves/src/core/sigmoid.rs b/crates/magic-curves/src/core/sigmoid.rs index 24c68ce..37e0eaf 100644 --- a/crates/magic-curves/src/core/sigmoid.rs +++ b/crates/magic-curves/src/core/sigmoid.rs @@ -1,5 +1,14 @@ use super::{BondingCurve, OperationSide}; +/// Represents a sigmoid bonding curve. +/// +/// This struct defines a sigmoid bonding curve with a maximum price, growth rate, and mid-supply point. +/// +/// # Fields +/// +/// * `max_price`: The maximum price that the curve approaches asymptotically. +/// * `growth`: The growth rate that determines how quickly the price increases. +/// * `mid_supply`: The supply at which the price is half of the maximum price. #[derive(Copy, Clone, Debug, PartialEq)] pub struct SigmoidBondingCurve { pub max_price: f64, @@ -8,6 +17,25 @@ pub struct SigmoidBondingCurve { } impl SigmoidBondingCurve { + /// Creates a new `SigmoidBondingCurve` with the specified maximum price, growth rate, and mid-supply point. + /// + /// # Arguments + /// + /// * `max_price` - The maximum price that the curve approaches asymptotically. + /// * `growth` - The growth rate that determines how quickly the price increases. + /// * `mid_supply` - The supply at which the price is half of the maximum price. + /// + /// # Returns + /// + /// A new instance of `SigmoidBondingCurve`. + /// + /// # Example + /// + /// ``` + /// use magic_curves::SigmoidBondingCurve; + /// + /// let curve = SigmoidBondingCurve::new(100.0, 0.01, 500); + /// ``` pub fn new(max_price: f64, growth: f64, mid_supply: u64) -> Self { Self { max_price, @@ -20,25 +48,42 @@ impl SigmoidBondingCurve { impl BondingCurve for SigmoidBondingCurve { /// Calculates the price based on the supply. /// - /// # Formula: + /// # Formula /// /// ```ignore - /// f(x) = L - /// ------ - /// 1+e^(-k[x-x0]) + /// f(x) = max_price / (1 + e^(-growth * (x - mid_supply))) /// ``` /// - /// where: + /// # Arguments + /// + /// * `supply` - The current supply of tokens. /// - /// - x is the supply. - /// - L is the maximum price (upper asymptote of the curve). - /// - k is the growth factor. - /// - x0 is the inflection point. (Can be: Max supply / 2) + /// # Returns + /// + /// The price of the token based on the supply. fn calculate_price(&self, supply: u64) -> f64 { let s = supply as f64; self.max_price / (1.0 + (-self.growth * (s - self.mid_supply as f64)).exp()) } + /// Calculates the price for a given amount of tokens. + /// + /// # Formula + /// + /// The integral of the sigmoid function is used: + /// ```ignore + /// F(x) = (max_price / growth) * ln(1 + e^(growth * (x - mid_supply))) + /// ``` + /// + /// # Arguments + /// + /// * `starting_supply` - The current supply of tokens. + /// * `amount` - The amount of tokens to calculate the price for. + /// * `side` - The side of the operation (add or remove). + /// + /// # Returns + /// + /// The total price for the given amount of tokens. fn calculate_price_many(&self, starting_supply: u64, amount: u64, side: OperationSide) -> f64 { let s = starting_supply as f64; let n = amount as f64; diff --git a/crates/magic-curves/src/core/tools.rs b/crates/magic-curves/src/core/tools.rs index b7befd1..196463a 100644 --- a/crates/magic-curves/src/core/tools.rs +++ b/crates/magic-curves/src/core/tools.rs @@ -1,9 +1,53 @@ +/// Converts a floating-point number to a fixed-point representation. +/// +/// This function takes a floating-point value and converts it to a fixed-point +/// representation with the specified number of decimal places. +/// +/// # Arguments +/// +/// * `value` - The floating-point value to convert. +/// * `decimals` - The number of decimal places to use in the fixed-point representation. +/// +/// # Returns +/// +/// A `u64` representing the fixed-point value. +/// +/// # Examples +/// +/// ``` +/// use magic_curves::float_to_fixed_point; +/// +/// let fixed = float_to_fixed_point(3.14159, 2); +/// assert_eq!(fixed, 314); +/// ``` pub fn float_to_fixed_point(value: f64, decimals: u8) -> u64 { let scale = 10u64.pow(decimals as u32); let scaled_value = value * scale as f64; scaled_value as u64 } +/// Converts a fixed-point number to a floating-point representation. +/// +/// This function takes a fixed-point value and converts it to a floating-point +/// representation with the specified number of decimal places. +/// +/// # Arguments +/// +/// * `value` - The fixed-point value to convert. +/// * `decimals` - The number of decimal places used in the fixed-point representation. +/// +/// # Returns +/// +/// A `f64` representing the floating-point value. +/// +/// # Examples +/// +/// ``` +/// use magic_curves::fixed_point_to_float; +/// +/// let floating = fixed_point_to_float(314, 2); +/// assert_eq!(floating, 3.14); +/// ``` pub fn fixed_point_to_float(value: u64, decimals: u8) -> f64 { value as f64 / 10u64.pow(decimals as u32) as f64 } diff --git a/crates/magic-curves/src/core/types.rs b/crates/magic-curves/src/core/types.rs index 5d14669..14051c0 100644 --- a/crates/magic-curves/src/core/types.rs +++ b/crates/magic-curves/src/core/types.rs @@ -15,13 +15,89 @@ pub enum OperationSide { Remove, } +/// Represents a bonding curve for token pricing. +/// +/// This trait defines the interface for a bonding curve, which is used to calculate +/// token prices based on the current supply and other parameters. +/// +/// # Type Parameters +/// +/// * `T` - The type used to represent prices. Currently a numeric type like `u64` or `f64`. +/// +/// The bonding curves that are implemented using `u64` use exact formulas with no +/// floating point precission loss. Currently, this crate provides two of them: +/// +/// * `LinearBondingCurve` - A linear bonding curve. +/// * `ExponentialBondingCurve` - An exponential bonding curve. +/// +/// The bonding curves that are implemented using `f64` use floating point numbers +/// for the calculations, which means that there is a risk of precision loss. +/// Currently, this crate provides one of them: +/// +/// * `ExponentialBondingCurve` - An exponential bonding curve. +/// * `LogarithmicBondingCurve` - A logarithmic bonding curve. +/// * `SigmoidBondingCurve` - A sigmoid bonding curve. pub trait BondingCurve { + /// Calculates the price for a single token at the given supply. + /// + /// # Arguments + /// + /// * `supply` - The current total supply of tokens. + /// + /// # Returns + /// + /// The price of a single token at the given supply. fn calculate_price(&self, supply: u64) -> T; + + /// Calculates the total price for a given amount of tokens starting from a specific supply. + /// + /// # Arguments + /// + /// * `starting_supply` - The initial supply before the operation. + /// * `amount` - The number of tokens to add or remove. + /// * `side` - Specifies whether tokens are being added or removed. + /// + /// # Returns + /// + /// The total price for the specified amount of tokens. fn calculate_price_many(&self, starting_supply: u64, amount: u64, side: OperationSide) -> T; } +/// Represents a bonding curve with checked operations for token pricing. +/// +/// This trait extends the `BondingCurve` trait by providing methods that return +/// `Result` types, allowing for error handling in case of overflow or other +/// computational issues. +/// +/// # Type Parameters +/// +/// * `T` - The type used to represent prices. Typically a numeric type like `u64` or `f64`. pub trait BondingCurveWithCheckedOperations { + /// Calculates the price for a single token at the given supply, with error checking. + /// + /// # Arguments + /// + /// * `supply` - The current total supply of tokens. + /// + /// # Returns + /// + /// A `Result` containing the price of a single token at the given supply, + /// or a `BondingCurveError` if the calculation fails. fn calculate_price_checked(&self, supply: u64) -> Result; + + /// Calculates the total price for a given amount of tokens starting from a specific supply, + /// with error checking. + /// + /// # Arguments + /// + /// * `starting_supply` - The initial supply before the operation. + /// * `amount` - The number of tokens to add or remove. + /// * `side` - Specifies whether tokens are being added or removed. + /// + /// # Returns + /// + /// A `Result` containing the total price for the specified amount of tokens, + /// or a `BondingCurveError` if the calculation fails. fn calculate_price_many_checked( &self, starting_supply: u64,