Skip to content

Commit 9deeaef

Browse files
committed
asset-registry: Pass Asset Id to AuthorityOrigin
Different AssetId's may require different origin checks, which is currently not possible. These changes use EnsureOriginWithArg to allow users of this pallet to tailor the origin check to take the `asset_id` itself in consideration when choosing the specific `EnsureOrigin` implementation to be applied.
1 parent cc26ffa commit 9deeaef

File tree

3 files changed

+73
-15
lines changed

3 files changed

+73
-15
lines changed

asset-registry/src/lib.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
// Older clippy versions give a false positive on the expansion of [pallet::call].
33
// This is fixed in https://github.com/rust-lang/rust-clippy/issues/8321
44
#![allow(clippy::large_enum_variant)]
5-
6-
use frame_support::{pallet_prelude::*, traits::EnsureOrigin, transactional};
5+
use frame_support::{pallet_prelude::*, traits::EnsureOriginWithArg, transactional};
76
use frame_system::pallet_prelude::*;
87
use orml_traits::asset_registry::AssetProcessor;
98
use scale_info::TypeInfo;
@@ -19,9 +18,12 @@ pub use module::*;
1918
pub use weights::WeightInfo;
2019

2120
mod impls;
21+
mod weights;
22+
23+
#[cfg(test)]
2224
mod mock;
25+
#[cfg(test)]
2326
mod tests;
24-
mod weights;
2527

2628
/// Data describing the asset properties.
2729
#[derive(scale_info::TypeInfo, Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug)]
@@ -48,8 +50,8 @@ pub mod module {
4850
/// The type used as a unique asset id,
4951
type AssetId: Parameter + Member + Default + TypeInfo;
5052

51-
/// The origin that is allowed to manipulate metadata.
52-
type AuthorityOrigin: EnsureOrigin<<Self as frame_system::Config>::Origin>;
53+
/// Checks that an origin has the authority to register/update an asset
54+
type AuthorityOrigin: EnsureOriginWithArg<Self::Origin, Option<Self::AssetId>>;
5355

5456
/// A filter ran upon metadata registration that assigns an is and
5557
/// potentially modifies the supplied metadata.
@@ -88,10 +90,6 @@ pub mod module {
8890
asset_id: T::AssetId,
8991
metadata: AssetMetadata<T::Balance, T::CustomMetadata>,
9092
},
91-
SetLocation {
92-
asset_id: T::AssetId,
93-
location: Box<VersionedMultiLocation>,
94-
},
9593
}
9694

9795
/// The metadata of an asset, indexed by asset id.
@@ -147,7 +145,7 @@ pub mod module {
147145
metadata: AssetMetadata<T::Balance, T::CustomMetadata>,
148146
asset_id: Option<T::AssetId>,
149147
) -> DispatchResult {
150-
T::AuthorityOrigin::ensure_origin(origin)?;
148+
T::AuthorityOrigin::ensure_origin(origin, &asset_id.clone())?;
151149

152150
Self::do_register_asset(metadata, asset_id)
153151
}
@@ -165,7 +163,7 @@ pub mod module {
165163
location: Option<Option<VersionedMultiLocation>>,
166164
additional: Option<T::CustomMetadata>,
167165
) -> DispatchResult {
168-
T::AuthorityOrigin::ensure_origin(origin)?;
166+
T::AuthorityOrigin::ensure_origin(origin, &Some(asset_id.clone()))?;
169167

170168
Self::do_update_asset(
171169
asset_id,

asset-registry/src/mock/para.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ use crate as orml_asset_registry;
44

55
use codec::{Decode, Encode};
66
use cumulus_primitives_core::{ChannelStatus, GetChannelInfo, ParaId};
7+
use frame_support::traits::{EnsureOrigin, EnsureOriginWithArg};
78
use frame_support::{
8-
construct_runtime, match_types, parameter_types,
9+
construct_runtime, match_types, ord_parameter_types, parameter_types,
910
traits::{ConstU128, ConstU32, ConstU64, Everything, Nothing},
1011
weights::{constants::WEIGHT_PER_SECOND, Weight},
1112
PalletId,
1213
};
13-
use frame_system::EnsureRoot;
14+
use frame_system::{EnsureRoot, EnsureSignedBy};
1415
use orml_asset_registry::{AssetRegistryTrader, FixedRateAssetRegistryTrader};
1516
use orml_traits::{
1617
location::{AbsoluteReserveProvider, RelativeReserveProvider},
@@ -103,11 +104,39 @@ pub struct CustomMetadata {
103104
pub fee_per_second: u128,
104105
}
105106

107+
const ADMIN_ASSET_TWO: AccountId = AccountId32::new([42u8; 32]);
108+
109+
ord_parameter_types! {
110+
pub const AdminAssetTwo: AccountId = ADMIN_ASSET_TWO;
111+
}
112+
113+
pub struct AssetAuthority;
114+
impl EnsureOriginWithArg<Origin, Option<u32>> for AssetAuthority {
115+
type Success = ();
116+
117+
fn try_origin(origin: Origin, asset_id: &Option<u32>) -> Result<Self::Success, Origin> {
118+
match asset_id {
119+
// We mock an edge case where the asset_id 2 requires a special origin check.
120+
Some(2) => EnsureSignedBy::<AdminAssetTwo, AccountId32>::try_origin(origin.clone())
121+
.map(|_| ())
122+
.map_err(|_| origin),
123+
124+
// Any other `asset_id` defaults to EnsureRoot
125+
_ => EnsureRoot::try_origin(origin),
126+
}
127+
}
128+
129+
#[cfg(feature = "runtime-benchmarks")]
130+
fn successful_origin(a: &u32) -> OO {
131+
unimplemented!()
132+
}
133+
}
134+
106135
impl orml_asset_registry::Config for Runtime {
107136
type Event = Event;
108137
type Balance = Balance;
109138
type AssetId = u32;
110-
type AuthorityOrigin = EnsureRoot<AccountId>;
139+
type AuthorityOrigin = AssetAuthority;
111140
type CustomMetadata = CustomMetadata;
112141
type AssetProcessor = orml_asset_registry::SequentialId<Runtime>;
113142
type WeightInfo = ();

asset-registry/src/tests.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
use super::*;
44
use crate as orml_asset_registry;
5-
use crate::tests::para::{AssetRegistry, CustomMetadata, Origin, Tokens, TreasuryAccount};
5+
use crate::tests::para::{AdminAssetTwo, AssetRegistry, CustomMetadata, Origin, Tokens, TreasuryAccount};
66
use frame_support::{assert_noop, assert_ok};
77
use mock::*;
88
use orml_traits::MultiCurrency;
99
use polkadot_parachain::primitives::Sibling;
10+
use sp_runtime::traits::BadOrigin;
1011
use sp_runtime::AccountId32;
1112
use xcm_simulator::TestExt;
1213

@@ -461,3 +462,33 @@ fn test_existential_deposits() {
461462
);
462463
});
463464
}
465+
466+
#[test]
467+
fn test_asset_authority() {
468+
TestNet::reset();
469+
470+
ParaA::execute_with(|| {
471+
let metadata = dummy_metadata();
472+
473+
// Assert that root can register an asset with id 1
474+
assert_ok!(AssetRegistry::register_asset(Origin::root(), metadata.clone(), Some(1)));
475+
476+
// Assert that only Account42 can register asset with id 42
477+
let metadata = AssetMetadata {
478+
location: None,
479+
..dummy_metadata()
480+
};
481+
482+
// It fails when signed with root...
483+
assert_noop!(
484+
AssetRegistry::register_asset(Origin::root(), metadata.clone(), Some(2)),
485+
BadOrigin
486+
);
487+
// It works when signed with the right account
488+
assert_ok!(AssetRegistry::register_asset(
489+
Origin::signed(AdminAssetTwo::get()),
490+
metadata,
491+
Some(2)
492+
));
493+
});
494+
}

0 commit comments

Comments
 (0)