1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
#![cfg(test)]
18

            
19
use {
20
    dancebox_runtime::{OriginCaller, PolkadotXcm},
21
    dancebox_runtime_test_utils::*,
22
    frame_support::assert_ok,
23
    xcm::latest::prelude::*,
24
    xcm::{VersionedAssets, VersionedLocation},
25
};
26

            
27
#[test]
28
1
fn test_dry_run_call_transfer_assets() {
29
    // Rewrite of test `test-xcm-dry-run-api.ts` in rust to debug a failure that only happened in typescript tests.
30
    // The fix was to create a new block, because this runtime api does no longer work when the current block is 0.
31
1
    ExtBuilder::default()
32
1
        .with_balances(vec![
33
1
            // Alice gets tokens for her tests
34
1
            (AccountId::from(ALICE), 1_000_000 * UNIT),
35
1
        ])
36
1
        .build()
37
1
        .execute_with(|| {
38
1
            sp_tracing::try_init_simple();
39

            
40
            // This must be set because in typescript dev tests the xcm version is already set, while
41
            // in rust integration tests it is not set and that gives error SendError
42
1
            assert_ok!(PolkadotXcm::force_default_xcm_version(
43
1
                root_origin(),
44
1
                Some(4u32)
45
            ));
46

            
47
            // Similar to the above test but with different expectations
48
1
            let balances_pallet_index = 10u8; // Balances pallet index in dancebox runtime
49
1
            let random_receiver: [u8; 32] = [0x22; 32];
50

            
51
1
            let versioned_beneficiary = VersionedLocation::V4(xcm::v4::Location::new(
52
1
                0,
53
1
                [xcm::v4::Junction::AccountId32 {
54
1
                    network: None,
55
1
                    id: random_receiver,
56
1
                }],
57
1
            ));
58

            
59
1
            let versioned_assets =
60
1
                VersionedAssets::V4(xcm::v4::Assets::from(vec![xcm::v4::Asset {
61
1
                    id: xcm::v4::AssetId(xcm::v4::Location::new(
62
1
                        0,
63
1
                        [xcm::v4::Junction::PalletInstance(balances_pallet_index)],
64
1
                    )),
65
1
                    fun: xcm::v4::Fungibility::Fungible(100_000_000_000_000u128), // 0.1 UNIT
66
1
                }]));
67

            
68
1
            let dest = VersionedLocation::V4(xcm::v4::Location::new(1, xcm::v4::Junctions::Here));
69

            
70
1
            let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::transfer_assets {
71
1
                dest: Box::new(dest),
72
1
                beneficiary: Box::new(versioned_beneficiary),
73
1
                assets: Box::new(versioned_assets),
74
1
                fee_asset_item: 0,
75
1
                weight_limit: WeightLimit::Unlimited,
76
1
            });
77

            
78
1
            let origin_caller =
79
1
                OriginCaller::system(frame_system::RawOrigin::Signed(AccountId::from(ALICE)));
80
1
            let xcm_version = 4;
81

            
82
            // Ensure the actual call works, without the dry_run_call.
83
            // This works because we are currently inside block 1, after on_initialize.
84
            /*
85
            use sp_runtime::traits::Dispatchable;
86
            use dancebox_runtime::RuntimeOrigin;
87
            call.dispatch(RuntimeOrigin::signed(AccountId::from(ALICE))).unwrap();
88
             */
89

            
90
            // Execute the dry run using PolkadotXcm directly
91
1
            let result = PolkadotXcm::dry_run_call::<
92
1
                Runtime,
93
1
                dancebox_runtime::xcm_config::XcmRouter,
94
1
                OriginCaller,
95
1
                RuntimeCall,
96
1
            >(origin_caller, call, xcm_version);
97

            
98
            // This also works because we are currently inside block 1, after on_initialize
99
            // The typescript test fails because it runs the dryRunCall after block 0 on_finalize, and
100
            // something is missing there that it makes the test fail
101
1
            match result {
102
1
                Ok(dry_run_effects) => {
103
1
                    assert!(dry_run_effects.execution_result.is_ok());
104
                }
105
                Err(e) => {
106
                    panic!("DryRun API call failed: {:?}", e);
107
                }
108
            }
109
1
        });
110
1
}