casper_types/
motes.rs

1//! The `motes` module is used for working with Motes.
2
3use alloc::vec::Vec;
4use core::{
5    fmt,
6    iter::Sum,
7    ops::{Add, Div, Mul, Sub},
8};
9
10#[cfg(feature = "datasize")]
11use datasize::DataSize;
12use num::Zero;
13use serde::{Deserialize, Serialize};
14
15use crate::{
16    bytesrepr::{self, FromBytes, ToBytes},
17    Gas, U512,
18};
19
20/// A struct representing a number of `Motes`.
21#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
22#[cfg_attr(feature = "datasize", derive(DataSize))]
23pub struct Motes(U512);
24
25impl Motes {
26    /// Constructs a new `Motes`.
27    pub fn new(value: U512) -> Motes {
28        Motes(value)
29    }
30
31    /// Checked integer addition. Computes `self + rhs`, returning `None` if overflow occurred.
32    pub fn checked_add(&self, rhs: Self) -> Option<Self> {
33        self.0.checked_add(rhs.value()).map(Self::new)
34    }
35
36    /// Checked integer subtraction. Computes `self - rhs`, returning `None` if underflow occurred.
37    pub fn checked_sub(&self, rhs: Self) -> Option<Self> {
38        self.0.checked_sub(rhs.value()).map(Self::new)
39    }
40
41    /// Returns the inner `U512` value.
42    pub fn value(&self) -> U512 {
43        self.0
44    }
45
46    /// Converts the given `gas` to `Motes` by multiplying them by `conv_rate`.
47    ///
48    /// Returns `None` if an arithmetic overflow occurred.
49    pub fn from_gas(gas: Gas, conv_rate: u64) -> Option<Self> {
50        gas.value()
51            .checked_mul(U512::from(conv_rate))
52            .map(Self::new)
53    }
54}
55
56impl fmt::Display for Motes {
57    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58        write!(f, "{:?}", self.0)
59    }
60}
61
62impl Add for Motes {
63    type Output = Motes;
64
65    fn add(self, rhs: Self) -> Self::Output {
66        let val = self.value() + rhs.value();
67        Motes::new(val)
68    }
69}
70
71impl Sub for Motes {
72    type Output = Motes;
73
74    fn sub(self, rhs: Self) -> Self::Output {
75        let val = self.value() - rhs.value();
76        Motes::new(val)
77    }
78}
79
80impl Div for Motes {
81    type Output = Motes;
82
83    fn div(self, rhs: Self) -> Self::Output {
84        let val = self.value() / rhs.value();
85        Motes::new(val)
86    }
87}
88
89impl Mul for Motes {
90    type Output = Motes;
91
92    fn mul(self, rhs: Self) -> Self::Output {
93        let val = self.value() * rhs.value();
94        Motes::new(val)
95    }
96}
97
98impl Zero for Motes {
99    fn zero() -> Self {
100        Motes::new(U512::zero())
101    }
102
103    fn is_zero(&self) -> bool {
104        self.0.is_zero()
105    }
106}
107
108impl Sum for Motes {
109    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
110        iter.fold(Motes::zero(), Add::add)
111    }
112}
113
114impl ToBytes for Motes {
115    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
116        self.0.to_bytes()
117    }
118
119    fn serialized_length(&self) -> usize {
120        self.0.serialized_length()
121    }
122}
123
124impl FromBytes for Motes {
125    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
126        let (value, remainder) = FromBytes::from_bytes(bytes)?;
127        Ok((Motes::new(value), remainder))
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use crate::U512;
134
135    use crate::{Gas, Motes};
136
137    #[test]
138    fn should_be_able_to_get_instance_of_motes() {
139        let initial_value = 1;
140        let motes = Motes::new(U512::from(initial_value));
141        assert_eq!(
142            initial_value,
143            motes.value().as_u64(),
144            "should have equal value"
145        )
146    }
147
148    #[test]
149    fn should_be_able_to_compare_two_instances_of_motes() {
150        let left_motes = Motes::new(U512::from(1));
151        let right_motes = Motes::new(U512::from(1));
152        assert_eq!(left_motes, right_motes, "should be equal");
153        let right_motes = Motes::new(U512::from(2));
154        assert_ne!(left_motes, right_motes, "should not be equal")
155    }
156
157    #[test]
158    fn should_be_able_to_add_two_instances_of_motes() {
159        let left_motes = Motes::new(U512::from(1));
160        let right_motes = Motes::new(U512::from(1));
161        let expected_motes = Motes::new(U512::from(2));
162        assert_eq!(
163            (left_motes + right_motes),
164            expected_motes,
165            "should be equal"
166        )
167    }
168
169    #[test]
170    fn should_be_able_to_subtract_two_instances_of_motes() {
171        let left_motes = Motes::new(U512::from(1));
172        let right_motes = Motes::new(U512::from(1));
173        let expected_motes = Motes::new(U512::from(0));
174        assert_eq!(
175            (left_motes - right_motes),
176            expected_motes,
177            "should be equal"
178        )
179    }
180
181    #[test]
182    fn should_be_able_to_multiply_two_instances_of_motes() {
183        let left_motes = Motes::new(U512::from(100));
184        let right_motes = Motes::new(U512::from(10));
185        let expected_motes = Motes::new(U512::from(1000));
186        assert_eq!(
187            (left_motes * right_motes),
188            expected_motes,
189            "should be equal"
190        )
191    }
192
193    #[test]
194    fn should_be_able_to_divide_two_instances_of_motes() {
195        let left_motes = Motes::new(U512::from(1000));
196        let right_motes = Motes::new(U512::from(100));
197        let expected_motes = Motes::new(U512::from(10));
198        assert_eq!(
199            (left_motes / right_motes),
200            expected_motes,
201            "should be equal"
202        )
203    }
204
205    #[test]
206    fn should_be_able_to_convert_from_motes() {
207        let gas = Gas::new(U512::from(100));
208        let motes = Motes::from_gas(gas, 10).expect("should have value");
209        let expected_motes = Motes::new(U512::from(1000));
210        assert_eq!(motes, expected_motes, "should be equal")
211    }
212
213    #[test]
214    fn should_be_able_to_default() {
215        let motes = Motes::default();
216        let expected_motes = Motes::new(U512::from(0));
217        assert_eq!(motes, expected_motes, "should be equal")
218    }
219
220    #[test]
221    fn should_be_able_to_compare_relative_value() {
222        let left_motes = Motes::new(U512::from(100));
223        let right_motes = Motes::new(U512::from(10));
224        assert!(left_motes > right_motes, "should be gt");
225        let right_motes = Motes::new(U512::from(100));
226        assert!(left_motes >= right_motes, "should be gte");
227        assert!(left_motes <= right_motes, "should be lte");
228        let left_motes = Motes::new(U512::from(10));
229        assert!(left_motes < right_motes, "should be lt");
230    }
231
232    #[test]
233    fn should_default() {
234        let left_motes = Motes::new(U512::from(0));
235        let right_motes = Motes::default();
236        assert_eq!(left_motes, right_motes, "should be equal");
237        let u512 = U512::zero();
238        assert_eq!(left_motes.value(), u512, "should be equal");
239    }
240
241    #[test]
242    fn should_support_checked_mul_from_gas() {
243        let gas = Gas::new(U512::MAX);
244        let conv_rate = 10;
245        let maybe = Motes::from_gas(gas, conv_rate);
246        assert!(maybe.is_none(), "should be none due to overflow");
247    }
248}