1use std::{
5 fmt,
6 ops::{Add, AddAssign, Deref, DerefMut, Mul, MulAssign, Sub, SubAssign},
7 sync::LazyLock,
8};
9
10use super::fvm_shared_latest::econ::TokenAmount as TokenAmount_latest;
11use crate::utils::get_size::big_int_heap_size_helper;
12use fvm_shared2::econ::TokenAmount as TokenAmount_v2;
13use fvm_shared3::econ::TokenAmount as TokenAmount_v3;
14pub use fvm_shared3::{BLOCK_GAS_LIMIT, TOTAL_FILECOIN_BASE};
15use fvm_shared4::econ::TokenAmount as TokenAmount_v4;
16use get_size2::GetSize;
17use num_bigint::BigInt;
18use num_traits::Zero;
19use serde::{Deserialize, Serialize};
20use static_assertions::const_assert_eq;
21
22const_assert_eq!(BLOCK_GAS_LIMIT, fvm_shared2::BLOCK_GAS_LIMIT as u64);
23const_assert_eq!(TOTAL_FILECOIN_BASE, fvm_shared2::TOTAL_FILECOIN_BASE);
24
25pub static TOTAL_FILECOIN: LazyLock<TokenAmount> =
27 LazyLock::new(|| TokenAmount::from_whole(TOTAL_FILECOIN_BASE));
28
29#[derive(Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize, Default)]
30#[serde(transparent)]
31pub struct TokenAmount(TokenAmount_latest);
32
33impl fmt::Debug for TokenAmount {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 fmt::Debug::fmt(&self.0, f)
36 }
37}
38
39impl GetSize for TokenAmount {
40 fn get_heap_size(&self) -> usize {
41 big_int_heap_size_helper(self.0.atto())
42 }
43}
44
45#[cfg(test)]
46impl quickcheck::Arbitrary for TokenAmount {
47 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
48 use fvm_shared4::bigint::MAX_BIGINT_SIZE;
49 use num::BigUint;
50 let significant_bits = usize::arbitrary(g) % ((MAX_BIGINT_SIZE - 1) * 8);
59 let bigint_upper_limit = BigUint::from(1u8) << significant_bits;
60 TokenAmount::from_atto(BigUint::arbitrary(g) % bigint_upper_limit)
61 }
62}
63
64impl Zero for TokenAmount {
65 fn zero() -> Self {
66 TokenAmount(TokenAmount_latest::zero())
67 }
68 fn is_zero(&self) -> bool {
69 self.0.is_zero()
70 }
71}
72
73impl Deref for TokenAmount {
74 type Target = TokenAmount_latest;
75
76 fn deref(&self) -> &Self::Target {
77 &self.0
78 }
79}
80
81impl DerefMut for TokenAmount {
82 fn deref_mut(&mut self) -> &mut Self::Target {
83 &mut self.0
84 }
85}
86
87impl std::fmt::Display for TokenAmount {
88 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
90 self.0.fmt(f)
91 }
92}
93
94impl TokenAmount {
95 pub const DECIMALS: usize = TokenAmount_latest::DECIMALS;
97
98 pub const PRECISION: u64 = TokenAmount_latest::PRECISION;
100
101 pub fn atto(&self) -> &BigInt {
103 self.0.atto()
104 }
105
106 pub fn from_atto(atto: impl Into<BigInt>) -> Self {
107 TokenAmount_v3::from_atto(atto).into()
108 }
109
110 pub fn from_nano(nano: impl Into<BigInt>) -> Self {
111 TokenAmount_v3::from_nano(nano).into()
112 }
113
114 pub fn from_whole(fil: impl Into<BigInt>) -> Self {
115 TokenAmount_v3::from_whole(fil).into()
116 }
117
118 #[inline]
119 pub fn div_rem(&self, other: impl Into<BigInt>) -> (TokenAmount, TokenAmount) {
120 let (q, r) = self.0.div_rem(other);
121 (q.into(), r.into())
122 }
123
124 #[inline]
125 pub fn div_ceil(&self, other: impl Into<BigInt>) -> TokenAmount {
126 self.0.div_ceil(other).into()
127 }
128
129 #[inline]
130 pub fn div_floor(&self, other: impl Into<BigInt>) -> TokenAmount {
131 self.0.div_floor(other).into()
132 }
133}
134
135impl From<TokenAmount> for BigInt {
136 fn from(value: TokenAmount) -> Self {
137 value.atto().to_owned()
138 }
139}
140
141impl From<BigInt> for TokenAmount {
142 fn from(value: BigInt) -> Self {
143 Self::from_atto(value)
144 }
145}
146
147impl From<TokenAmount_v2> for TokenAmount {
148 fn from(other: TokenAmount_v2) -> Self {
149 (&other).into()
150 }
151}
152
153impl From<&TokenAmount_v2> for TokenAmount {
154 fn from(other: &TokenAmount_v2) -> Self {
155 Self(TokenAmount_latest::from_atto(other.atto().clone()))
156 }
157}
158
159impl From<&TokenAmount_v3> for TokenAmount {
160 fn from(other: &TokenAmount_v3) -> Self {
161 Self(TokenAmount_latest::from_atto(other.atto().clone()))
162 }
163}
164
165impl From<TokenAmount_v3> for TokenAmount {
166 fn from(other: TokenAmount_v3) -> Self {
167 (&other).into()
168 }
169}
170
171impl From<TokenAmount_v4> for TokenAmount {
172 fn from(other: TokenAmount_v4) -> Self {
173 TokenAmount(other)
174 }
175}
176
177impl From<&TokenAmount_v4> for TokenAmount {
178 fn from(other: &TokenAmount_v4) -> Self {
179 other.clone().into()
180 }
181}
182
183impl From<TokenAmount> for TokenAmount_v2 {
184 fn from(other: TokenAmount) -> Self {
185 (&other).into()
186 }
187}
188
189impl From<&TokenAmount> for TokenAmount_v2 {
190 fn from(other: &TokenAmount) -> Self {
191 Self::from_atto(other.atto().clone())
192 }
193}
194
195impl From<TokenAmount> for TokenAmount_v3 {
196 fn from(other: TokenAmount) -> Self {
197 (&other).into()
198 }
199}
200
201impl From<&TokenAmount> for TokenAmount_v3 {
202 fn from(other: &TokenAmount) -> Self {
203 Self::from_atto(other.atto().clone())
204 }
205}
206
207impl From<TokenAmount> for TokenAmount_v4 {
208 fn from(other: TokenAmount) -> Self {
209 other.0
210 }
211}
212
213impl From<&TokenAmount> for TokenAmount_v4 {
214 fn from(other: &TokenAmount) -> Self {
215 other.0.clone()
216 }
217}
218
219impl Mul<BigInt> for TokenAmount {
220 type Output = TokenAmount;
221 fn mul(self, rhs: BigInt) -> Self::Output {
222 self.0.mul(rhs).into()
223 }
224}
225
226impl MulAssign<BigInt> for TokenAmount {
227 fn mul_assign(&mut self, rhs: BigInt) {
228 self.0.mul_assign(rhs)
229 }
230}
231
232impl Mul<BigInt> for &TokenAmount {
233 type Output = TokenAmount;
234 fn mul(self, rhs: BigInt) -> Self::Output {
235 (&self.0).mul(rhs).into()
236 }
237}
238
239impl Mul<i64> for &TokenAmount {
240 type Output = TokenAmount;
241 fn mul(self, rhs: i64) -> Self::Output {
242 (&self.0).mul(rhs).into()
243 }
244}
245
246impl Mul<i64> for TokenAmount {
247 type Output = TokenAmount;
248 fn mul(self, rhs: i64) -> Self::Output {
249 (&self.0).mul(rhs).into()
250 }
251}
252
253impl Mul<u64> for &TokenAmount {
254 type Output = TokenAmount;
255 fn mul(self, rhs: u64) -> Self::Output {
256 (&self.0).mul(rhs).into()
257 }
258}
259
260impl Mul<u64> for TokenAmount {
261 type Output = TokenAmount;
262 fn mul(self, rhs: u64) -> Self::Output {
263 (&self.0).mul(rhs).into()
264 }
265}
266
267impl Add<TokenAmount> for &TokenAmount {
268 type Output = TokenAmount;
269 fn add(self, rhs: TokenAmount) -> Self::Output {
270 (&self.0).add(rhs.0).into()
271 }
272}
273
274impl Add<&TokenAmount> for &TokenAmount {
275 type Output = TokenAmount;
276 fn add(self, rhs: &TokenAmount) -> Self::Output {
277 (&self.0).add(&rhs.0).into()
278 }
279}
280
281impl Add<TokenAmount> for TokenAmount {
282 type Output = TokenAmount;
283 fn add(self, rhs: TokenAmount) -> Self::Output {
284 (&self.0).add(rhs.0).into()
285 }
286}
287
288impl Add<&TokenAmount> for TokenAmount {
289 type Output = TokenAmount;
290 fn add(self, rhs: &TokenAmount) -> Self::Output {
291 (&self.0).add(&rhs.0).into()
292 }
293}
294
295impl AddAssign for TokenAmount {
296 fn add_assign(&mut self, other: Self) {
297 self.0.add_assign(other.0)
298 }
299}
300
301impl SubAssign for TokenAmount {
302 fn sub_assign(&mut self, other: Self) {
303 self.0.sub_assign(other.0)
304 }
305}
306
307impl Sub<&TokenAmount> for TokenAmount {
308 type Output = TokenAmount;
309 fn sub(self, rhs: &TokenAmount) -> Self::Output {
310 (&self.0).sub(&rhs.0).into()
311 }
312}
313
314impl Sub<TokenAmount> for &TokenAmount {
315 type Output = TokenAmount;
316 fn sub(self, rhs: TokenAmount) -> Self::Output {
317 (&self.0).sub(&rhs.0).into()
318 }
319}