Skip to content

Commit

Permalink
refactoring, benchmarking, updated mock, runtime integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Roznovjak committed Jul 24, 2023
1 parent 88291ab commit 70e51f6
Show file tree
Hide file tree
Showing 14 changed files with 327 additions and 346 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 3 additions & 7 deletions pallets/asset-registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,13 +590,9 @@ impl<T: Config> ShareTokenRegistry<T::AssetId, Vec<u8>, T::Balance, DispatchErro
}
}

impl<T: Config> BondRegistry<T::AssetId, Vec<u8>, T::Balance, AssetDetailsT<T>, DispatchError> for Pallet<T> {
fn get_asset_details(asset_id: T::AssetId) -> Result<AssetDetailsT<T>, DispatchError> {
Assets::<T>::try_get(asset_id).map_err(|_| Error::<T>::AssetNotRegistered.into())
}

fn create_bond_asset(name: &Vec<u8>, existential_deposit: T::Balance) -> Result<T::AssetId, DispatchError> {
let bounded_name: BoundedVec<u8, T::StringLimit> = Self::to_bounded_name(name.clone())?;
impl<T: Config> BondRegistry<T::AssetId, Vec<u8>, T::Balance, DispatchError> for Pallet<T> {
fn create_bond_asset(existential_deposit: T::Balance) -> Result<T::AssetId, DispatchError> {
let bounded_name: BoundedVec<u8, T::StringLimit> = Self::to_bounded_name(Vec::<u8>::new())?;
Self::register_asset(bounded_name, AssetType::Bond, existential_deposit, None, None)
}
}
Expand Down
13 changes: 4 additions & 9 deletions pallets/bonds/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ codec = { default-features = false, features = ["derive"], package = "parity-sca
# HydraDX
hydradx-traits = { workspace = true }
primitives = { workspace = true }
pallet-asset-registry = { workspace = true }

# primitives
sp-runtime = { workspace = true }
sp-std = { workspace = true }
sp-core = { workspace = true }

# FRAME
frame-support = { workspace = true }
Expand All @@ -39,15 +39,12 @@ log = { version = "0.4.17", default-features = false }

# Optional imports for benchmarking
frame-benchmarking = { workspace = true, optional = true }
pallet-balances = { workspace = true, optional = true }
sp-core = { workspace = true, optional = true }
sp-io = { workspace = true, optional = true }
pallet-timestamp = { workspace = true, optional = true }

[dev-dependencies]
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-tracing = { workspace = true }
pallet-balances = { workspace = true }
frame-benchmarking = { workspace = true }
orml-tokens = { workspace = true }
proptest = "1.0.0"
Expand All @@ -64,17 +61,15 @@ std = [
"scale-info/std",
"sp-core/std",
"sp-io/std",
"pallet-balances/std",
"orml-tokens/std",
"pallet-timestamp/std",
"hydradx-traits/std",
"pallet-asset-registry/std",
"primitives/std",
"frame-benchmarking/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"sp-core",
"sp-io",
"pallet-balances",
"pallet-timestamp/runtime-benchmarks"
]
try-runtime = [ "frame-support/try-runtime" ]
111 changes: 111 additions & 0 deletions pallets/bonds/src/benchmarks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// This file is part of Basilisk-node

// Copyright (C) 2020-2022 Intergalactic, Limited (GIB).
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![cfg(feature = "runtime-benchmarks")]

use super::*;

use frame_benchmarking::account;
use frame_benchmarking::benchmarks;
use frame_support::assert_ok;
use frame_system::RawOrigin;
use orml_traits::MultiCurrency;
use sp_std::vec::Vec;

use hydradx_traits::Registry;
use primitives::constants::time::unix_time::MONTH;

pub const NOW: Moment = 1689844300000; // unix time in milliseconds
pub const ONE: u128 = 1_000_000_000_000;
pub const HDX: u32 = 0;

benchmarks! {
where_clause {
where
T::AssetRegistry: Registry<T::AssetId, Vec<u8>, T::Balance, DispatchError>,
T: Config,
T: pallet_timestamp::Config,
T::AssetId: From<u32> + Into<u32>,
T::Balance: From<u32> + From<u128>,
T::TimestampProvider: Time<Moment = Moment>,
T::Moment: From<u64>
}

issue {
pallet_timestamp::Pallet::<T>::set_timestamp(NOW.into());
let issuer: T::AccountId = account("caller", 0, 1);
let amount: T::Balance = (200 * ONE).into();
let maturity = 1893452400000u64; // 1.1.2030
let maturity = NOW + T::MinMaturity::get();

T::Currency::deposit(HDX.into(), &issuer, amount)?;

}: _(RawOrigin::Signed(issuer), HDX.into(), (100 * ONE).into(), maturity)
verify {
let bond_id = RegisteredBonds::<T>::iter_keys().next().unwrap();
assert!(crate::Pallet::<T>::bonds(bond_id).is_some());
}

redeem {
pallet_timestamp::Pallet::<T>::set_timestamp(NOW.into());

let issuer: T::AccountId = account("caller", 0, 1);
let amount: T::Balance = (200 * ONE).into();
T::Currency::deposit(HDX.into(), &issuer, amount)?;

let maturity = NOW + T::MinMaturity::get();

assert_ok!(crate::Pallet::<T>::issue(RawOrigin::Signed(issuer.clone()).into(), HDX.into(), amount, maturity));

let fee = <T as Config>::ProtocolFee::get().mul_ceil(amount);
let amount_without_fee: T::Balance = amount.checked_sub(&fee).unwrap();

pallet_timestamp::Pallet::<T>::set_timestamp((NOW + MONTH).into());

let bond_id = RegisteredBonds::<T>::iter_keys().next().unwrap();

}: _(RawOrigin::Signed(issuer), bond_id, amount_without_fee)
verify {
assert!(crate::Pallet::<T>::bonds(bond_id).is_none());
}

unlock {
pallet_timestamp::Pallet::<T>::set_timestamp(NOW.into());

let issuer: T::AccountId = account("caller", 0, 1);
let amount: T::Balance = (200 * ONE).into();
T::Currency::deposit(HDX.into(), &issuer, amount)?;

let maturity = NOW + T::MinMaturity::get();

assert_ok!(crate::Pallet::<T>::issue(RawOrigin::Signed(issuer).into(), HDX.into(), amount, maturity));

let fee = <T as Config>::ProtocolFee::get().mul_ceil(amount);
let amount_without_fee: T::Balance = amount.checked_sub(&fee).unwrap();

pallet_timestamp::Pallet::<T>::set_timestamp((NOW + T::MinMaturity::get() / 2).into());

let bond_id = RegisteredBonds::<T>::iter_keys().next().unwrap();

}: _(RawOrigin::Root, bond_id)
verify {
let bond_data = crate::Pallet::<T>::bonds(bond_id).unwrap();
assert_eq!(bond_data.maturity, NOW + T::MinMaturity::get() / 2);
}

impl_benchmark_test_suite!(Pallet, crate::tests::mock::ExtBuilder::default().build(), crate::tests::mock::Test);
}
37 changes: 23 additions & 14 deletions pallets/bonds/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,24 @@ use frame_support::{
ArithmeticError, DispatchError, Permill, RuntimeDebug,
},
traits::Time,
BoundedVec, PalletId,
PalletId,
};
use frame_system::{ensure_signed, pallet_prelude::OriginFor};
use scale_info::TypeInfo;
use sp_core::MaxEncodedLen;

use hydradx_traits::BondRegistry;
use orml_traits::MultiCurrency;
use pallet_asset_registry::AssetDetails;
use hydradx_traits::{BondRegistry, Registry};
use orml_traits::{GetByKey, MultiCurrency};
use primitives::Moment;
use sp_std::vec;
use sp_std::vec::Vec;

#[cfg(test)]
mod tests;

#[cfg(any(feature = "runtime-benchmarks", test))]
mod benchmarks;

pub mod weights;

pub use pallet::*;
Expand Down Expand Up @@ -112,13 +116,10 @@ pub mod pallet {
type Currency: MultiCurrency<Self::AccountId, CurrencyId = Self::AssetId, Balance = Self::Balance>;

/// Asset Registry mechanism - used to register bonds in the asset registry
type AssetRegistry: BondRegistry<
Self::AssetId,
Vec<u8>,
Self::Balance,
AssetDetails<Self::AssetId, Self::Balance, BoundedVec<u8, ConstU32<32>>>,
DispatchError,
>;
type AssetRegistry: BondRegistry<Self::AssetId, Vec<u8>, Self::Balance, DispatchError>;

/// Provider for existential deposits of assets
type ExistentialDeposits: GetByKey<Self::AssetId, Self::Balance>;

/// Provider for the current block number.
type TimestampProvider: Time<Moment = Moment>;
Expand All @@ -133,6 +134,8 @@ pub mod pallet {
/// Min amount of bonds that can be created
// type MinAmount: Get<Balance>; TODO: Do we want this param?

// type Deposit: Get<Balance>; TODO: Do we want this param?

/// The origin which can issue new bonds.
type IssueOrigin: EnsureOrigin<Self::RuntimeOrigin>;

Expand Down Expand Up @@ -182,6 +185,8 @@ pub mod pallet {
InsufficientBalance,
/// Bond not registered
BondNotRegistered,
/// Underlying asset is not registered
UnderlyingAssetNotRegistered,
/// Bond is not mature
BondNotMature,
/// Maturity not long enough
Expand Down Expand Up @@ -222,15 +227,19 @@ pub mod pallet {
.ok_or(ArithmeticError::Overflow)?;
ensure!(time_diff >= T::MinMaturity::get(), Error::<T>::InvalidMaturity);

let asset_details = T::AssetRegistry::get_asset_details(asset_id)?;

ensure!(
T::AssetRegistry::exists(asset_id),
Error::<T>::UnderlyingAssetNotRegistered
);
ensure!(
T::Currency::free_balance(asset_id, &who) >= amount,
Error::<T>::InsufficientBalance
);

let asset_ed = T::ExistentialDeposits::get(&asset_id);

// not covered in the tests. Create an asset with empty name should always work
let bond_asset_id = T::AssetRegistry::create_bond_asset(&vec![], asset_details.existential_deposit)?;
let bond_asset_id = T::AssetRegistry::create_bond_asset(asset_ed)?;

let fee = T::ProtocolFee::get().mul_ceil(amount); // TODO: check
let amount_without_fee = amount.checked_sub(&fee).ok_or(ArithmeticError::Overflow)?;
Expand Down
Loading

0 comments on commit 70e51f6

Please sign in to comment.