snowbridge_core/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
3//! # Core
4//!
5//! Common traits and types
6#![cfg_attr(not(feature = "std"), no_std)]
7
8#[cfg(test)]
9mod tests;
10
11pub mod inbound;
12pub mod location;
13pub mod operating_mode;
14pub mod outbound;
15pub mod pricing;
16pub mod ringbuffer;
17
18pub use location::{AgentId, AgentIdOf, TokenId, TokenIdOf};
19pub use polkadot_parachain_primitives::primitives::{
20	Id as ParaId, IsSystem, Sibling as SiblingParaId,
21};
22pub use ringbuffer::{RingBufferMap, RingBufferMapImpl};
23pub use sp_core::U256;
24
25use codec::{Decode, Encode, MaxEncodedLen};
26use frame_support::{traits::Contains, BoundedVec};
27use hex_literal::hex;
28use scale_info::TypeInfo;
29use sp_core::{ConstU32, H256};
30use sp_io::hashing::keccak_256;
31use sp_runtime::{traits::AccountIdConversion, RuntimeDebug};
32use sp_std::prelude::*;
33use xcm::prelude::{Junction::Parachain, Location};
34
35/// The ID of an agent contract
36pub use operating_mode::BasicOperatingMode;
37
38pub use pricing::{PricingParameters, Rewards};
39
40pub fn sibling_sovereign_account<T>(para_id: ParaId) -> T::AccountId
41where
42	T: frame_system::Config,
43{
44	SiblingParaId::from(para_id).into_account_truncating()
45}
46
47pub struct AllowSiblingsOnly;
48impl Contains<Location> for AllowSiblingsOnly {
49	fn contains(location: &Location) -> bool {
50		matches!(location.unpack(), (1, [Parachain(_)]))
51	}
52}
53
54pub fn gwei(x: u128) -> U256 {
55	U256::from(1_000_000_000u128).saturating_mul(x.into())
56}
57
58pub fn meth(x: u128) -> U256 {
59	U256::from(1_000_000_000_000_000u128).saturating_mul(x.into())
60}
61
62pub fn eth(x: u128) -> U256 {
63	U256::from(1_000_000_000_000_000_000u128).saturating_mul(x.into())
64}
65
66pub const ROC: u128 = 1_000_000_000_000;
67
68/// Identifier for a message channel
69#[derive(
70	Clone, Copy, Encode, Decode, PartialEq, Eq, Default, RuntimeDebug, MaxEncodedLen, TypeInfo,
71)]
72pub struct ChannelId([u8; 32]);
73
74/// Deterministically derive a ChannelId for a sibling parachain
75/// Generator: keccak256("para" + big_endian_bytes(para_id))
76///
77/// The equivalent generator on the Solidity side is in
78/// contracts/src/Types.sol:into().
79fn derive_channel_id_for_sibling(para_id: ParaId) -> ChannelId {
80	let para_id: u32 = para_id.into();
81	let para_id_bytes: [u8; 4] = para_id.to_be_bytes();
82	let prefix: [u8; 4] = *b"para";
83	let preimage: Vec<u8> = prefix.into_iter().chain(para_id_bytes).collect();
84	keccak_256(&preimage).into()
85}
86
87impl ChannelId {
88	pub const fn new(id: [u8; 32]) -> Self {
89		ChannelId(id)
90	}
91}
92
93impl From<ParaId> for ChannelId {
94	fn from(value: ParaId) -> Self {
95		derive_channel_id_for_sibling(value)
96	}
97}
98
99impl From<[u8; 32]> for ChannelId {
100	fn from(value: [u8; 32]) -> Self {
101		ChannelId(value)
102	}
103}
104
105impl From<ChannelId> for [u8; 32] {
106	fn from(value: ChannelId) -> Self {
107		value.0
108	}
109}
110
111impl<'a> From<&'a [u8; 32]> for ChannelId {
112	fn from(value: &'a [u8; 32]) -> Self {
113		ChannelId(*value)
114	}
115}
116
117impl From<H256> for ChannelId {
118	fn from(value: H256) -> Self {
119		ChannelId(value.into())
120	}
121}
122
123impl AsRef<[u8]> for ChannelId {
124	fn as_ref(&self) -> &[u8] {
125		&self.0
126	}
127}
128
129#[derive(Clone, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)]
130pub struct Channel {
131	/// ID of the agent contract deployed on Ethereum
132	pub agent_id: AgentId,
133	/// ID of the parachain who will receive or send messages using this channel
134	pub para_id: ParaId,
135}
136
137pub trait StaticLookup {
138	/// Type to lookup from.
139	type Source;
140	/// Type to lookup into.
141	type Target;
142	/// Attempt a lookup.
143	fn lookup(s: Self::Source) -> Option<Self::Target>;
144}
145
146/// Channel for high-priority governance commands
147pub const PRIMARY_GOVERNANCE_CHANNEL: ChannelId =
148	ChannelId::new(hex!("0000000000000000000000000000000000000000000000000000000000000001"));
149
150/// Channel for lower-priority governance commands
151pub const SECONDARY_GOVERNANCE_CHANNEL: ChannelId =
152	ChannelId::new(hex!("0000000000000000000000000000000000000000000000000000000000000002"));
153
154/// Metadata to include in the instantiated ERC20 token contract
155#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
156pub struct AssetMetadata {
157	pub name: BoundedVec<u8, ConstU32<METADATA_FIELD_MAX_LEN>>,
158	pub symbol: BoundedVec<u8, ConstU32<METADATA_FIELD_MAX_LEN>>,
159	pub decimals: u8,
160}
161
162#[cfg(any(test, feature = "std", feature = "runtime-benchmarks"))]
163impl Default for AssetMetadata {
164	fn default() -> Self {
165		AssetMetadata {
166			name: BoundedVec::truncate_from(vec![]),
167			symbol: BoundedVec::truncate_from(vec![]),
168			decimals: 0,
169		}
170	}
171}
172
173/// Maximum length of a string field in ERC20 token metada
174const METADATA_FIELD_MAX_LEN: u32 = 32;