1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use core::{
  ops::{Add, Sub, Mul},
  fmt::Debug,
};

#[cfg(feature = "std")]
use zeroize::Zeroize;

#[cfg(feature = "borsh")]
use borsh::{BorshSerialize, BorshDeserialize};
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};

use scale::{Encode, Decode, MaxEncodedLen};
use scale_info::TypeInfo;

/// The type used for amounts within Substrate.
// Distinct from Amount due to Substrate's requirements on this type.
// While Amount could have all the necessary traits implemented, not only are they many, it'd make
// Amount a large type with a variety of misc functions.
// The current type's minimalism sets clear bounds on usage.
pub type SubstrateAmount = u64;
/// The type used for amounts.
#[derive(
  Clone, Copy, PartialEq, Eq, PartialOrd, Debug, Encode, Decode, MaxEncodedLen, TypeInfo,
)]
#[cfg_attr(feature = "std", derive(Zeroize))]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Amount(pub SubstrateAmount);

// TODO: these impl shouldn't panic and return error to be dealt with.
// Otherwise we might have a panic that stops the network.
impl Add for Amount {
  type Output = Amount;
  fn add(self, other: Amount) -> Amount {
    // Explicitly use checked_add so even if range checks are disabled, this is still checked
    Amount(self.0.checked_add(other.0).unwrap())
  }
}

impl Sub for Amount {
  type Output = Amount;
  fn sub(self, other: Amount) -> Amount {
    Amount(self.0.checked_sub(other.0).unwrap())
  }
}

impl Mul for Amount {
  type Output = Amount;
  fn mul(self, other: Amount) -> Amount {
    Amount(self.0.checked_mul(other.0).unwrap())
  }
}