Coverage Report

Created: 2022-11-10 19:56

/home/runner/work/creditcoin/creditcoin/pallets/creditcoin/src/types/platform.rs
Line
Count
Source (jump to first uncovered line)
1
use core::convert::TryFrom;
2
3
use codec::{Decode, Encode, MaxEncodedLen};
4
use frame_support::{traits::ConstU32, BoundedVec, RuntimeDebug};
5
use scale_info::TypeInfo;
6
use sp_runtime::traits::Hash as HashT;
7
use strum::EnumCount;
8
9
use crate::{Config, ExternalAddress, LegacyTransferKind};
10
use alloc::string::ToString;
11
use sp_std::borrow::Cow;
12
13
// as of EIP-155 the max chain ID is 9,223,372,036,854,775,771 which fits well within a u64
14
#[derive(
15
  Copy,
16
1.08k
  Clone,
17
22
  RuntimeDebug,
18
576
  PartialEq,
19
  Eq,
20
0
  PartialOrd,
21
0
  Ord,
22
  Encode,
23
1.21k
  Decode,
24
1
  TypeInfo,
25
16
  MaxEncodedLen,
26
1
)]
27
#[repr(transparent)]
28
2.03k
pub struct EvmChainId(#[codec(compact)] u64);
29
30
impl From<u64> for EvmChainId {
31
10
  fn from(value: u64) -> Self {
32
10
    EvmChainId(value)
33
10
  }
34
}
35
36
impl EvmChainId {
37
3
  pub const fn new(value: u64) -> Self {
38
3
    EvmChainId(value)
39
3
  }
40
5
  pub fn as_u64(self) -> u64 {
41
5
    self.0
42
5
  }
43
44
  pub const ETHEREUM: EvmChainId = EvmChainId::new(1);
45
  pub const RINKEBY: EvmChainId = EvmChainId::new(4);
46
  pub const LUNIVERSE_TESTNET: EvmChainId = EvmChainId::new(949790);
47
  pub const LUNIVERSE: EvmChainId = EvmChainId::new(59496427);
48
}
49
50
#[derive(
51
1.21k
  
Clone1.07k
,
RuntimeDebug21
,
PartialEq569
, Eq,
PartialOrd0
,
Ord0
, Encode, Decode,
TypeInfo1
,
MaxEncodedLen15
,
52
1
)]
53
pub struct EvmInfo {
54
971
  pub chain_id: EvmChainId,
55
}
56
57
impl EvmInfo {
58
  pub const ETHEREUM: EvmInfo = EvmInfo { chain_id: EvmChainId::ETHEREUM };
59
  pub const RINKEBY: EvmInfo = EvmInfo { chain_id: EvmChainId::RINKEBY };
60
  pub const LUNIVERSE_TESTNET: EvmInfo = EvmInfo { chain_id: EvmChainId::LUNIVERSE_TESTNET };
61
  pub const LUNIVERSE: EvmInfo = EvmInfo { chain_id: EvmChainId::LUNIVERSE };
62
}
63
64
#[derive(
65
843
  
Clone578
,
RuntimeDebu15
g15
,
PartialEq549
, Eq,
PartialOrd0
,
Encod701
e701
, Decode,
T1
ypeInfo,
MaxEncodedLen10
,
66
1
)]
67
pub enum Blockchain {
68
  Evm(EvmInfo),
69
}
70
71
impl Blockchain {
72
0
  pub const fn evm(chain_id: EvmChainId) -> Blockchain {
73
0
    Blockchain::Evm(EvmInfo { chain_id })
74
0
  }
75
  // Chain IDs from chainlist.org and Gluwa's internal luniverse documentation
76
  pub const ETHEREUM: Blockchain = Blockchain::evm(EvmChainId::ETHEREUM);
77
  pub const RINKEBY: Blockchain = Blockchain::evm(EvmChainId::RINKEBY);
78
  pub const LUNIVERSE_TESTNET: Blockchain = Blockchain::evm(EvmChainId::LUNIVERSE_TESTNET);
79
  pub const LUNIVERSE: Blockchain = Blockchain::evm(EvmChainId::LUNIVERSE);
80
81
2.16k
  pub fn as_bytes(&self) -> Cow<'_, [u8]> {
82
2.16k
    match *self {
83
215
      Blockchain::ETHEREUM => Cow::Borrowed(b"ethereum"),
84
1.93k
      Blockchain::RINKEBY => Cow::Borrowed(b"rinkeby"),
85
10
      Blockchain::LUNIVERSE_TESTNET | Blockchain::LUNIVERSE => Cow::Borrowed(b"luniverse"),
86
2
      Blockchain::Evm(EvmInfo { chain_id }) => {
87
2
        let s = chain_id.as_u64().to_string();
88
2
        let mut buf = b"evm-".to_vec();
89
2
        buf.extend(s.as_bytes());
90
2
        Cow::Owned(buf)
91
      },
92
    }
93
2.16k
  }
94
95
17
  pub fn supports(&self, kind: &LegacyTransferKind) -> bool {
96
17
    match (self, kind) {
97
      (
98
        &Blockchain::ETHEREUM
99
        | &Blockchain::RINKEBY
100
        | &Blockchain::LUNIVERSE
101
        | &Blockchain::LUNIVERSE_TESTNET,
102
17
        LegacyTransferKind::Erc20(_)
103
17
        | LegacyTransferKind::Ethless(_)
104
17
        | LegacyTransferKind::Native,
105
13
      ) => true,
106
4
      (_, _) => false,
107
    }
108
17
  }
109
}
110
111
#[derive(
112
  Copy,
113
76
  Clone,
114
16
  RuntimeDebug,
115
101
  PartialEq,
116
  Eq,
117
0
  PartialOrd,
118
0
  Ord,
119
408
  Encode,
120
422
  Decode,
121
2
  TypeInfo,
122
12
  MaxEncodedLen,
123
1
  EnumCount,
124
)]
125
pub enum EvmTransferKind {
126
  Erc20,
127
  Ethless,
128
}
129
130
pub type EvmSupportedTransferKinds =
131
  BoundedVec<EvmTransferKind, ConstU32<{ EvmTransferKind::COUNT as u32 }>>;
132
133
#[derive(
134
367
  
Clone202
,
RuntimeDebu6
g6
,
P20
artialE
q20
, Eq,
P0
artialOr
d0
,
O0
r
d0
,
Encod270
e270
, Decode,
T1
ypeInfo,
MaxEncodedLen5
,
135
1
)]
136
pub enum EvmCurrencyType {
137
  SmartContract(ExternalAddress, EvmSupportedTransferKinds),
138
}
139
140
#[derive(
141
366
  
Clone200
,
RuntimeDebu5
g5
,
P14
artialE
q14
, Eq,
P0
artialOr
d0
,
O0
r
d0
,
Encod269
e269
, Decode,
T1
ypeInfo,
MaxEncodedLen4
,
142
1
)]
143
pub enum Currency {
144
  Evm(EvmCurrencyType, EvmInfo),
145
}
146
147
impl Currency {
148
295
  pub fn blockchain(&self) -> Blockchain {
149
295
    match self {
150
295
      Currency::Evm(_, info) => Blockchain::Evm(info.clone()),
151
295
    }
152
295
  }
153
48
  pub fn supports(&self, kind: &TransferKind) -> bool {
154
48
    match (self, kind) {
155
48
      (Currency::Evm(currency, _), TransferKind::Evm(kind)) => match currency {
156
48
        EvmCurrencyType::SmartContract(_, supported) => supported.contains(kind),
157
48
      },
158
48
    }
159
48
  }
160
161
480
  pub fn to_id<T: Config>(&self) -> CurrencyId<T::Hash> {
162
480
    CurrencyId::new::<T>(self)
163
480
  }
164
}
165
166
#[derive(
167
137
  
Clone74
,
RuntimeDebu9
g9
,
PartialEq27
, Eq,
PartialOrd0
, Encode,
D54
ecode,
T1
ypeInfo,
MaxEncodedLen6
,
168
1
)]
169
pub enum TransferKind {
170
  Evm(EvmTransferKind),
171
}
172
173
impl From<EvmTransferKind> for TransferKind {
174
36
  fn from(kind: EvmTransferKind) -> Self {
175
36
    Self::Evm(kind)
176
36
  }
177
}
178
179
impl TryFrom<super::LegacyTransferKind> for TransferKind {
180
  type Error = ();
181
3
  fn try_from(legacy: super::LegacyTransferKind) -> Result<Self, Self::Error> {
182
3
    match legacy {
183
3
      LegacyTransferKind::Ethless(_) => Ok(TransferKind::Evm(EvmTransferKind::Ethless)),
184
0
      _ => Err(()),
185
    }
186
3
  }
187
}
188
189
#[derive(
190
1.11k
  
Clone732
,
RuntimeDebug7
,
PartialEq60
, Eq,
PartialOrd0
, Encode, Decode,
TypeInfo1
,
MaxEncodedLen7
,
Or0
d,
191
)]
192
1.86k
pub struct CurrencyId<Hash>(Hash);
193
194
impl<H> CurrencyId<H> {
195
1.06k
  pub fn new<T>(currency: &Currency) -> Self
196
1.06k
  where
197
1.06k
    T: frame_system::Config,
198
1.06k
    <T as frame_system::Config>::Hashing: sp_runtime::traits::Hash<Output = H>,
199
1.06k
  {
200
1.06k
    match currency {
201
1.06k
      Currency::Evm(EvmCurrencyType::SmartContract(address, _), evm_info) => {
202
1.06k
        let encoded = (address, evm_info.chain_id).encode();
203
1.06k
        CurrencyId(T::Hashing::hash(&encoded))
204
1.06k
      },
205
1.06k
    }
206
1.06k
  }
207
}
208
209
impl<H> CurrencyId<H>
210
where
211
  H: Default,
212
{
213
11
  pub fn placeholder() -> Self {
214
11
    Self(H::default())
215
11
  }
216
}
217
218
impl<H> CurrencyId<H>
219
where
220
  H: Default + PartialEq,
221
{
222
5
  pub fn is_placeholder(&self) -> bool {
223
5
    let default = CurrencyId(H::default());
224
5
225
5
    self == &default
226
5
  }
227
}
228
229
#[cfg(test)]
230
mod test {
231
  use super::*;
232
233
1
  #[test]
234
1
  fn blockchain_as_bytes_back_compat() {
235
1
    assert_eq!(Blockchain::ETHEREUM.as_bytes(), b"ethereum".as_slice());
236
1
    assert_eq!(Blockchain::RINKEBY.as_bytes(), b"rinkeby".as_slice());
237
1
    assert_eq!(Blockchain::LUNIVERSE.as_bytes(), b"luniverse".as_slice());
238
1
    assert_eq!(Blockchain::LUNIVERSE_TESTNET.as_bytes(), b"luniverse".as_slice());
239
1
  }
240
241
1
  #[test]
242
1
  fn blockchain_as_bytes_evm_chain() {
243
1
    assert_eq!(
244
1
      Blockchain::Evm(EvmInfo { chain_id: EvmChainId::new(31337) }).as_bytes(),
245
1
      b"evm-31337".as_slice()
246
1
    );
247
1
  }
248
}