cosmwasm_common_library/
biginteger.rs1use 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}