名称: mvx_defi_math 描述: MultiversX DeFi 的金融数学 — 精度管理、半上舍入、安全重缩放、百分比计算。
MultiversX DeFi 数学模式
精度级别
| 级别 | 小数位数 | 使用场景 |
|---|---|---|
| BPS (4) | 10,000 = 100% | 费用,简单百分比 |
| PPM (6) | 1,000,000 = 100% | 细粒度百分比 |
| WAD (18) | 1e18 = 1.0 | 代币数量,价格 |
| RAY (27) | 1e27 = 1.0 | 利息指数,复利,高精度数学 |
pub const BPS: u64 = 10_000;
pub const PPM: u64 = 1_000_000;
pub const WAD: u128 = 1_000_000_000_000_000_000;
pub const RAY: u128 = 1_000_000_000_000_000_000_000_000_000;
规则: 使用避免舍入误差的最低精度。中间计算使用比最终结果更高的精度。
半上舍入
标准的 ManagedDecimal 截断 → 系统性价值损失 → 可被利用。
乘法
fn mul_half_up(&self, a: &ManagedDecimal<Self::Api, NumDecimals>, b: &ManagedDecimal<Self::Api, NumDecimals>, precision: NumDecimals) -> ManagedDecimal<Self::Api, NumDecimals> {
let product = a.rescale(precision).into_raw_units() * b.rescale(precision).into_raw_units();
let scaled = BigUint::from(10u64).pow(precision as u32);
let rounded = (product + &scaled / 2u64) / scaled;
self.to_decimal(rounded, precision)
}
除法
fn div_half_up(&self, a: &ManagedDecimal<Self::Api, NumDecimals>, b: &ManagedDecimal<Self::Api, NumDecimals>, precision: NumDecimals) -> ManagedDecimal<Self::Api, NumDecimals> {
let scaled = BigUint::from(10u64).pow(precision as u32);
let numerator = a.rescale(precision).into_raw_units() * &scaled;
let denominator = b.rescale(precision).into_raw_units();
let rounded = (numerator + &denominator / 2u64) / denominator;
self.to_decimal(rounded, precision)
}
安全重缩放
fn rescale_half_up(&self, value: &ManagedDecimal<Self::Api, NumDecimals>, new_precision: NumDecimals) -> ManagedDecimal<Self::Api, NumDecimals> {
let old = value.scale();
if new_precision >= old { return value.rescale(new_precision); }
let factor = BigUint::from(10u64).pow((old - new_precision) as u32);
ManagedDecimal::from_raw_units((value.into_raw_units() + &factor / 2u64) / factor, new_precision)
}
百分比计算
框架内置: proportion()
// 首选 — 使用框架中的 BigUint::proportion(part, total)
pub const PERCENT_BASE_POINTS: u64 = 100_000; // 100% = 100_000
let fee = amount.proportion(fee_percent, PERCENT_BASE_POINTS);
手动 BPS / PPM
pub fn apply_bps(amount: &BigUint, bps: u64) -> BigUint { (amount * bps) / 10_000u64 }
pub fn apply_ppm(amount: &BigUint, ppm: u32) -> BigUint { (amount * ppm) / 1_000_000u64 }
舍入攻击向量
| 攻击 | 缓解措施 |
|---|---|
| 粉尘存款以窃取舍入 | 在缩放金额上使用半上舍入 |
| 重复小操作 | 最小金额 + 在指数上使用半上舍入 |
| 转换中的精度损失 | 中间数学使用 RAY 精度 |
| 费用计算中的截断 | 向上舍入费用(协议优势) |
反模式
- 混合精度而不重缩放
- 截断除法用于费用(应使用向上舍入除法)
- 中间结果在低精度(计算时使用 RAY,最后降精度)
领域应用
- 借贷: 利息模型,复利,利用率 — RAY 精度
- DEX: 价格影响,LP 份额 — WAD 精度,使用半上舍入
- 质押: 奖励分配,份额比率 — RAY 指数
- 保险库: 费用计算,收益 — BPS 费用,使用向上舍入除法