pub struct Wad(/* private fields */);Expand description
Fixed-point decimal number with 18 decimal places of precision.
Wad represents decimal numbers using a fixed-point representation where
1.0 is stored as 1_000_000_000_000_000_000 (10^18). This provides precise
decimal arithmetic suitable for financial calculations in smart contracts.
§Truncation
All arithmetic operations truncate toward zero rather than rounding:
5 / 2 = 2(not 2.5 or 3)-5 / 2 = -2(not -2.5 or -3)
§Precision
Due to truncation on each multiplication/division, the order of operations can affect results:
let a = Wad::from_integer(&e, 1000);
let b = Wad::from_raw(55_000_000_000_000_000); // 0.055
let c = Wad::from_raw(8_333_333_333_333_333); // ~0.00833
let result1 = a * b * c; // Truncates after first multiplication
let result2 = a * (b * c); // Truncates after inner multiplication
// result1 and result2 may differ by ~10^-16 due to different truncation pointsTypical precision loss: ~10^-15 to 10^-16 in relative terms, which is negligible when converting to typical token precision (6-8 decimals).
§Examples
use soroban_sdk::Env;
use contract_utils::math::wad::Wad;
let e = Env::default();
// Creating Wad values
let five = Wad::from_integer(&e, 5); // 5.0
let half = Wad::from_ratio(&e, 1, 2); // 0.5
let price = Wad::from_token_amount(&e, 1_500_000, 6); // 1.5 (from USDC)
// Arithmetic
let sum = five + half; // 5.5
let product = five * half; // 2.5
let quotient = five / half; // 10.0
// Converting back to token amounts
let usdc_amount = product.to_token_amount(&e, 6); // 2_500_000 (2.5 USDC)Implementations§
Source§impl Wad
impl Wad
Sourcepub fn from_integer(e: &Env, n: i128) -> Self
pub fn from_integer(e: &Env, n: i128) -> Self
Creates a Wad from an integer by applying WAD scaling.
Treats the input as a whole number and scales it to WAD precision (18 decimals).
§Arguments
e- Access to the Soroban environment.n- The integer value to convert to WAD representation.
§Errors
SorobanFixedPointError::Overflow- When the multiplication overflows i128.
§Examples
let wad = Wad::from_integer(&e, 5);
assert_eq!(wad.raw(), 5_000_000_000_000_000_000);§Notes
Compare with Wad::from_raw which does NOT apply WAD scaling.
Sourcepub fn to_integer(self) -> i128
pub fn to_integer(self) -> i128
Sourcepub fn from_ratio(e: &Env, num: i128, den: i128) -> Self
pub fn from_ratio(e: &Env, num: i128, den: i128) -> Self
Creates a Wad from a ratio (num / den).
§Arguments
e- Access to the Soroban environment.num- The numerator of the ratio.den- The denominator of the ratio.
§Errors
SorobanFixedPointError::DivisionByZero- Whendenis zero.SorobanFixedPointError::Overflow- When the multiplication overflows i128.
§Examples
let wad = Wad::from_ratio(&e, 5, 10);
assert_eq!(wad.raw(), 500_000_000_000_000_000); // 0.5 in WADSourcepub fn from_token_amount(e: &Env, amount: i128, token_decimals: u8) -> Self
pub fn from_token_amount(e: &Env, amount: i128, token_decimals: u8) -> Self
Creates a Wad from a token amount with specified decimals.
Converts a token’s native representation to WAD (18 decimals). Truncates toward zero when scaling down (token_decimals > 18).
§Arguments
e- Access to the Soroban environment.amount- The token amount in its smallest unit.token_decimals- The number of decimals the token uses.
§Errors
SorobanFixedPointError::Overflow- When the scaling multiplication overflows i128.
§Examples
// USDC has 2 decimals, so 1 USDC = 100 units
let wad = Wad::from_token_amount(&e, 100, 2);
assert_eq!(wad.raw(), 1_000_000_000_000_000_000); // 1.0 in WAD§Notes
amount must be in the token’s smallest unit. For example, to represent
1 USDC (2 decimals), pass 100, not 1.
Sourcepub fn to_token_amount(self, e: &Env, token_decimals: u8) -> i128
pub fn to_token_amount(self, e: &Env, token_decimals: u8) -> i128
Converts Wad to a token amount with specified decimals.
Converts from WAD (18 decimals) back to a token’s native representation. Truncates toward zero when scaling down (token_decimals < 18).
§Arguments
e- Access to the Soroban environment.token_decimals- The number of decimals the target token uses.
§Errors
SorobanFixedPointError::Overflow- When the scaling multiplication overflows i128 (occurs whentoken_decimals > 18).
§Examples
let wad = Wad::from_raw(1_000_000_000_000_000_000); // 1.0 in WAD
let usdc_amount = wad.to_token_amount(&e, 2);
assert_eq!(usdc_amount, 100); // 1 USDC = 100 unitsSourcepub fn from_price(e: &Env, price_integer: i128, price_decimals: u8) -> Self
pub fn from_price(e: &Env, price_integer: i128, price_decimals: u8) -> Self
Creates a Wad from a price with specified decimals.
This is an alias for Wad::from_token_amount.
§Arguments
e- Access to the Soroban environment.price_integer- The price in its smallest unit.price_decimals- The number of decimals the price uses.
§Errors
refer to Wad::from_token_amount errors.
Sourcepub fn from_raw(raw: i128) -> Self
pub fn from_raw(raw: i128) -> Self
Creates a Wad from a raw i128 value without applying WAD scaling.
Interprets the input as the internal representation directly.
§Arguments
raw- The raw internal value.
§Examples
let wad = Wad::from_raw(5);
// Represents 0.000000000000000005 in decimal
assert_eq!(wad.raw(), 5);§Notes
Compare with Wad::from_integer which applies WAD scaling.
Sourcepub fn checked_add(self, rhs: Wad) -> Option<Wad>
pub fn checked_add(self, rhs: Wad) -> Option<Wad>
Checked addition. Returns None on overflow.
Sourcepub fn checked_sub(self, rhs: Wad) -> Option<Wad>
pub fn checked_sub(self, rhs: Wad) -> Option<Wad>
Checked subtraction. Returns None on overflow.
Sourcepub fn checked_mul(self, e: &Env, rhs: Wad) -> Option<Wad>
pub fn checked_mul(self, e: &Env, rhs: Wad) -> Option<Wad>
Checked multiplication (Wad * Wad).
Returns None on overflow. Handles phantom overflow by scaling to
I256 when intermediate multiplication overflows i128 but the final
result fits. Result is truncated toward zero after division by
WAD_SCALE.
Sourcepub fn checked_div(self, e: &Env, rhs: Wad) -> Option<Wad>
pub fn checked_div(self, e: &Env, rhs: Wad) -> Option<Wad>
Checked division (Wad / Wad). Returns None on overflow or division by
zero.
Result is truncated toward zero.
Sourcepub fn checked_mul_int(self, n: i128) -> Option<Wad>
pub fn checked_mul_int(self, n: i128) -> Option<Wad>
Checked multiplication by integer. Returns None on overflow.
Sourcepub fn checked_div_int(self, n: i128) -> Option<Wad>
pub fn checked_div_int(self, n: i128) -> Option<Wad>
Checked division by integer. Returns None on division by zero.
Sourcepub fn pow(self, e: &Env, exponent: u32) -> Self
pub fn pow(self, e: &Env, exponent: u32) -> Self
Raises Wad to an unsigned integer power using exponentiation by squaring.
This method is optimized for efficiency, computing the result in O(log n) multiplications where n is the exponent. Each multiplication maintains fixed-point precision by dividing by WAD_SCALE, with truncation toward zero.
§Arguments
e- Access to the Soroban environment for error handling.exponent- The unsigned integer exponent (0 to 2^32-1).
§Errors
SorobanFixedPointError::Overflow- When intermediate or final result exceeds i128 bounds.
§Examples
// Compound interest: (1.05)^10
let rate = Wad::from_ratio(&e, 105, 100); // 1.05
let final_multiplier = rate.pow(&e, 10);
let final_amount = principal * final_multiplier;
// Quadratic bonding curve: price = supply^2
let supply = Wad::from_integer(&e, 1000);
let price = supply.pow(&e, 2);Sourcepub fn checked_pow(self, e: &Env, exponent: u32) -> Option<Self>
pub fn checked_pow(self, e: &Env, exponent: u32) -> Option<Self>
Checked version of Wad::pow.
Returns None instead of panicking on overflow. Handles phantom
overflow transparently by scaling to I256 when intermediate
multiplications overflow i128 but the final result fits.
§Arguments
e- Access to the Soroban environment for i256 operations.exponent- The unsigned integer exponent.
§Examples
let e = Env::default();
let small = Wad::from_integer(&e, 2);
assert_eq!(small.checked_pow(&e, 10), Some(Wad::from_integer(&e, 1024)));
let large = Wad::from_integer(&e, i128::MAX / WAD_SCALE);
assert_eq!(large.checked_pow(&e, 2), None); // Overflows§Notes
Phantom overflow is handled internally.
Trait Implementations§
Source§impl Ord for Wad
impl Ord for Wad
Source§impl PartialOrd for Wad
impl PartialOrd for Wad
impl Copy for Wad
impl Eq for Wad
impl StructuralPartialEq for Wad
Auto Trait Implementations§
impl Freeze for Wad
impl RefUnwindSafe for Wad
impl Send for Wad
impl Sync for Wad
impl Unpin for Wad
impl UnwindSafe for Wad
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
Source§impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
type Error = E
fn compare( &self, a: &(T, U, V, W), b: &(T, U, V, W), ) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>
Source§impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
type Error = E
fn compare( &self, a: &(T, U, V, W, X), b: &(T, U, V, W, X), ) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more