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_attr(not(feature = "std"), no_std)]
18

            
19
use frame_support::traits::Get;
20
use xcm::latest::prelude::*;
21

            
22
pub use dp_xcm_reserve::NativeAssetReserve;
23

            
24
/// Filter to ensure an ETH asset is coming from a trusted Ethereum location.
25
pub struct EthereumAssetReserve<EthereumLocation, EthereumNetwork>(
26
    core::marker::PhantomData<(EthereumLocation, EthereumNetwork)>,
27
);
28
impl<EthereumLocation, EthereumNetwork> frame_support::traits::ContainsPair<Asset, Location>
29
    for EthereumAssetReserve<EthereumLocation, EthereumNetwork>
30
where
31
    EthereumLocation: Get<Location>,
32
    EthereumNetwork: Get<NetworkId>,
33
{
34
87
    fn contains(asset: &Asset, origin: &Location) -> bool {
35
87
        log::trace!(target: "xcm::contains", "EthereumAssetReserve asset: {:?}, origin: {:?}", asset, origin);
36
87
        if *origin != EthereumLocation::get() {
37
4
            return false;
38
83
        }
39
83
        matches!((asset.id.0.parents, asset.id.0.first_interior()), (1, Some(GlobalConsensus(network))) if *network == EthereumNetwork::get())
40
87
    }
41
}
42

            
43
/// Filter to ensure an ETH asset is coming from a parent.
44
pub struct EthereumAssetReserveFromParent<EthereumLocation, EthereumNetwork>(
45
    core::marker::PhantomData<(EthereumLocation, EthereumNetwork)>,
46
);
47
impl<EthereumLocation, EthereumNetwork> frame_support::traits::ContainsPair<Asset, Location>
48
    for EthereumAssetReserveFromParent<EthereumLocation, EthereumNetwork>
49
where
50
    EthereumLocation: Get<Location>,
51
    EthereumNetwork: Get<NetworkId>,
52
{
53
26
    fn contains(asset: &Asset, origin: &Location) -> bool {
54
26
        log::trace!(target: "xcm::contains", "EthereumAssetReserveFromPara asset: {:?}, origin: {:?}, eth_network: {:?}", asset, origin, EthereumLocation::get());
55
26
        if *origin == EthereumLocation::get() || *origin == Location::parent() {
56
24
            return matches!((asset.id.0.parents, asset.id.0.first_interior()), (2, Some(GlobalConsensus(network))) if *network == EthereumNetwork::get());
57
2
        }
58
2
        return false;
59
26
    }
60
}
61

            
62
/// Filter to ensure that Ethereum can be recongnized as a reserve for Tanssi asset.
63
/// Used in containers to allow sending tokens to Ethereum and paying fees with Tanssi.
64
pub struct EthereumAssetReserveForTanssi<EthereumLocation>(
65
    core::marker::PhantomData<EthereumLocation>,
66
);
67
impl<EthereumLocation> frame_support::traits::ContainsPair<Asset, Location>
68
    for EthereumAssetReserveForTanssi<EthereumLocation>
69
where
70
    EthereumLocation: Get<Location>,
71
{
72
28
    fn contains(asset: &Asset, origin: &Location) -> bool {
73
28
        log::trace!(target: "xcm::contains", "EthereumAssetReserveForTanssi asset: {:?}, origin: {:?}, eth_network: {:?}", asset, origin, EthereumLocation::get());
74
28
        if *origin == EthereumLocation::get() {
75
6
            return matches!((asset.id.0.parents, asset.id.0.first_interior()), (1, None));
76
22
        }
77
22
        return false;
78
28
    }
79
}
80

            
81
/// Filter to ensure that Ethereum can be recognized as a reserve for container chain assets.
82
/// Used when assets native to container chains are transferred back from Ethereum.
83
///
84
/// Note: this is not the usual way of managing container assets, as recognizing Ethereum as
85
/// their reserve is not the "correct" way of doing it.
86
///
87
/// This is an exception for inbound queue V2 processing, where we need to recognize Ethereum
88
/// as the reserve for container assets at the moment of placing them in the holding (in Tanssi)
89
/// via ReserveAssetDeposited instruction.
90
///
91
/// Otherwise, we don't have any other way of placing inbound container assets in holding, since
92
/// we cannot extract them from the Ethereum's sovereign account either (as the assets
93
/// don't exist in Tanssi).
94
pub struct EthereumAssetReserveForContainerAssets<EthereumLocation>(
95
    core::marker::PhantomData<EthereumLocation>,
96
);
97
impl<EthereumLocation> frame_support::traits::ContainsPair<Asset, Location>
98
    for EthereumAssetReserveForContainerAssets<EthereumLocation>
99
where
100
    EthereumLocation: Get<Location>,
101
{
102
6
    fn contains(asset: &Asset, origin: &Location) -> bool {
103
6
        log::trace!(target: "xcm::contains", "EthereumAssetReserveForContainerAssets asset: {:?}, origin: {:?}, eth_location: {:?}", asset, origin, EthereumLocation::get());
104
6
        if *origin == EthereumLocation::get() {
105
            // Check if the asset has a Parachain junction as its first interior,
106
            // indicating it's native to a container chain
107
1
            return matches!(
108
4
                (asset.id.0.parents, asset.id.0.first_interior()),
109
                (0, Some(Parachain(_)))
110
            );
111
2
        }
112
2
        false
113
6
    }
114
}