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
trait Parse {
22
    /// Returns the "chain" location part. It could be parent, sibling
23
    /// parachain, or child parachain.
24
    fn chain_part(&self) -> Option<Location>;
25
}
26

            
27
impl Parse for Location {
28
480
    fn chain_part(&self) -> Option<Location> {
29
480
        match (self.parents, self.first_interior()) {
30
            // sibling parachain
31
120
            (1, Some(Parachain(id))) => Some(Location::new(1, [Parachain(*id)])),
32
            // parent
33
348
            (1, _) => Some(Location::parent()),
34
            // children parachain
35
            (0, Some(Parachain(id))) => Some(Location::new(0, [Parachain(*id)])),
36
12
            _ => None,
37
        }
38
480
    }
39
}
40

            
41
pub struct NativeAssetReserve;
42
impl frame_support::traits::ContainsPair<Asset, Location> for NativeAssetReserve {
43
696
    fn contains(asset: &Asset, origin: &Location) -> bool {
44
696
        log::trace!(target: "xcm::contains", "NativeAssetReserve asset: {:?}, origin: {:?}", asset, origin);
45
696
        let reserve = if asset.id.0.parents == 0
46
216
            && !matches!(asset.id.0.first_interior(), Some(Parachain(_)))
47
        {
48
216
            Some(Location::here())
49
        } else {
50
480
            asset.id.0.chain_part()
51
        };
52

            
53
696
        if let Some(ref reserve) = reserve {
54
684
            if reserve == origin {
55
384
                return true;
56
300
            }
57
12
        }
58
312
        false
59
696
    }
60
}
61

            
62
/// Filter to ensure an ETH asset is coming from a trusted Ethereum location.
63
pub struct EthereumAssetReserve<EthereumLocation, EthereumNetwork>(
64
    sp_std::marker::PhantomData<(EthereumLocation, EthereumNetwork)>,
65
);
66
impl<EthereumLocation, EthereumNetwork> frame_support::traits::ContainsPair<Asset, Location>
67
    for EthereumAssetReserve<EthereumLocation, EthereumNetwork>
68
where
69
    EthereumLocation: Get<Location>,
70
    EthereumNetwork: Get<NetworkId>,
71
{
72
3
    fn contains(asset: &Asset, origin: &Location) -> bool {
73
3
        log::trace!(target: "xcm::contains", "EthereumAssetReserve asset: {:?}, origin: {:?}", asset, origin);
74
3
        if *origin != EthereumLocation::get() {
75
1
            return false;
76
2
        }
77
2
        match (asset.id.0.parents, asset.id.0.first_interior()) {
78
2
            (1, Some(GlobalConsensus(network))) if *network == EthereumNetwork::get() => true,
79
            _ => false,
80
        }
81
3
    }
82
}