// SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork use super::*; use frame_support::{assert_noop, assert_ok}; use hex_literal::hex; use snowbridge_core::{inbound::Proof, ChannelId}; use sp_keyring::AccountKeyring as Keyring; use sp_runtime::{DispatchError, TokenError}; use sp_std::convert::From; use crate::{Error, Event as InboundQueueEvent}; use crate::mock::*; #[test] fn test_submit_happy_path() { new_tester().execute_with(|| { let relayer: AccountId = Keyring::Bob.into(); let channel_sovereign = sibling_sovereign_account::(ASSET_HUB_PARAID.into()); let origin = RuntimeOrigin::signed(relayer.clone()); // Submit message let message = Message { event_log: mock_event_log(), proof: Proof { block_hash: Default::default(), tx_index: Default::default(), data: Default::default(), }, }; let initial_fund = InitialFund::get(); assert_eq!(Balances::balance(&relayer), 0); assert_eq!(Balances::balance(&channel_sovereign), initial_fund); assert_ok!(InboundQueue::submit(origin.clone(), message.clone())); expect_events(vec![InboundQueueEvent::MessageReceived { channel_id: hex!("c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539") .into(), nonce: 1, message_id: [ 27, 217, 88, 127, 46, 143, 199, 70, 236, 66, 212, 244, 85, 221, 153, 104, 175, 37, 224, 20, 140, 95, 140, 7, 27, 74, 182, 199, 77, 12, 194, 236, ], fee_burned: 110000000000, } .into()]); let delivery_cost = InboundQueue::calculate_delivery_cost(message.encode().len() as u32); assert!( Parameters::get().rewards.local < delivery_cost, "delivery cost exceeds pure reward" ); assert_eq!(Balances::balance(&relayer), delivery_cost, "relayer was rewarded"); assert!( Balances::balance(&channel_sovereign) <= initial_fund - delivery_cost, "sovereign account paid reward" ); }); } #[test] fn test_submit_xcm_invalid_channel() { new_tester().execute_with(|| { let relayer: AccountId = Keyring::Bob.into(); let origin = RuntimeOrigin::signed(relayer); // Deposit funds into sovereign account of parachain 1001 let sovereign_account = sibling_sovereign_account::(TEMPLATE_PARAID.into()); println!("account: {}", sovereign_account); let _ = Balances::mint_into(&sovereign_account, 10000); // Submit message let message = Message { event_log: mock_event_log_invalid_channel(), proof: Proof { block_hash: Default::default(), tx_index: Default::default(), data: Default::default(), }, }; assert_noop!( InboundQueue::submit(origin.clone(), message.clone()), Error::::InvalidChannel, ); }); } #[test] fn test_submit_with_invalid_gateway() { new_tester().execute_with(|| { let relayer: AccountId = Keyring::Bob.into(); let origin = RuntimeOrigin::signed(relayer); // Deposit funds into sovereign account of Asset Hub (Statemint) let sovereign_account = sibling_sovereign_account::(ASSET_HUB_PARAID.into()); let _ = Balances::mint_into(&sovereign_account, 10000); // Submit message let message = Message { event_log: mock_event_log_invalid_gateway(), proof: Proof { block_hash: Default::default(), tx_index: Default::default(), data: Default::default(), }, }; assert_noop!( InboundQueue::submit(origin.clone(), message.clone()), Error::::InvalidGateway ); }); } #[test] fn test_submit_with_invalid_nonce() { new_tester().execute_with(|| { let relayer: AccountId = Keyring::Bob.into(); let origin = RuntimeOrigin::signed(relayer); // Deposit funds into sovereign account of Asset Hub (Statemint) let sovereign_account = sibling_sovereign_account::(ASSET_HUB_PARAID.into()); let _ = Balances::mint_into(&sovereign_account, 10000); // Submit message let message = Message { event_log: mock_event_log(), proof: Proof { block_hash: Default::default(), tx_index: Default::default(), data: Default::default(), }, }; assert_ok!(InboundQueue::submit(origin.clone(), message.clone())); let nonce: u64 = >::get(ChannelId::from(hex!( "c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539" ))); assert_eq!(nonce, 1); // Submit the same again assert_noop!( InboundQueue::submit(origin.clone(), message.clone()), Error::::InvalidNonce ); }); } #[test] fn test_submit_no_funds_to_reward_relayers() { new_tester().execute_with(|| { let relayer: AccountId = Keyring::Bob.into(); let origin = RuntimeOrigin::signed(relayer); // Reset balance of sovereign_account to zero so to trigger the FundsUnavailable error let sovereign_account = sibling_sovereign_account::(ASSET_HUB_PARAID.into()); Balances::set_balance(&sovereign_account, 0); // Submit message let message = Message { event_log: mock_event_log(), proof: Proof { block_hash: Default::default(), tx_index: Default::default(), data: Default::default(), }, }; assert_noop!( InboundQueue::submit(origin.clone(), message.clone()), TokenError::FundsUnavailable ); }); } #[test] fn test_set_operating_mode() { new_tester().execute_with(|| { let relayer: AccountId = Keyring::Bob.into(); let origin = RuntimeOrigin::signed(relayer); let message = Message { event_log: mock_event_log(), proof: Proof { block_hash: Default::default(), tx_index: Default::default(), data: Default::default(), }, }; assert_ok!(InboundQueue::set_operating_mode( RuntimeOrigin::root(), snowbridge_core::BasicOperatingMode::Halted )); assert_noop!(InboundQueue::submit(origin, message), Error::::Halted); }); } #[test] fn test_set_operating_mode_root_only() { new_tester().execute_with(|| { assert_noop!( InboundQueue::set_operating_mode( RuntimeOrigin::signed(Keyring::Bob.into()), snowbridge_core::BasicOperatingMode::Halted ), DispatchError::BadOrigin ); }); }