implement ConversionToAssetBalance in asset-rate (#2903)

Implements the `ConversionToAssetBalance` trait to asset-rate by doing
`1/rate*(balance)`.
This commit is contained in:
girazoki
2024-02-20 15:28:05 +01:00
committed by GitHub
parent ca382f3203
commit 5f8b6f38a3
3 changed files with 74 additions and 4 deletions
+15
View File
@@ -0,0 +1,15 @@
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
title: "Implement `ConversionToAssetBalance` in asset-rate"
doc:
- audience: Runtime Dev
description: |
Implements the `ConversionToAssetBalance` trait to the asset-rate pallet.
Previously only the `ConversionFromAssetBalance` trait was implemented, which would allow to convert an asset balance into the corresponding native balance.
The `ConversionToAssetBalance` allows to use pallet-asset-rate, e.g., as a mechanism to charge XCM fees in an asset that is not the native.
crates: [ ]
+32 -2
View File
@@ -59,8 +59,14 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
use frame_support::traits::{fungible::Inspect, tokens::ConversionFromAssetBalance}; use frame_support::traits::{
use sp_runtime::{traits::Zero, FixedPointNumber, FixedU128}; fungible::Inspect,
tokens::{ConversionFromAssetBalance, ConversionToAssetBalance},
};
use sp_runtime::{
traits::{CheckedDiv, Zero},
FixedPointNumber, FixedU128,
};
use sp_std::boxed::Box; use sp_std::boxed::Box;
pub use pallet::*; pub use pallet::*;
@@ -144,6 +150,8 @@ pub mod pallet {
UnknownAssetKind, UnknownAssetKind,
/// The given asset ID already has an assigned conversion rate and cannot be re-created. /// The given asset ID already has an assigned conversion rate and cannot be re-created.
AlreadyExists, AlreadyExists,
/// Overflow ocurred when calculating the inverse rate.
Overflow,
} }
#[pallet::call] #[pallet::call]
@@ -246,3 +254,25 @@ where
pallet::ConversionRateToNative::<T>::set(asset_id.clone(), Some(1.into())); pallet::ConversionRateToNative::<T>::set(asset_id.clone(), Some(1.into()));
} }
} }
/// Exposes conversion of a native balance to an asset balance.
impl<T> ConversionToAssetBalance<BalanceOf<T>, AssetKindOf<T>, BalanceOf<T>> for Pallet<T>
where
T: Config,
{
type Error = pallet::Error<T>;
fn to_asset_balance(
balance: BalanceOf<T>,
asset_kind: AssetKindOf<T>,
) -> Result<BalanceOf<T>, pallet::Error<T>> {
let rate = pallet::ConversionRateToNative::<T>::get(asset_kind)
.ok_or(pallet::Error::<T>::UnknownAssetKind.into())?;
// We cannot use `saturating_div` here so we use `checked_div`.
Ok(FixedU128::from_u32(1)
.checked_div(&rate)
.ok_or(pallet::Error::<T>::Overflow.into())?
.saturating_mul_int(balance))
}
}
+27 -2
View File
@@ -131,12 +131,19 @@ fn convert_works() {
FixedU128::from_float(2.51) FixedU128::from_float(2.51)
)); ));
let conversion = <AssetRate as ConversionFromAssetBalance< let conversion_from_asset = <AssetRate as ConversionFromAssetBalance<
BalanceOf<Test>, BalanceOf<Test>,
<Test as pallet_asset_rate::Config>::AssetKind, <Test as pallet_asset_rate::Config>::AssetKind,
BalanceOf<Test>, BalanceOf<Test>,
>>::from_asset_balance(10, ASSET_ID); >>::from_asset_balance(10, ASSET_ID);
assert_eq!(conversion.expect("Conversion rate exists for asset"), 25); assert_eq!(conversion_from_asset.expect("Conversion rate exists for asset"), 25);
let conversion_to_asset = <AssetRate as ConversionToAssetBalance<
BalanceOf<Test>,
<Test as pallet_asset_rate::Config>::AssetKind,
BalanceOf<Test>,
>>::to_asset_balance(25, ASSET_ID);
assert_eq!(conversion_to_asset.expect("Conversion rate exists for asset"), 9);
}); });
} }
@@ -151,3 +158,21 @@ fn convert_unknown_throws() {
assert!(conversion.is_err()); assert!(conversion.is_err());
}); });
} }
#[test]
fn convert_overflow_throws() {
new_test_ext().execute_with(|| {
assert_ok!(AssetRate::create(
RuntimeOrigin::root(),
Box::new(ASSET_ID),
FixedU128::from_u32(0)
));
let conversion = <AssetRate as ConversionToAssetBalance<
BalanceOf<Test>,
<Test as pallet_asset_rate::Config>::AssetKind,
BalanceOf<Test>,
>>::to_asset_balance(10, ASSET_ID);
assert!(conversion.is_err());
});
}