Skip to content
This repository was archived by the owner on May 21, 2024. It is now read-only.

Commit f75f1c7

Browse files
Validate MultiLocation for asset-registry (#224)
* Validate location for register_reserve_asset * fmt * fmt * fmt * validator refactor * fmt
1 parent e9de40e commit f75f1c7

File tree

2 files changed

+197
-75
lines changed

2 files changed

+197
-75
lines changed

pallets/asset-registry/src/lib.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ pub mod pallet {
3939
use frame_system::pallet_prelude::*;
4040

4141
use xcm::latest::{
42-
Junction::{GeneralIndex, PalletInstance, Parachain},
43-
Junctions, MultiLocation,
42+
Junction::{AccountId32, AccountKey20, GeneralIndex, PalletInstance},
43+
MultiLocation,
4444
};
4545

4646
#[pallet::pallet]
@@ -114,13 +114,7 @@ pub mod pallet {
114114

115115
// verify MultiLocation is valid
116116
ensure!(
117-
matches!(
118-
asset_multi_location,
119-
MultiLocation {
120-
parents: 1,
121-
interior: Junctions::X3(Parachain(_), PalletInstance(_), GeneralIndex(_))
122-
}
123-
),
117+
Self::valid_asset_location(&asset_multi_location),
124118
Error::<T>::WrongMultiLocation
125119
);
126120

@@ -153,6 +147,31 @@ pub mod pallet {
153147
}
154148
}
155149

150+
impl<T: Config> Pallet<T> {
151+
//Validates that the location points to an asset (Native, Frame based, Erc20) as described
152+
// in the xcm-format: https://github.com/paritytech/xcm-format#concrete-identifiers
153+
fn valid_asset_location(location: &MultiLocation) -> bool {
154+
let (split_multilocation, last_junction) = location.clone().split_last_interior();
155+
156+
let check = matches!(
157+
last_junction,
158+
Some(AccountId32 { .. }) |
159+
Some(AccountKey20 { .. }) |
160+
Some(PalletInstance(_)) |
161+
None
162+
);
163+
164+
check |
165+
match last_junction {
166+
Some(GeneralIndex(_)) => {
167+
let penultimate = split_multilocation.last();
168+
matches!(penultimate, Some(PalletInstance(_)))
169+
},
170+
_ => false,
171+
}
172+
}
173+
}
174+
156175
impl<T: Config> xcm_primitives::AssetMultiLocationGetter<AssetIdOf<T>> for Pallet<T> {
157176
fn get_asset_multi_location(asset_id: AssetIdOf<T>) -> Option<MultiLocation> {
158177
AssetIdMultiLocation::<T>::get(asset_id)

pallets/asset-registry/src/tests.rs

Lines changed: 169 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -29,84 +29,187 @@ const STATEMINE_ASSET_MULTI_LOCATION: MultiLocation = MultiLocation {
2929
),
3030
};
3131

32-
#[test]
33-
fn register_reserve_asset_works() {
34-
new_test_ext().execute_with(|| {
35-
assert_ok!(AssetRegistry::register_reserve_asset(
36-
RuntimeOrigin::root(),
37-
LOCAL_ASSET_ID,
38-
STATEMINE_ASSET_MULTI_LOCATION,
39-
));
40-
41-
assert_eq!(
42-
AssetIdMultiLocation::<Test>::get(LOCAL_ASSET_ID),
43-
Some(STATEMINE_ASSET_MULTI_LOCATION)
44-
);
45-
assert_eq!(
46-
AssetMultiLocationId::<Test>::get(STATEMINE_ASSET_MULTI_LOCATION),
47-
Some(LOCAL_ASSET_ID)
48-
);
49-
});
50-
}
32+
mod register_reserve_assest {
33+
use super::*;
34+
35+
#[test]
36+
fn register_reserve_asset_works() {
37+
new_test_ext().execute_with(|| {
38+
assert_ok!(AssetRegistry::register_reserve_asset(
39+
RuntimeOrigin::root(),
40+
LOCAL_ASSET_ID,
41+
STATEMINE_ASSET_MULTI_LOCATION,
42+
));
43+
44+
assert_eq!(
45+
AssetIdMultiLocation::<Test>::get(LOCAL_ASSET_ID),
46+
Some(STATEMINE_ASSET_MULTI_LOCATION)
47+
);
48+
assert_eq!(
49+
AssetMultiLocationId::<Test>::get(STATEMINE_ASSET_MULTI_LOCATION),
50+
Some(LOCAL_ASSET_ID)
51+
);
52+
});
53+
}
5154

52-
#[test]
53-
fn cannot_register_unexisting_asset() {
54-
new_test_ext().execute_with(|| {
55-
let unexisting_asset_id = 9999;
55+
#[test]
56+
fn cannot_register_unexisting_asset() {
57+
new_test_ext().execute_with(|| {
58+
let unexisting_asset_id = 9999;
5659

57-
assert_noop!(
58-
AssetRegistry::register_reserve_asset(
60+
assert_noop!(
61+
AssetRegistry::register_reserve_asset(
62+
RuntimeOrigin::root(),
63+
unexisting_asset_id,
64+
STATEMINE_ASSET_MULTI_LOCATION,
65+
),
66+
Error::<Test>::AssetDoesNotExist
67+
);
68+
});
69+
}
70+
71+
#[test]
72+
fn cannot_double_register() {
73+
new_test_ext().execute_with(|| {
74+
assert_ok!(AssetRegistry::register_reserve_asset(
5975
RuntimeOrigin::root(),
60-
unexisting_asset_id,
76+
LOCAL_ASSET_ID,
6177
STATEMINE_ASSET_MULTI_LOCATION,
78+
));
79+
80+
assert_noop!(
81+
AssetRegistry::register_reserve_asset(
82+
RuntimeOrigin::root(),
83+
LOCAL_ASSET_ID,
84+
STATEMINE_ASSET_MULTI_LOCATION,
85+
),
86+
Error::<Test>::AssetAlreadyRegistered
87+
);
88+
});
89+
}
90+
91+
#[test]
92+
fn valid_locations_succced() {
93+
let native_frame_based_currency =
94+
MultiLocation { parents: 1, interior: X2(Parachain(1000), PalletInstance(1)) };
95+
let multiasset_pallet_instance = MultiLocation {
96+
parents: 1,
97+
interior: X3(Parachain(1000), PalletInstance(1), GeneralIndex(2)),
98+
};
99+
let relay_native_currency = MultiLocation { parents: 1, interior: Junctions::Here };
100+
let erc20_frame_sm_asset = MultiLocation {
101+
parents: 1,
102+
interior: X3(
103+
Parachain(1000),
104+
PalletInstance(2),
105+
AccountId32 { network: Any, id: [0; 32] },
62106
),
63-
Error::<Test>::AssetDoesNotExist
64-
);
65-
});
66-
}
107+
};
108+
let erc20_ethereum_sm_asset = MultiLocation {
109+
parents: 1,
110+
interior: X2(Parachain(2000), AccountKey20 { network: Any, key: [0; 20] }),
111+
};
67112

68-
#[test]
69-
fn cannot_double_register() {
70-
new_test_ext().execute_with(|| {
71-
assert_ok!(AssetRegistry::register_reserve_asset(
72-
RuntimeOrigin::root(),
73-
LOCAL_ASSET_ID,
74-
STATEMINE_ASSET_MULTI_LOCATION,
75-
));
76-
77-
assert_noop!(
78-
AssetRegistry::register_reserve_asset(
113+
new_test_ext().execute_with(|| {
114+
assert_ok!(AssetRegistry::register_reserve_asset(
79115
RuntimeOrigin::root(),
80116
LOCAL_ASSET_ID,
81-
STATEMINE_ASSET_MULTI_LOCATION,
117+
native_frame_based_currency,
118+
));
119+
});
120+
new_test_ext().execute_with(|| {
121+
assert_ok!(AssetRegistry::register_reserve_asset(
122+
RuntimeOrigin::root(),
123+
LOCAL_ASSET_ID,
124+
multiasset_pallet_instance,
125+
));
126+
});
127+
new_test_ext().execute_with(|| {
128+
assert_ok!(AssetRegistry::register_reserve_asset(
129+
RuntimeOrigin::root(),
130+
LOCAL_ASSET_ID,
131+
relay_native_currency,
132+
));
133+
});
134+
new_test_ext().execute_with(|| {
135+
assert_ok!(AssetRegistry::register_reserve_asset(
136+
RuntimeOrigin::root(),
137+
LOCAL_ASSET_ID,
138+
erc20_frame_sm_asset,
139+
));
140+
});
141+
new_test_ext().execute_with(|| {
142+
assert_ok!(AssetRegistry::register_reserve_asset(
143+
RuntimeOrigin::root(),
144+
LOCAL_ASSET_ID,
145+
erc20_ethereum_sm_asset,
146+
));
147+
});
148+
}
149+
150+
#[test]
151+
fn invalid_locations_fail() {
152+
let governance_location = MultiLocation {
153+
parents: 1,
154+
interior: X2(
155+
Parachain(1000),
156+
Plurality { id: BodyId::Executive, part: BodyPart::Voice },
82157
),
83-
Error::<Test>::AssetAlreadyRegistered
84-
);
85-
});
158+
};
159+
let invalid_general_index =
160+
MultiLocation { parents: 1, interior: X2(Parachain(1000), GeneralIndex(1u128)) };
161+
162+
new_test_ext().execute_with(|| {
163+
assert_noop!(
164+
AssetRegistry::register_reserve_asset(
165+
RuntimeOrigin::root(),
166+
LOCAL_ASSET_ID,
167+
governance_location,
168+
),
169+
Error::<Test>::WrongMultiLocation
170+
);
171+
172+
assert_noop!(
173+
AssetRegistry::register_reserve_asset(
174+
RuntimeOrigin::root(),
175+
LOCAL_ASSET_ID,
176+
invalid_general_index,
177+
),
178+
Error::<Test>::WrongMultiLocation
179+
);
180+
})
181+
}
86182
}
87183

88-
#[test]
89-
fn unregister_reserve_asset_works() {
90-
new_test_ext().execute_with(|| {
91-
assert_ok!(AssetRegistry::register_reserve_asset(
92-
RuntimeOrigin::root(),
93-
LOCAL_ASSET_ID,
94-
STATEMINE_ASSET_MULTI_LOCATION,
95-
));
184+
mod unregister_reserve_asset {
185+
use super::*;
96186

97-
assert_ok!(AssetRegistry::unregister_reserve_asset(RuntimeOrigin::root(), LOCAL_ASSET_ID));
187+
#[test]
188+
fn unregister_reserve_asset_works() {
189+
new_test_ext().execute_with(|| {
190+
assert_ok!(AssetRegistry::register_reserve_asset(
191+
RuntimeOrigin::root(),
192+
LOCAL_ASSET_ID,
193+
STATEMINE_ASSET_MULTI_LOCATION,
194+
));
98195

99-
assert!(AssetIdMultiLocation::<Test>::get(LOCAL_ASSET_ID).is_none());
100-
assert!(AssetMultiLocationId::<Test>::get(STATEMINE_ASSET_MULTI_LOCATION).is_none());
101-
});
102-
}
196+
assert_ok!(AssetRegistry::unregister_reserve_asset(
197+
RuntimeOrigin::root(),
198+
LOCAL_ASSET_ID
199+
));
200+
201+
assert!(AssetIdMultiLocation::<Test>::get(LOCAL_ASSET_ID).is_none());
202+
assert!(AssetMultiLocationId::<Test>::get(STATEMINE_ASSET_MULTI_LOCATION).is_none());
203+
});
204+
}
103205

104-
#[test]
105-
fn cannot_register_unregistered_asset() {
106-
new_test_ext().execute_with(|| {
107-
assert_noop!(
108-
AssetRegistry::unregister_reserve_asset(RuntimeOrigin::root(), LOCAL_ASSET_ID),
109-
Error::<Test>::AssetIsNotRegistered
110-
);
111-
});
206+
#[test]
207+
fn cannot_register_unregistered_asset() {
208+
new_test_ext().execute_with(|| {
209+
assert_noop!(
210+
AssetRegistry::unregister_reserve_asset(RuntimeOrigin::root(), LOCAL_ASSET_ID),
211+
Error::<Test>::AssetIsNotRegistered
212+
);
213+
});
214+
}
112215
}

0 commit comments

Comments
 (0)