@@ -178,6 +178,32 @@ impl Div for Wad {
178178}
179179```
180180
181+ ## Exponentiation
182+
183+ WAD supports raising a value to an ** unsigned integer exponent** via ` pow ` .
184+
185+ - ` pow(&e, exponent) ` is optimized using ** exponentiation by squaring** (O(log n) multiplications).
186+ - Each multiplication keeps WAD semantics (fixed-point multiplication and truncation toward zero).
187+ - Overflow is reported via Soroban errors.
188+
189+ In addition to ` pow ` , WAD also provides ` checked_pow ` , which returns ` None ` on overflow.
190+
191+ ``` rust
192+ // Compound interest multiplier: (1.05)^10
193+ let rate = Wad :: from_ratio (& e , 105 , 100 ); // 1.05
194+ let multiplier = rate . pow (& e , 10 );
195+ ```
196+
197+ ### Notes on ` pow ` and Phantom Overflow
198+
199+ ` pow ` / ` checked_pow ` are implemented using exponentiation by squaring and rely
200+ on Soroban fixed-point helpers that can automatically scale intermediate products
201+ to ` I256 ` when needed.
202+
203+ This avoids ** phantom overflow** cases where an intermediate multiplication would
204+ overflow ` i128 ` , but the final scaled result would still fit in ` i128 ` .
205+
206+
181207## Token Conversions
182208
183209Different tokens have different decimal places (USDC: 6, ETH: 18, BTC: 8). WAD handles these conversions:
@@ -305,7 +331,7 @@ fn safe_multiply(e: &Env, a: i128, b: i128) -> Result<i128, Error> {
305331
306332 // Use checked variant
307333 let result_wad = a_wad
308- . checked_mul (b_wad )
334+ . checked_mul (e , b_wad )
309335 . ok_or (Error :: Overflow )? ;
310336
311337 Ok (result_wad . to_token_amount (e , 6 ))
@@ -351,10 +377,11 @@ fn safe_multiply(e: &Env, a: i128, b: i128) -> Result<i128, Error> {
351377| --------| ---------| -------------|
352378| ` checked_add(rhs) ` | ` Option<Wad> ` | Addition with overflow check |
353379| ` checked_sub(rhs) ` | ` Option<Wad> ` | Subtraction with overflow check |
354- | ` checked_mul(rhs) ` | ` Option<Wad> ` | Multiplication with overflow check |
380+ | ` checked_mul(e, rhs) ` | ` Option<Wad> ` | Multiplication with overflow check (handles phantom overflow internally) |
355381| ` checked_div(rhs) ` | ` Option<Wad> ` | Division with overflow/zero check |
356382| ` checked_mul_int(n) ` | ` Option<Wad> ` | Integer multiplication with overflow check |
357383| ` checked_div_int(n) ` | ` Option<Wad> ` | Integer division with zero check |
384+ | ` checked_pow(e, exponent) ` | ` Option<Wad> ` | Exponentiation with overflow check |
358385
359386## Utility Methods
360387
@@ -363,16 +390,15 @@ fn safe_multiply(e: &Env, a: i128, b: i128) -> Result<i128, Error> {
363390| ` abs() ` | Absolute value |
364391| ` min(other) ` | Minimum of two values |
365392| ` max(other) ` | Maximum of two values |
393+ | ` pow(e, exponent) ` | Raises WAD to an unsigned integer power (panics with Soroban error on overflow) |
366394
367395## Error Handling
368396
369- WAD uses Soroban's contract error system:
397+ WAD uses Soroban's contract error system via ` SorobanFixedPointError ` :
370398
371399``` rust
372- #[contracterror]
373- pub enum WadError {
374- Overflow = 1600 , // Arithmetic overflow
375- DivisionByZero = 1601 , // Division by zero
376- InvalidDecimals = 1602 , // Invalid decimal conversion
400+ pub enum SorobanFixedPointError {
401+ Overflow = 1500 ,
402+ DivisionByZero = 1501 ,
377403}
378404```
0 commit comments