forest/shim/
econ.rs

1// Copyright 2019-2025 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use 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
25/// Total Filecoin available to the network.
26pub 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        // During serialization/deserialization, permissible length of the byte
51        // representation (plus a leading positive sign byte for non-zero
52        // values) of BigInts is currently set to a max of MAX_BIGINT_SIZE with
53        // a value of 128; need to constrain the corresponding length during
54        // `Arbitrary` generation of `BigInt` in `TokenAmount` to below
55        // MAX_BIGINT_SIZE.
56        // The 'significant_bits' variable changes the distribution from uniform
57        // to log-scaled.
58        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    // This trait requires `fmt` with this exact signature.
89    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
90        self.0.fmt(f)
91    }
92}
93
94impl TokenAmount {
95    /// The logical number of decimal places of a token unit.
96    pub const DECIMALS: usize = TokenAmount_latest::DECIMALS;
97
98    /// The logical precision of a token unit.
99    pub const PRECISION: u64 = TokenAmount_latest::PRECISION;
100
101    /// Returns the quantity of indivisible units.
102    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}