Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

connectors: Wrapped token lookup #1393

Merged
merged 28 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
17c2853
asset-registry: Add `transferability` property
NunoAlexandre May 1, 2023
a172a75
Merge branch 'main' into feat/connectors-metadata
NunoAlexandre Jun 7, 2023
64bb64a
wip: Move xcm metadata to Transferability::Xcm and All
NunoAlexandre Jun 7, 2023
5ccc7d3
fixup
NunoAlexandre Jun 7, 2023
cf627d6
Add CrossChainTransferability::None and set as default
NunoAlexandre Jun 7, 2023
85175ed
fmt
NunoAlexandre Jun 7, 2023
5ed78f0
Fix e2e tests
NunoAlexandre Jun 7, 2023
1c2e548
altair: Add CrossChainTransferabilityMigration
NunoAlexandre Jun 7, 2023
8a70101
Merge branch 'main' into feat/connectors-metadata
NunoAlexandre Jun 7, 2023
bda728e
Merge branch 'main' into feat/connectors-metadata
NunoAlexandre Jun 8, 2023
cf56bff
Merge branch 'main' into feat/connectors-metadata
NunoAlexandre Jun 8, 2023
36bc975
cfg-traits: Add AssetLocator trait
NunoAlexandre Jun 8, 2023
fafee80
cfg-types: Move `EVMChainId` to crate root
NunoAlexandre Jun 8, 2023
34f7453
cfg-types: Add AssetLocation enum type
NunoAlexandre Jun 8, 2023
c7481bb
Add ConnectorsWrappedToken and test conversion identity
NunoAlexandre Jun 8, 2023
f42a6e6
Drop old approach ✨ 🧹
NunoAlexandre Jun 8, 2023
0f2088b
clippy
NunoAlexandre Jun 9, 2023
e88c7ee
wip: ConnectorsWrappedTokenConvert
NunoAlexandre Jun 12, 2023
8d94947
Impl Token to MultiLocation conversion
NunoAlexandre Jun 12, 2023
0d116d4
fmt
NunoAlexandre Jun 12, 2023
5dc6889
Test ConnectorsWrappedToken conversions
NunoAlexandre Jun 12, 2023
850de3b
fmt
NunoAlexandre Jun 12, 2023
82b9737
Add mod test
NunoAlexandre Jun 12, 2023
8f71ff2
Self review
NunoAlexandre Jun 12, 2023
cedf48b
Fix cargo doc
NunoAlexandre Jun 13, 2023
104d82d
fmt
NunoAlexandre Jun 13, 2023
3c466ff
Merge remote-tracking branch 'origin/main' into evm-token-lookup
NunoAlexandre Jun 13, 2023
a464b1e
Doc review comment
NunoAlexandre Jun 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions libs/primitives/src/lib.rs
Expand Up @@ -175,6 +175,9 @@ pub mod types {

/// A representation of a loan identifier
pub type LoanId = u64;

/// The type for indexing pallets on a Substrate runtime
pub type PalletIndex = u8;
}

/// Common constants for all runtimes
Expand Down
2 changes: 1 addition & 1 deletion libs/traits/src/lib.rs
Expand Up @@ -634,7 +634,7 @@ pub trait TransferAllowance<AccountId> {
type CurrencyId;
type Location: Member + Debug + Eq + PartialEq + TypeInfo + Encode + Decode + MaxEncodedLen;
/// Determines whether the `send` account is allowed to make a transfer to
/// the `recieve` loocation with `currency` type currency. Returns result
/// the `receive` location with `currency` type currency. Returns result
/// wrapped bool for whether allowance is allowed.
fn allowance(
send: AccountId,
Expand Down
4 changes: 1 addition & 3 deletions libs/types/src/domain_address.rs
Expand Up @@ -15,9 +15,7 @@ use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_core::TypeId;

/// The EVM Chain ID
/// The type should accomodate all chain ids listed on https://chainlist.org/.
type EVMChainId = u64;
use crate::EVMChainId;

/// A Domain is a chain or network we can send a Connectors message to.
/// The domain indices need to match those used in the EVM contracts and these
Expand Down
4 changes: 4 additions & 0 deletions libs/types/src/lib.rs
Expand Up @@ -30,3 +30,7 @@ pub mod permissions;
pub mod time;
pub mod tokens;
pub mod xcm;

/// The EVM Chain ID
/// The type should accomodate all chain ids listed on https://chainlist.org/.
type EVMChainId = u64;
21 changes: 20 additions & 1 deletion libs/types/src/tokens.rs
Expand Up @@ -21,7 +21,7 @@ use scale_info::TypeInfo;
use serde::{Deserialize, Serialize};
use sp_runtime::{traits::Get, DispatchError, TokenError};

use crate::xcm::XcmMetadata;
use crate::{xcm::XcmMetadata, EVMChainId};

#[derive(
Clone,
Expand Down Expand Up @@ -255,6 +255,25 @@ impl CrossChainTransferability {
}
}

/// Connectors-wrapped tokens
///
/// Currently, Connectors are only deployed on EVM-based chains and therefore
/// we only support EVM tokens. In the far future, we might support wrapped
/// tokens from other chains such as Cosmos based ones.
#[derive(
Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, Encode, Decode, TypeInfo, MaxEncodedLen,
)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum ConnectorsWrappedToken {
NunoAlexandre marked this conversation as resolved.
Show resolved Hide resolved
/// An EVM-native token
EVM {
/// The EVM chain id where the token is deployed
chain_id: EVMChainId,
/// The token contract address
address: [u8; 20],
},
}

#[cfg(test)]
mod tests {
use frame_support::parameter_types;
Expand Down
149 changes: 149 additions & 0 deletions runtime/common/src/lib.rs
Expand Up @@ -453,3 +453,152 @@ pub mod changes {
}
}
}

pub mod connectors {
use cfg_primitives::types::PalletIndex;
use cfg_types::tokens::ConnectorsWrappedToken;
use sp_core::Get;
use sp_runtime::traits::Convert;
use sp_std::marker::PhantomData;
use xcm::{
latest::{MultiLocation, NetworkId},
prelude::{AccountKey20, GlobalConsensus, PalletInstance, X3},
};

/// This type offers conversions between the xcm MultiLocation and our
/// ConnectorsWrappedToken types. This conversion is runtime-dependant, as
/// it needs to include the Connectors pallet index on the target runtime.
/// Therefore, we have `Index` as a generic type param that we use to unwrap
/// said pallet index and correctly convert between the two types.
pub struct ConnectorsWrappedTokenConvert<Index: Get<PalletIndex>>(PhantomData<Index>);

impl<Index: Get<PalletIndex>> Convert<MultiLocation, Result<ConnectorsWrappedToken, ()>>
for ConnectorsWrappedTokenConvert<Index>
{
fn convert(location: MultiLocation) -> Result<ConnectorsWrappedToken, ()> {
match location {
MultiLocation {
parents: 0,
interior:
X3(
PalletInstance(pallet_instance),
mustermeiszer marked this conversation as resolved.
Show resolved Hide resolved
GlobalConsensus(NetworkId::Ethereum { chain_id }),
AccountKey20 {
network: None,
key: address,
},
),
} if pallet_instance == Index::get() => Ok(ConnectorsWrappedToken::EVM { chain_id, address }),
_ => Err(()),
}
}
}

impl<Index: Get<PalletIndex>> Convert<ConnectorsWrappedToken, MultiLocation>
for ConnectorsWrappedTokenConvert<Index>
{
fn convert(token: ConnectorsWrappedToken) -> MultiLocation {
match token {
ConnectorsWrappedToken::EVM { chain_id, address } => MultiLocation {
parents: 0,
interior: X3(
PalletInstance(Index::get()),
GlobalConsensus(NetworkId::Ethereum { chain_id }),
AccountKey20 {
network: None,
key: address,
},
),
},
}
}
}

#[cfg(test)]
mod test {
use sp_core::parameter_types;
use sp_runtime::traits::Convert;

use super::*;

#[test]
/// Verify that converting a ConnectorsWrappedToken to MultiLocation and
/// back results in the same original value.
fn connectors_wrapped_token_convert_identity() {
parameter_types! {
const Index: PalletIndex = 108;
}

const CHAIN_ID: u64 = 123;
const ADDRESS: [u8; 20] = [9; 20];

let wrapped_token = ConnectorsWrappedToken::EVM {
chain_id: CHAIN_ID,
address: ADDRESS,
};

let location = MultiLocation {
parents: 0,
interior: X3(
PalletInstance(Index::get()),
GlobalConsensus(NetworkId::Ethereum { chain_id: CHAIN_ID }),
AccountKey20 {
network: None,
key: ADDRESS,
},
),
};

assert_eq!(
<ConnectorsWrappedTokenConvert<Index> as Convert<
ConnectorsWrappedToken,
MultiLocation,
>>::convert(wrapped_token),
location
);

assert_eq!(
<ConnectorsWrappedTokenConvert<Index> as Convert<
MultiLocation,
Result<ConnectorsWrappedToken, ()>,
>>::convert(location),
Ok(wrapped_token)
);
}

/// Verify that ConnectorsWrappedTokenConvert will fail to convert a
/// location to a ConnectorsWrappedToken if the PalletInstance value
/// doesn't match the Index generic param, i.e, fail if the token
/// doesn't appear to be under the Connectors pallet and thus be a
/// connectors wrapped token.
#[test]
fn connectors_wrapped_token_convert_fail() {
parameter_types! {
const Index: PalletIndex = 108;
const WrongIndex: PalletIndex = 72;
}
const CHAIN_ID: u64 = 123;
const ADDRESS: [u8; 20] = [9; 20];

let location = MultiLocation {
parents: 0,
interior: X3(
PalletInstance(WrongIndex::get()),
GlobalConsensus(NetworkId::Ethereum { chain_id: CHAIN_ID }),
AccountKey20 {
network: None,
key: ADDRESS,
},
),
};

assert_eq!(
<ConnectorsWrappedTokenConvert<Index> as Convert<
MultiLocation,
Result<ConnectorsWrappedToken, ()>,
>>::convert(location),
Err(())
);
}
}
}