Smart Contract

FlowALPMath

A.6b00ff876c299c61.FlowALPMath

Valid From

142,666,847

Deployed

1w ago
Feb 18, 2026, 10:18:35 PM UTC

Dependents

0 imports
1access(all) contract FlowALPMath {
2
3    access(self) let ufix64Step: UFix128
4    access(self) let ufix64HalfStep: UFix128
5
6    access(all) let decimals: UInt8
7    access(all) let ufix64Decimals: UInt8
8
9    /// Deprecated: Use 1.0 directly
10    access(all) let one: UFix128
11    /// Deprecated: Use 0.0 directly
12    access(all) let zero: UFix128
13
14    access(all) enum RoundingMode: UInt8 {
15        access(all) case RoundDown
16        access(all) case RoundUp
17        access(all) case RoundHalfUp
18        access(all) case RoundEven
19    }
20
21    /// Fast exponentiation for UFix128 with a non-negative integer exponent (seconds).
22    /// Uses exponentiation-by-squaring with truncation at each multiply (fixed-point semantics)
23    access(all) view fun powUFix128(_ base: UFix128, _ expSeconds: UFix64): UFix128 {
24        if expSeconds == 0.0 { return 1.0 }
25        if base == 1.0 { return 1.0 }
26        var result: UFix128 = 1.0
27        var b = base
28        var e = expSeconds
29        // Floor the seconds to an integer count
30        var remaining = UInt64(e)
31        while remaining > 0 {
32            if remaining % 2 == 1 {
33                result = result * b
34            }
35            b = b * b
36            remaining = remaining / 2
37        }
38        return result
39    }
40
41    access(all) view fun toUFix64(_ value: UFix128, rounding: RoundingMode): UFix64 {
42        let truncated = UFix64(value)
43        let truncatedAs128 = UFix128(truncated)
44        let remainder = value - truncatedAs128
45
46        if remainder == 0.0 {
47            return truncated
48        }
49
50        switch rounding {
51        case self.RoundingMode.RoundDown:
52            return truncated
53        case self.RoundingMode.RoundUp:
54            return self.roundUp(truncated)
55        case self.RoundingMode.RoundHalfUp:
56            return remainder >= self.ufix64HalfStep ? self.roundUp(truncated) : truncated
57        case self.RoundingMode.RoundEven:
58            return self.roundHalfToEven(truncated, remainder)
59        default:
60            panic("Unsupported rounding mode")
61        }
62    }
63
64    access(all) view fun toUFix64Round(_ value: UFix128): UFix64 {
65        return self.toUFix64(value, rounding: self.RoundingMode.RoundHalfUp)
66    }
67
68    access(all) view fun toUFix64RoundDown(_ value: UFix128): UFix64 {
69        return self.toUFix64(value, rounding: self.RoundingMode.RoundDown)
70    }
71
72    access(all) view fun toUFix64RoundUp(_ value: UFix128): UFix64 {
73        return self.toUFix64(value, rounding: self.RoundingMode.RoundUp)
74    }
75
76    access(self) view fun roundUp(_ base: UFix64): UFix64 {
77        let increment: UFix64 = 0.00000001
78        return base >= UFix64.max - increment ? UFix64.max : base + increment
79    }
80
81    access(self) view fun roundHalfToEven(_ base: UFix64, _ remainder: UFix128): UFix64 {
82        if remainder < self.ufix64HalfStep {
83            return base
84        }
85        if remainder > self.ufix64HalfStep {
86            return self.roundUp(base)
87        }
88        let scaled = base * 100_000_000.0
89        let scaledInt = UInt64(scaled)
90        return scaledInt % 2 == 1 ? self.roundUp(base) : base
91    }
92
93    init() {
94        self.ufix64Step = 0.00000001
95        self.ufix64HalfStep = self.ufix64Step / 2.0
96        self.decimals = 24
97        self.ufix64Decimals = 8
98
99        self.one = 1.0
100        self.zero = 0.0
101    }
102}
103