Skip to main content

cosmwasm_common_library/
biginteger.rs

1use crate::bigdecimal::BigDecimal;
2use core::fmt::{Display, Formatter};
3use core::str::FromStr;
4use cosmwasm_schema::cw_serde;
5use cosmwasm_std::{StdError, StdResult, Uint128, Uint256};
6use std::iter::Sum;
7use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
8
9#[cw_serde]
10#[derive(Copy, Default, Ord, PartialOrd, Eq)]
11pub struct BigInteger(pub Uint256);
12
13impl BigInteger {
14    pub const MAX: Self = Self(Uint256::MAX);
15    pub const MIN: Self = Self(Uint256::MIN);
16
17    pub const fn new(value: u128) -> Self {
18        Self(Uint256::new(value))
19    }
20
21    pub fn scale_down(&self, decimals: u32) -> BigDecimal {
22        BigDecimal::from(*self, decimals)
23    }
24
25    pub fn scale_up(&self, decimals: u32) -> Self {
26        Self(self.0 * Uint256::from(10u64).pow(decimals))
27    }
28
29    pub fn to_uint128(&self) -> StdResult<Uint128> {
30        Ok(Uint128::try_from(self.0)?)
31    }
32
33    pub fn to_uint256(&self) -> Uint256 {
34        self.0
35    }
36
37    pub fn create_with_scale(value: u128, decimals: u32) -> Self {
38        Self::from(value).scale_up(decimals)
39    }
40
41    pub fn is_zero(&self) -> bool {
42        self.0.is_zero()
43    }
44
45    pub fn zero() -> Self {
46        Self(Uint256::zero())
47    }
48
49    pub fn one() -> Self {
50        Self(Uint256::one())
51    }
52
53    pub fn saturating_sub(&self, rhs: Self) -> Self {
54        Self(self.0.saturating_sub(rhs.0))
55    }
56
57    pub fn checked_sub(&self, rhs: Self) -> StdResult<Self> {
58        Ok(Self(self.0.checked_sub(rhs.0)?))
59    }
60
61    pub fn pow(&self, exp: u32) -> Self {
62        Self(self.0.pow(exp))
63    }
64
65    pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
66        Self(Uint256::from_be_bytes(bytes))
67    }
68
69    pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
70        Self(Uint256::from_le_bytes(bytes))
71    }
72
73    pub fn to_be_bytes(&self) -> [u8; 32] {
74        self.0.to_be_bytes()
75    }
76
77    pub fn to_le_bytes(&self) -> [u8; 32] {
78        self.0.to_le_bytes()
79    }
80
81    pub fn multiply_ratio<A: Into<Uint256>, B: Into<Uint256>>(
82        &self,
83        numerator: A,
84        denominator: B,
85    ) -> BigInteger {
86        let multiplier = BigDecimal::from_ratio(numerator, denominator);
87        BigInteger::from(*self * multiplier)
88    }
89}
90
91impl From<BigInteger> for String {
92    fn from(value: BigInteger) -> Self {
93        Self::from(value.0)
94    }
95}
96
97impl FromStr for BigInteger {
98    type Err = StdError;
99
100    fn from_str(s: &str) -> Result<Self, Self::Err> {
101        Ok(BigInteger(Uint256::from_str(s)?))
102    }
103}
104
105impl From<BigDecimal> for BigInteger {
106    fn from(value: BigDecimal) -> Self {
107        Self(value.0.to_uint_floor())
108    }
109}
110
111impl From<Uint256> for BigInteger {
112    fn from(value: Uint256) -> Self {
113        Self(value)
114    }
115}
116
117impl From<u128> for BigInteger {
118    fn from(value: u128) -> Self {
119        Self(Uint256::new(value))
120    }
121}
122
123impl From<Uint128> for BigInteger {
124    fn from(value: Uint128) -> Self {
125        Self::from(value.u128())
126    }
127}
128
129impl From<BigInteger> for Uint256 {
130    fn from(value: BigInteger) -> Self {
131        value.0
132    }
133}
134
135impl From<u64> for BigInteger {
136    fn from(value: u64) -> Self {
137        Self(Uint256::from(value))
138    }
139}
140
141impl From<u32> for BigInteger {
142    fn from(value: u32) -> Self {
143        Self(Uint256::from(value))
144    }
145}
146
147impl From<u16> for BigInteger {
148    fn from(value: u16) -> Self {
149        Self(Uint256::from(value))
150    }
151}
152
153impl From<u8> for BigInteger {
154    fn from(value: u8) -> Self {
155        Self(Uint256::from(value))
156    }
157}
158
159impl Sub<BigInteger> for BigInteger {
160    type Output = BigInteger;
161
162    fn sub(self, rhs: BigInteger) -> Self::Output {
163        Self(self.0 - rhs.0)
164    }
165}
166
167impl Add<BigInteger> for BigInteger {
168    type Output = BigInteger;
169
170    fn add(self, rhs: BigInteger) -> Self::Output {
171        Self(self.0 + rhs.0)
172    }
173}
174
175impl Div<BigInteger> for BigInteger {
176    type Output = BigInteger;
177
178    fn div(self, rhs: BigInteger) -> Self::Output {
179        Self(self.0 / rhs.0)
180    }
181}
182
183impl Div<BigDecimal> for BigInteger {
184    type Output = BigDecimal;
185
186    #[allow(clippy::suspicious_arithmetic_impl)]
187    fn div(self, rhs: BigDecimal) -> Self::Output {
188        BigDecimal::from(self, 0) / rhs
189    }
190}
191
192impl Mul<BigInteger> for BigInteger {
193    type Output = BigInteger;
194
195    fn mul(self, rhs: BigInteger) -> Self::Output {
196        Self(self.0 * rhs.0)
197    }
198}
199
200impl Mul<BigDecimal> for BigInteger {
201    type Output = BigDecimal;
202
203    fn mul(self, rhs: BigDecimal) -> Self::Output {
204        rhs * self
205    }
206}
207
208impl AddAssign for BigInteger {
209    fn add_assign(&mut self, rhs: Self) {
210        self.0 += rhs.0;
211    }
212}
213
214impl SubAssign for BigInteger {
215    fn sub_assign(&mut self, rhs: Self) {
216        self.0 -= rhs.0;
217    }
218}
219
220impl MulAssign for BigInteger {
221    fn mul_assign(&mut self, rhs: Self) {
222        self.0 *= rhs.0;
223    }
224}
225
226impl DivAssign for BigInteger {
227    fn div_assign(&mut self, rhs: Self) {
228        self.0 /= rhs.0;
229    }
230}
231
232impl Display for BigInteger {
233    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
234        self.0.fmt(f)
235    }
236}
237
238impl Sum for BigInteger {
239    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
240        iter.fold(Self::zero(), Add::add)
241    }
242}
243
244impl<'a> Sum<&'a BigInteger> for BigInteger {
245    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
246        iter.fold(Self::zero(), |a, b| a + *b)
247    }
248}
249
250#[cfg(test)]
251mod tests {
252    use crate::bigdecimal::BigDecimal;
253    use crate::biginteger::BigInteger;
254    use cosmwasm_std::{Decimal, Decimal256, Fraction, Uint128, Uint256};
255
256    #[test]
257    fn test_scale_down() {
258        let bigint = BigInteger(Uint256::from(1000000u64));
259        let bigdecimal = bigint.scale_down(6);
260        assert_eq!(bigdecimal, BigDecimal(Decimal256::one()));
261    }
262
263    #[test]
264    fn test_div() {
265        let d = BigDecimal::from(BigInteger::from(100000000000000000000u128), 0);
266        let i = BigInteger::from(100000000000000000000u128);
267        assert_eq!(i / d, BigDecimal::one());
268
269        let d = Decimal::percent(10);
270        assert_eq!(
271            BigInteger::from(Uint128::new(10).multiply_ratio(d.numerator(), d.denominator())),
272            BigInteger::from(BigInteger::new(10) * BigDecimal::percent(10)),
273        );
274    }
275
276    #[test]
277    fn test_sum() {
278        let vector: Vec<BigInteger> = vec![
279            BigInteger::from(1u64),
280            BigInteger::from(2u64),
281            BigInteger::from(3u64),
282        ];
283        assert_eq!(
284            vector.clone().into_iter().sum::<BigInteger>(),
285            BigInteger::from(6u64)
286        );
287        assert_eq!(vector.iter().sum::<BigInteger>(), BigInteger::from(6u64));
288    }
289
290    #[test]
291    fn test_bytes() {
292        let i = BigInteger(Uint256::from(1000000u64));
293
294        assert_eq!(BigInteger::from_be_bytes(i.to_be_bytes()), i);
295    }
296
297    #[test]
298    fn test_multiply_ratio() {
299        let a = BigInteger::new(100);
300
301        assert_eq!(a.multiply_ratio(1u128, 2u128), BigInteger::new(50));
302        assert_eq!(a.multiply_ratio(10u128, 10u128), BigInteger::new(100));
303        assert_eq!(a.multiply_ratio(2u128, 1u128), BigInteger::new(200));
304        assert_eq!(a.multiply_ratio(11u128, 10u128), BigInteger::new(110));
305        assert_eq!(a.multiply_ratio(10u128, 11u128), BigInteger::new(90));
306    }
307}