From dd3753d5c9c1b4ae4d798c3cd21a0fd5c4530c15 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 14 Sep 2023 10:09:51 +0200 Subject: [PATCH 1/3] adds transfer token test --- smoketest/src/constants.rs | 2 + smoketest/src/helper.rs | 16 ++++- smoketest/tests/transfer_token.rs | 114 ++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 smoketest/tests/transfer_token.rs diff --git a/smoketest/src/constants.rs b/smoketest/src/constants.rs index a021eca908..136f5bc171 100644 --- a/smoketest/src/constants.rs +++ b/smoketest/src/constants.rs @@ -4,6 +4,7 @@ pub const ETHEREUM_API: &str = "ws://localhost:8546"; pub const ETHEREUM_HTTP_API: &str = "http://localhost:8545"; pub const BRIDGE_HUB_WS_URL: &str = "ws://127.0.0.1:11144"; pub const BRIDGE_HUB_PARA_ID: u32 = 1013; +pub const ASSET_HUB_WS_URL: &str = "ws://127.0.0.1:12144"; pub const TEMPLATE_NODE_WS_URL: &str = "ws://127.0.0.1:13144"; @@ -17,6 +18,7 @@ pub const ETHEREUM_ADDRESS: [u8; 20] = hex!("90A987B944Cb1dCcE5564e5FDeCD7a54D3d // GatewayProxy in local setup pub const GATEWAY_PROXY_CONTRACT: [u8; 20] = hex!("EDa338E4dC46038493b885327842fD3E301CaB39"); +pub const WETH_CONTRACT: [u8; 20] = hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d"); // Agent for sibling parachain 1001 pub const SIBLING_AGENT_ID: [u8; 32] = diff --git a/smoketest/src/helper.rs b/smoketest/src/helper.rs index d66f9a2e71..76e4353e9b 100644 --- a/smoketest/src/helper.rs +++ b/smoketest/src/helper.rs @@ -16,7 +16,7 @@ use std::time::Duration; use subxt::blocks::ExtrinsicEvents; use subxt::events::StaticEvent; use subxt::tx::{PairSigner, TxPayload}; -use subxt::{Config, OnlineClient, PolkadotConfig}; +use subxt::{Config, OnlineClient, PolkadotConfig, SubstrateConfig}; use templateXcm::{ v3::{junction::Junction, junctions::Junctions, multilocation::MultiLocation}, VersionedMultiLocation, VersionedXcm, @@ -36,6 +36,20 @@ impl Config for TemplateConfig { type ExtrinsicParams = ::ExtrinsicParams; } +/// Custom config that works with Statemint +pub enum AssetHubConfig {} + +impl Config for AssetHubConfig { + type Index = ::Index; + type Hash = ::Hash; + type AccountId = ::AccountId; + type Address = ::Address; + type Signature = ::Signature; + type Hasher = ::Hasher; + type Header = ::Header; + type ExtrinsicParams = ::ExtrinsicParams; +} + pub struct TestClients { pub bridge_hub_client: Box>, pub template_client: Box>, diff --git a/smoketest/tests/transfer_token.rs b/smoketest/tests/transfer_token.rs new file mode 100644 index 0000000000..207e1807ce --- /dev/null +++ b/smoketest/tests/transfer_token.rs @@ -0,0 +1,114 @@ +use ethers::{ + providers::{Provider, Ws}, + types::Address, +}; +use std::{sync::Arc, time::Duration}; +use ethers::prelude::Middleware; +use snowbridge_smoketest::contracts::weth9::WETH9; +use subxt::{ + tx::{PairSigner}, + OnlineClient, PolkadotConfig, +}; +use snowbridge_smoketest::constants::{ASSET_HUB_WS_URL, ETHEREUM_API, GATEWAY_PROXY_CONTRACT, WETH_CONTRACT}; +use sp_core::{sr25519::Pair, Pair as PairT}; +use snowbridge_smoketest::{ + contracts::weth9::{TransferFilter}, + parachains::{ + assethub::api::runtime_types::xcm::{ + v3::{ + junction::{Junction, NetworkId}, + junctions::Junctions, + multiasset::{AssetId, Fungibility, MultiAsset, MultiAssets}, + multilocation::MultiLocation, + }, + VersionedMultiAssets, VersionedMultiLocation, + }, + assethub::{self}, + }, +}; +use hex_literal::hex; +use sp_core::bytes::to_hex; +use subxt::tx::TxPayload; +use assethub::api::bridge_transfer::calls::TransactionApi; +use futures::StreamExt; +use snowbridge_smoketest::helper::{AssetHubConfig, TemplateConfig}; + +const DESTINATION_ADDRESS: [u8; 20] = hex!("44a57ee2f2FCcb85FDa2B0B18EBD0D8D2333700e"); + +#[tokio::test] +async fn transfer_token() { + let ethereum_provider = Provider::::connect(ETHEREUM_API) + .await + .unwrap() + .interval(Duration::from_millis(10u64)); + + + let ethereum_client = Arc::new(ethereum_provider); + + let weth_addr: Address = WETH_CONTRACT.into(); + let weth = WETH9::new(weth_addr, ethereum_client.clone()); + + let assethub: OnlineClient = + OnlineClient::from_url(ASSET_HUB_WS_URL).await.unwrap(); + + let keypair: Pair = Pair::from_string("//Ferdie", None).expect("cannot create keypair"); + + let signer: PairSigner = PairSigner::new(keypair); + + let amount: u128 = 1_000_000_000; + let assets = VersionedMultiAssets::V3(MultiAssets(vec![MultiAsset { + id: AssetId::Concrete(MultiLocation { + parents: 2, + interior: Junctions::X3( + Junction::GlobalConsensus(NetworkId::Ethereum { chain_id: 15 }), + Junction::AccountKey20 { network: None, key: GATEWAY_PROXY_CONTRACT.into() }, + Junction::AccountKey20 { network: None, key: WETH_CONTRACT.into() }, + ), + }), + fun: Fungibility::Fungible(amount), + }])); + + let destination = VersionedMultiLocation::V3(MultiLocation { + parents: 2, + interior: Junctions::X2( + Junction::GlobalConsensus(NetworkId::Ethereum { chain_id: 15 }), + Junction::AccountKey20 { network: None, key: DESTINATION_ADDRESS.into() }, + ), + }); + + let bridge_transfer_call = TransactionApi.transfer_asset_via_bridge(assets, destination); + + let result = assethub + .tx() + .sign_and_submit_then_watch_default(&bridge_transfer_call, &signer) + .await + .expect("send through call.") + .wait_for_finalized_success() + .await + .expect("call success"); + + println!("bridge_transfer call issued at assethub block hash {:?}", result.block_hash()); + + let wait_for_blocks = 50; + let mut stream = ethereum_client.subscribe_blocks().await.unwrap().take(wait_for_blocks); + + let mut transfer_event_found = false; + while let Some(block) = stream.next().await { + println!("Polling ethereum block {:?} for transfer event", block.number.unwrap()); + if let Ok(transfers) = + weth.event::().at_block_hash(block.hash.unwrap()).query().await + { + for transfer in transfers { + println!("Transfer event found at ethereum block {:?}", block.number.unwrap()); + assert_eq!(transfer.src, DESTINATION_ADDRESS.into()); + assert_eq!(transfer.dst, DESTINATION_ADDRESS.into()); + assert_eq!(transfer.wad, amount.into()); + transfer_event_found = true; + } + } + if transfer_event_found { + break; + } + } + assert!(transfer_event_found); +} From 9b0d3b008a1a8099b4afc38de2f14d140d768cb2 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Thu, 14 Sep 2023 11:17:35 +0000 Subject: [PATCH 2/3] assert agent id is the source --- smoketest/tests/transfer_token.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/smoketest/tests/transfer_token.rs b/smoketest/tests/transfer_token.rs index 207e1807ce..9be094364d 100644 --- a/smoketest/tests/transfer_token.rs +++ b/smoketest/tests/transfer_token.rs @@ -4,7 +4,7 @@ use ethers::{ }; use std::{sync::Arc, time::Duration}; use ethers::prelude::Middleware; -use snowbridge_smoketest::contracts::weth9::WETH9; +use snowbridge_smoketest::contracts::{i_gateway::IGateway, weth9::WETH9}; use subxt::{ tx::{PairSigner}, OnlineClient, PolkadotConfig, @@ -48,6 +48,12 @@ async fn transfer_token() { let weth_addr: Address = WETH_CONTRACT.into(); let weth = WETH9::new(weth_addr, ethereum_client.clone()); + let gateway_addr: Address = GATEWAY_PROXY_CONTRACT.into(); + let gateway = IGateway::new(GATEWAY_PROXY_CONTRACT, ethereum_client.clone()); + let agent_src = gateway.agent_of(todo!()) + .await + .expect("could not get agent address"); + let assethub: OnlineClient = OnlineClient::from_url(ASSET_HUB_WS_URL).await.unwrap(); @@ -100,7 +106,7 @@ async fn transfer_token() { { for transfer in transfers { println!("Transfer event found at ethereum block {:?}", block.number.unwrap()); - assert_eq!(transfer.src, DESTINATION_ADDRESS.into()); + assert_eq!(transfer.src, agent_src.into()); assert_eq!(transfer.dst, DESTINATION_ADDRESS.into()); assert_eq!(transfer.wad, amount.into()); transfer_event_found = true; From b8d63082f8db634e3e3fc17cf1a5f7045827c4a1 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 14 Sep 2023 14:50:38 +0200 Subject: [PATCH 3/3] complete transfer token test --- parachain/pallets/inbound-queue/src/test.rs | 26 ++++++++++----------- smoketest/src/constants.rs | 3 +++ smoketest/tests/transfer_token.rs | 11 ++++----- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/parachain/pallets/inbound-queue/src/test.rs b/parachain/pallets/inbound-queue/src/test.rs index 5786073775..b13094763b 100644 --- a/parachain/pallets/inbound-queue/src/test.rs +++ b/parachain/pallets/inbound-queue/src/test.rs @@ -22,7 +22,7 @@ use snowbridge_core::inbound::{Message, Proof}; use snowbridge_ethereum::Log; use hex_literal::hex; -use xcm::v3::{SendXcm, MultiAssets, prelude::*}; +use xcm::v3::{prelude::*, MultiAssets, SendXcm}; use crate::{self as inbound_queue, envelope::Envelope, Error, Event as InboundQueueEvent}; @@ -151,19 +151,19 @@ impl SendXcm for MockXcmSender { type Ticket = (); fn validate( - dest: &mut Option, - _: &mut Option>, - ) -> xcm::v3::SendResult { - match dest { - Some(MultiLocation { parents: _, interior }) => { - if let X1(Parachain(1001)) = interior { - return Err(XcmpSendError::NotApplicable); - } - Ok(((), MultiAssets::default())) + dest: &mut Option, + _: &mut Option>, + ) -> xcm::v3::SendResult { + match dest { + Some(MultiLocation { parents: _, interior }) => { + if let X1(Parachain(1001)) = interior { + return Err(XcmpSendError::NotApplicable) } - _ => Ok(((), MultiAssets::default())) - } + Ok(((), MultiAssets::default())) + }, + _ => Ok(((), MultiAssets::default())), } + } fn deliver(_: Self::Ticket) -> core::result::Result { Ok(H256::zero().into()) @@ -267,7 +267,7 @@ fn test_submit_happy_path() { expect_events(vec![InboundQueueEvent::MessageReceived { dest: dest_para, nonce: 1, - xcm_hash: H256::zero().into() + xcm_hash: H256::zero().into(), } .into()]); }); diff --git a/smoketest/src/constants.rs b/smoketest/src/constants.rs index 136f5bc171..d22d08e89f 100644 --- a/smoketest/src/constants.rs +++ b/smoketest/src/constants.rs @@ -23,3 +23,6 @@ pub const WETH_CONTRACT: [u8; 20] = hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A // Agent for sibling parachain 1001 pub const SIBLING_AGENT_ID: [u8; 32] = hex!("2075b9f5bc236462eb1473c9a6236c3588e33ed19ead53aa3d9c62ed941cb793"); +// Agent for asset hub parachain 1000 +pub const ASSET_HUB_AGENT_ID: [u8; 32] = + hex!("72456f48efed08af20e5b317abf8648ac66e86bb90a411d9b0b713f7364b75b4"); diff --git a/smoketest/tests/transfer_token.rs b/smoketest/tests/transfer_token.rs index 9be094364d..901a97a2b0 100644 --- a/smoketest/tests/transfer_token.rs +++ b/smoketest/tests/transfer_token.rs @@ -7,9 +7,9 @@ use ethers::prelude::Middleware; use snowbridge_smoketest::contracts::{i_gateway::IGateway, weth9::WETH9}; use subxt::{ tx::{PairSigner}, - OnlineClient, PolkadotConfig, + OnlineClient, }; -use snowbridge_smoketest::constants::{ASSET_HUB_WS_URL, ETHEREUM_API, GATEWAY_PROXY_CONTRACT, WETH_CONTRACT}; +use snowbridge_smoketest::constants::{ASSET_HUB_WS_URL, ETHEREUM_API, GATEWAY_PROXY_CONTRACT, WETH_CONTRACT, ASSET_HUB_AGENT_ID}; use sp_core::{sr25519::Pair, Pair as PairT}; use snowbridge_smoketest::{ contracts::weth9::{TransferFilter}, @@ -27,11 +27,9 @@ use snowbridge_smoketest::{ }, }; use hex_literal::hex; -use sp_core::bytes::to_hex; -use subxt::tx::TxPayload; use assethub::api::bridge_transfer::calls::TransactionApi; use futures::StreamExt; -use snowbridge_smoketest::helper::{AssetHubConfig, TemplateConfig}; +use snowbridge_smoketest::helper::AssetHubConfig; const DESTINATION_ADDRESS: [u8; 20] = hex!("44a57ee2f2FCcb85FDa2B0B18EBD0D8D2333700e"); @@ -48,9 +46,8 @@ async fn transfer_token() { let weth_addr: Address = WETH_CONTRACT.into(); let weth = WETH9::new(weth_addr, ethereum_client.clone()); - let gateway_addr: Address = GATEWAY_PROXY_CONTRACT.into(); let gateway = IGateway::new(GATEWAY_PROXY_CONTRACT, ethereum_client.clone()); - let agent_src = gateway.agent_of(todo!()) + let agent_src = gateway.agent_of(ASSET_HUB_AGENT_ID) .await .expect("could not get agent address");