Skip to content

Commit

Permalink
Assets pallet: Giving the asset owner the ability to set minimum bala…
Browse files Browse the repository at this point in the history
…nce (paritytech#13486)

* set_min_balance

* allow when new_min_balance < old_min_balance

* add more specific event

* Update frame/assets/src/lib.rs

Co-authored-by: Bastian Köcher <[email protected]>

* Update frame/assets/src/lib.rs

Co-authored-by: Bastian Köcher <[email protected]>

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_assets

* use actual weight

---------

Co-authored-by: Bastian Köcher <[email protected]>
Co-authored-by: command-bot <>
  • Loading branch information
2 people authored and nathanwhit committed Jul 19, 2023
1 parent 5063c9a commit 9e49a0d
Show file tree
Hide file tree
Showing 4 changed files with 337 additions and 186 deletions.
7 changes: 7 additions & 0 deletions frame/assets/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,5 +471,12 @@ benchmarks_instance_pallet! {
assert_last_event::<T, I>(Event::ApprovalCancelled { asset_id: asset_id.into(), owner: caller, delegate }.into());
}

set_min_balance {
let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(true);
}: _(SystemOrigin::Signed(caller.clone()), asset_id, 50u32.into())
verify {
assert_last_event::<T, I>(Event::AssetMinBalanceChanged { asset_id: asset_id.into(), new_min_balance: 50u32.into() }.into());
}

impl_benchmark_test_suite!(Assets, crate::mock::new_test_ext(), crate::mock::Test)
}
45 changes: 45 additions & 0 deletions frame/assets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,8 @@ pub mod pallet {
},
/// An asset has had its attributes changed by the `Force` origin.
AssetStatusChanged { asset_id: T::AssetId },
/// The min_balance of an asset has been updated by the asset owner.
AssetMinBalanceChanged { asset_id: T::AssetId, new_min_balance: T::Balance },
}

#[pallet::error]
Expand Down Expand Up @@ -1511,6 +1513,49 @@ pub mod pallet {
let id: T::AssetId = id.into();
Self::do_refund(id, ensure_signed(origin)?, allow_burn)
}

/// Sets the minimum balance of an asset.
///
/// Only works if there aren't any accounts that are holding the asset or if
/// the new value of `min_balance` is less than the old one.
///
/// Origin must be Signed and the sender has to be the Owner of the
/// asset `id`.
///
/// - `id`: The identifier of the asset.
/// - `min_balance`: The new value of `min_balance`.
///
/// Emits `AssetMinBalanceChanged` event when successful.
#[pallet::call_index(28)]
#[pallet::weight(T::WeightInfo::set_min_balance())]
pub fn set_min_balance(
origin: OriginFor<T>,
id: T::AssetIdParameter,
min_balance: T::Balance,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
let id: T::AssetId = id.into();

let mut details = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
ensure!(origin == details.owner, Error::<T, I>::NoPermission);

let old_min_balance = details.min_balance;
// Ensure that either the new min_balance is less than old min_balance or there aren't
// any accounts holding the asset.
ensure!(
min_balance < old_min_balance || details.accounts == 0,
Error::<T, I>::NoPermission
);

details.min_balance = min_balance;
Asset::<T, I>::insert(&id, details);

Self::deposit_event(Event::AssetMinBalanceChanged {
asset_id: id,
new_min_balance: min_balance,
});
Ok(())
}
}
}

Expand Down
29 changes: 29 additions & 0 deletions frame/assets/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,35 @@ fn force_asset_status_should_work() {
});
}

#[test]
fn set_min_balance_should_work() {
new_test_ext().execute_with(|| {
let id = 42;
Balances::make_free_balance_be(&1, 10);
assert_ok!(Assets::create(RuntimeOrigin::signed(1), id, 1, 30));

assert_ok!(Assets::mint(RuntimeOrigin::signed(1), id, 1, 50));
// won't execute because there is an asset holder.
assert_noop!(
Assets::set_min_balance(RuntimeOrigin::signed(1), id, 50),
Error::<Test>::NoPermission
);

// will execute because the new value of min_balance is less than the
// old value. 10 < 30
assert_ok!(Assets::mint(RuntimeOrigin::signed(1), id, 1, 10));

assert_ok!(Assets::burn(RuntimeOrigin::signed(1), id, 1, 50));
assert_noop!(
Assets::set_min_balance(RuntimeOrigin::signed(2), id, 50),
Error::<Test>::NoPermission
);

assert_ok!(Assets::set_min_balance(RuntimeOrigin::signed(1), id, 50));
assert_eq!(Asset::<Test>::get(id).unwrap().min_balance, 50);
});
}

#[test]
fn balance_conversion_should_work() {
new_test_ext().execute_with(|| {
Expand Down
Loading

0 comments on commit 9e49a0d

Please sign in to comment.