Skip to content

Commit 0dbb4d5

Browse files
paritytech-release-backport-bot[bot]gui1117github-actions[bot]acatangiu
authored
[stable2509] Backport #7456 (#10070)
Backport #7456 into `stable2509` from gui1117. See the [documentation](https://github.com/paritytech/polkadot-sdk/blob/master/docs/BACKPORT.md) on how to use this bot. <!-- # To be used by other automation, do not modify: original-pr-number: #${pull_number} --> Co-authored-by: Guillaume Thiolliere <[email protected]> Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Adrian Catangiu <[email protected]>
1 parent b4a7f1c commit 0dbb4d5

File tree

4 files changed

+48
-24
lines changed

4 files changed

+48
-24
lines changed

prdoc/pr_7456.prdoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
title: 'pallet-assets: make touch other permissionless'
2+
doc:
3+
- audience: Runtime User
4+
description: |-
5+
In pallet assets, make `touch_other` call permissionless. Before this PR only `Admin` and `Freezer` of an asset could touch an account, now every account can.
6+
crates:
7+
- name: pallet-assets
8+
bump: minor

substrate/frame/assets/src/functions.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -338,23 +338,15 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
338338
}
339339

340340
/// Creates an account for `who` to hold asset `id` with a zero balance and takes a deposit.
341-
///
342-
/// When `check_depositor` is set to true, the depositor must be either the asset's Admin or
343-
/// Freezer, otherwise the depositor can be any account.
344341
pub(super) fn do_touch(
345342
id: T::AssetId,
346343
who: T::AccountId,
347344
depositor: T::AccountId,
348-
check_depositor: bool,
349345
) -> DispatchResult {
350346
ensure!(!Account::<T, I>::contains_key(&id, &who), Error::<T, I>::AlreadyExists);
351347
let deposit = T::AssetAccountDeposit::get();
352348
let mut details = Asset::<T, I>::get(&id).ok_or(Error::<T, I>::Unknown)?;
353349
ensure!(details.status == AssetStatus::Live, Error::<T, I>::AssetNotLive);
354-
ensure!(
355-
!check_depositor || &depositor == &details.admin || &depositor == &details.freezer,
356-
Error::<T, I>::NoPermission
357-
);
358350
let reason = Self::new_account(&who, &mut details, Some((&depositor, deposit)))?;
359351
T::Currency::reserve(&depositor, deposit)?;
360352
Asset::<T, I>::insert(&id, details);

substrate/frame/assets/src/lib.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
//! * `refund`: Return the deposit (if any) of the caller's asset account or a consumer reference
9595
//! (if any) of the caller's account.
9696
//! * `refund_other`: Return the deposit (if any) of a specified asset account.
97+
//! * `touch_other`: Create an asset account for specified account. Caller must place a deposit.
9798
//!
9899
//! ### Permissioned Functions
99100
//!
@@ -116,8 +117,6 @@
116117
//! Owner.
117118
//! * `set_metadata`: Set the metadata of an asset class; called by the asset class's Owner.
118119
//! * `clear_metadata`: Remove the metadata of an asset class; called by the asset class's Owner.
119-
//! * `touch_other`: Create an asset account for specified account. Caller must place a deposit;
120-
//! called by the asset class's Freezer or Admin.
121120
//! * `block`: Disallows further `transfer`s to and from an account; called by the asset class's
122121
//! Freezer.
123122
//!
@@ -1618,7 +1617,7 @@ pub mod pallet {
16181617
pub fn touch(origin: OriginFor<T>, id: T::AssetIdParameter) -> DispatchResult {
16191618
let who = ensure_signed(origin)?;
16201619
let id: T::AssetId = id.into();
1621-
Self::do_touch(id, who.clone(), who, false)
1620+
Self::do_touch(id, who.clone(), who)
16221621
}
16231622

16241623
/// Return the deposit (if any) of an asset account or a consumer reference (if any) of an
@@ -1695,9 +1694,10 @@ pub mod pallet {
16951694
///
16961695
/// A deposit will be taken from the signer account.
16971696
///
1698-
/// - `origin`: Must be Signed by `Freezer` or `Admin` of the asset `id`; the signer account
1699-
/// must have sufficient funds for a deposit to be taken.
1700-
/// - `id`: The identifier of the asset for the account to be created.
1697+
/// - `origin`: Must be Signed; the signer account must have sufficient funds for a deposit
1698+
/// to be taken.
1699+
/// - `id`: The identifier of the asset for the account to be created, the asset status must
1700+
/// be live.
17011701
/// - `who`: The account to be created.
17021702
///
17031703
/// Emits `Touched` event when successful.
@@ -1711,7 +1711,7 @@ pub mod pallet {
17111711
let origin = ensure_signed(origin)?;
17121712
let who = T::Lookup::lookup(who)?;
17131713
let id: T::AssetId = id.into();
1714-
Self::do_touch(id, who, origin, true)
1714+
Self::do_touch(id, who, origin)
17151715
}
17161716

17171717
/// Return the deposit (if any) of a target asset account. Useful if you are the depositor.
@@ -1823,7 +1823,6 @@ pub mod pallet {
18231823

18241824
/// Implements [`AccountTouch`] trait.
18251825
/// Note that a depositor can be any account, without any specific privilege.
1826-
/// This implementation is supposed to be used only for creation of system accounts.
18271826
impl<T: Config<I>, I: 'static> AccountTouch<T::AssetId, T::AccountId> for Pallet<T, I> {
18281827
type Balance = DepositBalanceOf<T, I>;
18291828

@@ -1846,7 +1845,7 @@ pub mod pallet {
18461845
who: &T::AccountId,
18471846
depositor: &T::AccountId,
18481847
) -> DispatchResult {
1849-
Self::do_touch(asset, who.clone(), depositor.clone(), false)
1848+
Self::do_touch(asset, who.clone(), depositor.clone())
18501849
}
18511850
}
18521851

substrate/frame/assets/src/tests.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,12 +1004,14 @@ fn touching_and_freezing_account_with_zero_asset_balance_should_work() {
10041004
});
10051005
}
10061006

1007+
// In the past only admin and freezer could call `touch_other`.
1008+
// Test that this behavior is still supported.
10071009
#[test]
1008-
fn touch_other_works() {
1010+
fn touch_other_works_legacy() {
10091011
new_test_ext().execute_with(|| {
10101012
// 1 will be admin
10111013
// 2 will be freezer
1012-
// 4 will be an account attempting to execute `touch_other`
1014+
// 4 will be an account successfully attempting to execute `touch_other`
10131015
Balances::make_free_balance_be(&1, 100);
10141016
Balances::make_free_balance_be(&2, 100);
10151017
Balances::make_free_balance_be(&4, 100);
@@ -1019,19 +1021,42 @@ fn touch_other_works() {
10191021
assert_eq!(Assets::balance(0, 1), 100);
10201022
// account `3` does not exist
10211023
assert!(!Account::<Test>::contains_key(0, &3));
1022-
// creation of asset account `3` by account `4` fails
1023-
assert_noop!(
1024-
Assets::touch_other(RuntimeOrigin::signed(4), 0, 3),
1025-
Error::<Test>::NoPermission
1026-
);
1024+
// creation of asset account `30` by account `4` works
1025+
assert_ok!(Assets::touch_other(RuntimeOrigin::signed(4), 0, 30));
10271026
// creation of asset account `3` by admin `1` works
10281027
assert!(!Account::<Test>::contains_key(0, &3));
10291028
assert_ok!(Assets::touch_other(RuntimeOrigin::signed(1), 0, 3));
10301029
assert!(Account::<Test>::contains_key(0, &3));
10311030
// creation of asset account `4` by freezer `2` works
10321031
assert!(!Account::<Test>::contains_key(0, &4));
10331032
assert_ok!(Assets::touch_other(RuntimeOrigin::signed(2), 0, 4));
1033+
});
1034+
}
1035+
1036+
#[test]
1037+
fn touch_other_works() {
1038+
new_test_ext().execute_with(|| {
1039+
Balances::make_free_balance_be(&3, 100);
1040+
assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1));
1041+
assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 3, 100));
1042+
assert_eq!(Assets::balance(0, 3), 100);
1043+
1044+
// account `4` does not exist
1045+
assert!(!Account::<Test>::contains_key(0, &4));
1046+
1047+
// creation of asset account `4` by funded account `3` works
1048+
assert_ok!(Assets::touch_other(RuntimeOrigin::signed(3), 0, 4));
10341049
assert!(Account::<Test>::contains_key(0, &4));
1050+
1051+
// account `6` does not exist
1052+
assert!(!Account::<Test>::contains_key(0, &6));
1053+
1054+
// creation of asset account `6` by not funded account `5` fails
1055+
assert_noop!(
1056+
Assets::touch_other(RuntimeOrigin::signed(5), 0, 6),
1057+
BalancesError::<Test>::InsufficientBalance,
1058+
);
1059+
assert!(!Account::<Test>::contains_key(0, &6));
10351060
});
10361061
}
10371062

0 commit comments

Comments
 (0)