Skip to content

Commit 9cb10d2

Browse files
committed
suggestions
1 parent 17309ac commit 9cb10d2

File tree

1 file changed

+10
-33
lines changed
  • content/stellar-contracts/utils/math

1 file changed

+10
-33
lines changed

content/stellar-contracts/utils/math/wad.mdx

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -35,44 +35,22 @@ of floating-point arithmetic in smart contracts.
3535

3636
- **High Precision**: 18 decimals is more than sufficient for financial calculations
3737
- **Deterministic**: Same inputs always produce same outputs
38-
- **Gas Efficient**: Uses native `i128` arithmetic under the hood
38+
- **Efficient**: Uses native `i128` arithmetic under the hood
3939
- **Battle-Tested**: Used in production by MakerDAO, Uniswap, Aave, and others
4040
- **Ergonomic**: Operator overloading makes code readable: `a + b * c`
4141
- **Type Safe**: NewType pattern prevents mixing scaled and unscaled values
4242

4343
# Design Decisions
4444

45-
## 1. Why 18 Decimals?
46-
47-
18 decimals was chosen for several reasons:
48-
49-
- **Battle-Tested Standard**: Most DeFi protocols on use 18 decimals
50-
- **Sufficient Precision**: Provides precision down to 10^-18, far exceeding practical financial needs
51-
- **Interoperability**: Makes it easier to port DeFi protocols from other ecosystems to Stellar
52-
- **Performance**: Fits in `i128` without overflow concerns for typical values
53-
54-
**Example Precision:**
55-
```rust
56-
// Interest rate: 5.5% = 0.055
57-
let rate = Wad::from_ratio(&e, 55, 1000); // 55/1000 = 0.055
58-
59-
// Time fraction: 1 day / 365 days ≈ 0.00274
60-
let time = Wad::from_ratio(&e, 1, 365); // 1/365 ≈ 0.00274
61-
62-
// Interest = principal * rate * time
63-
let interest = principal * rate * time;
64-
// Precise to 18 decimal places!
65-
```
66-
67-
## 2. NewType Pattern
45+
## 1. NewType Pattern
6846

6947
We use a NewType `struct Wad(i128)` instead of a type alias:
7048

7149
```rust
72-
// ❌ BAD: Type alias
50+
// Type alias
7351
type Wad = i128;
7452

75-
// ✅ GOOD: NewType
53+
// NewType
7654
pub struct Wad(i128);
7755
```
7856

@@ -81,7 +59,7 @@ pub struct Wad(i128);
8159
- **Operator Overloading**: Can implement `+`, `-`, `*`, `/` with correct semantics
8260
- **Semantic Clarity**: Makes intent explicit in function signatures
8361

84-
## 3. No `From`/`Into` Traits
62+
## 2. No `From`/`Into` Traits
8563

8664
We deliberately **DID NOT** implement `From<i128>` or `Into<i128>` because it's ambiguous:
8765

@@ -96,17 +74,16 @@ Instead, we provide explicit constructors:
9674
- `Wad::from_integer(e, 5)` - Creates 5.0 (scaled)
9775
- `Wad::from_raw(5)` - Creates raw value 5 (0.000000000000000005)
9876

99-
## 4. Truncation vs Rounding
77+
## 3. Truncation vs Rounding
10078

10179
All operations truncate toward zero rather than rounding:
10280

10381
**Why truncation?**
10482
- **Predictable**: Same behavior as integer division
10583
- **Conservative**: In financial calculations, truncation is often safer (e.g., don't over-calculate interest)
10684
- **Fast**: No additional logic needed
107-
- **Standard**: Matches Solidity and most fixed-point libraries
10885

109-
## 5. Operator Overloading
86+
## 4. Operator Overloading
11087

11188
We provide operator overloading (`+`, `-`, `*`, `/`, `-`) for convenience:
11289

@@ -130,7 +107,7 @@ Operator overloading is supported across WAD and native i128 types where unambig
130107
Just like regular Rust, operator overloading does not include overflow checks:
131108

132109
- Use `checked_*` methods (`checked_add()`, `checked_sub()`, `checked_mul()`, etc.) when handling user inputs or when overflow is possible. These return `Option<Wad>` for safe error handling.
133-
- Use operator overloads (`+`, `-`, `*`, `/`) when you want to save gas by skipping overflow checks, or when you're confident the operation cannot overflow.
110+
- Use operator overloads (`+`, `-`, `*`, `/`) when you want to reduce computational overhead by skipping overflow checks, or when you're confident the operation cannot overflow.
134111

135112
This design follows Rust's standard library pattern: operators for performance, checked methods for safety.
136113

@@ -206,7 +183,7 @@ overflow `i128`, but the final scaled result would still fit in `i128`.
206183

207184
## Token Conversions
208185

209-
Different tokens have different decimal places (USDC: 6, ETH: 18, BTC: 8). WAD handles these conversions:
186+
Different tokens have different decimal places (USDC: 6, XLM: 7, ETH: 18, BTC: 8). WAD handles these conversions:
210187

211188
```rust
212189
// Convert from USDC (6 decimals) to WAD
@@ -261,7 +238,7 @@ let result2 = a * (b * c); // Truncates after inner multiplication
261238

262239
```rust
263240
use soroban_sdk::Env;
264-
use contract_utils::math::wad::Wad;
241+
use stellar_contract_utils::math::wad::Wad;
265242

266243
fn calculate_interest(e: &Env, principal: i128, rate_bps: u32) -> i128 {
267244
// Convert principal (assume 6 decimals like USDC)

0 commit comments

Comments
 (0)