/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 artialEq20 , Eq, P0 artialOrd0 , O0 rd0 , 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 artialEq14 , Eq, P0 artialOrd0 , O0 rd0 , 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 | | } |