Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CU-1ux3e25 CU-1q4x2t6 CU-1pdtjrz finalizing lending features #546

Merged
merged 14 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

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

9 changes: 3 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@
[![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/composablefi/composable)](https://github.com/composablefi/composable/tags) [![Twitter](https://img.shields.io/badge/Twitter-gray?logo=twitter)](https://twitter.com/ComposableFin) [![Discord](https://img.shields.io/badge/Discord-gray?logo=discord)](https://discord.gg/pFZn2GCn65) [![Telegram](https://img.shields.io/badge/Telegram-gray?logo=telegram)](https://t.me/ComposableFinanceAnnouncements) [![Medium](https://img.shields.io/badge/Medium-gray?logo=medium)](https://composablefi.medium.com/)


Picasso is our custom built kusama parachain, based on the substrate framework.
Picasso is our custom built Kusama parachain, based on the substrate framework.




## Install
## Install

For linux, FreeBSD, OpenBSD and macOS:

Expand All @@ -26,7 +23,7 @@ git clone https://github.com/composableFi/composable
cd composable/
sh scripts/init.sh
cargo build --release
```
```

or you can simply install it with this one liner:

Expand Down
18 changes: 2 additions & 16 deletions frame/bonded-finance/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,3 @@
# Bonded Finance Pallet
# Overview

## Overview

A simple pallet providing means of submitting bond offers.

## Interface

This pallet implements the `BondedFinance` trait from `composable-traits`.

## Dispatchable Functions

- `offer` ― Register a new bond offer, allowing use to later bond it.
- `bond` ― Bond to an offer, the user should provide the number of contracts a user is willing
to buy. On offer completion (a.k.a. no more contract on the offer), the `stake` put by the creator is refunded.
- `cancel_offer` ― Cancel a running offer, blocking further bond but not cancelling the
currently vested rewards. The `stake` put by the creator is refunded.
A simple pallet providing means of submitting bond offers.
34 changes: 20 additions & 14 deletions frame/bonded-finance/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,21 @@
//!
//! A simple pallet providing means of submitting bond offers.
//!
//! ## Interface
//! Alice offers some bond priced in specific assets per bond as some amount of shares.
//! At same time she provides reward asset which will be vested into account which takes bond
//! offers. She locks some native currency to make the offer registered.
//!
//! Bob bonds parts of shares from offer by transfer some asset amount desired by Alice.
//! Bob will be vested part of reward amount during maturity period from that moment.
//! It the end of some period Bob may or may be not be return with amount he provided to Alice -
//! depends on how offer was setup.
//!
//! This pallet implements the `BondedFinance` trait from `composable-traits`.
//! Alice may cancel offer and prevent new bonds on offer, she gets her native tokens back.
//! All existing vesting periods continue to be executed.
//!
//! ## Dispatchable Functions
//! ## Interface
//!
//! - `offer` - Register a new bond offer, allowing use to later bond it.
//! - `bond` - Bond to an offer, the user should provide the number of nb_of_bonds a user is willing
//! to buy.
//! - `cancel_offer` - Cancel a running offer, blocking further bond but not cancelling the
//! currently vested rewards.
//! This pallet implements the `composable_traits::bonded_finance::BondedFinance`.

mod benchmarks;
mod mock;
Expand Down Expand Up @@ -194,7 +198,7 @@ pub mod pallet {

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Create a new offer.
/// Create a new offer. So later can `bond` it.
///
/// The dispatch origin for this call must be _Signed_ and the sender must have the
/// appropriate funds.
Expand All @@ -208,6 +212,9 @@ pub mod pallet {
}

/// Bond to an offer.
/// And user should provide the number of contracts she is willing to buy.
/// On offer completion (a.k.a. no more contract on the offer), the `stake` put by the
/// creator is refunded.
///
/// The dispatch origin for this call must be _Signed_ and the sender must have the
/// appropriate funds.
Expand All @@ -225,12 +232,12 @@ pub mod pallet {
Ok(())
}

/// Cancel an offer.
///
/// Cancel a running offer. Blocking further bond but not cancelling the
/// currently vested rewards. The `stake` put by the creator is refunded.
/// The dispatch origin for this call must be _Signed_ and the sender must be `AdminOrigin`
///
/// Emits a `OfferCancelled`.
#[pallet::weight(10_000)]
#[pallet::weight(10_000)] // TODO: add weights
#[transactional]
pub fn cancel(origin: OriginFor<T>, offer_id: T::BondOfferId) -> DispatchResult {
let (issuer, offer) = Self::get_offer(offer_id)?;
Expand Down Expand Up @@ -315,7 +322,7 @@ pub mod pallet {
nb_of_bonds <= offer.nb_of_bonds,
Error::<T>::InvalidNumberOfBonds
);
// NOTE(hussein-aitlahcen): can't overflow, subsumed by `offer.valid()` in
// can't overflow, subsumed by `offer.valid()` in
// `do_offer`
let value = nb_of_bonds * offer.bond_price;
let reward_share = T::Convert::convert(
Expand Down Expand Up @@ -355,7 +362,6 @@ pub mod pallet {
)?;
},
BondDuration::Infinite => {
// NOTE(hussein-aitlahcen): in the case of an inifite duration for
// the offer, the liquidity is never returned to the bonder, meaning
// that the protocol is now owning the funds.
},
Expand Down
1 change: 1 addition & 0 deletions frame/bonded-finance/src/proptest-regressions/tests.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cc e005bce405358673d3249e53d51e474d4b135bdf8f2b0b82f94f525c0efbdbf8 #Test failed: 190000000 * 1000 / 190500000 = 997375328083989501 != 1000 at frame/bonded-finance/src/tests.rs:404; minimal failing input: offer = BondOffer { beneficiary: 1, asset: BTC, bond_price: 1000000, nb_of_bonds: 381, maturity: BondDuration::Infinite, reward: BondOfferReward { asset: ETH, amount: 381000000, maturity: 1 } }
40 changes: 38 additions & 2 deletions frame/bonded-finance/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,42 @@ prop_compose! {
}
}

#[test]
fn bond_offer_cc_e005bce405358673d3249e53d51e474d4b135bdf8f2b0b82f94f525c0efbdbf8() {
dzmitry-lahoda marked this conversation as resolved.
Show resolved Hide resolved
ExtBuilder::build()
.execute_with(|| {
let offer = BondOffer {
beneficiary: 1,
asset: MockCurrencyId::BTC,
bond_price: 1000000,
nb_of_bonds: 381,
maturity: BondDuration::Infinite,
reward: BondOfferReward {
asset: MockCurrencyId::ETH,
amount: 381000000,
maturity: 1,
},
};
prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get()));
prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount));
let half_nb_of_bonds = offer.nb_of_bonds / 2;
let half_reward = offer.reward.amount / 2;
prop_assert_ok!(Tokens::mint_into(
offer.asset,
&BOB,
half_nb_of_bonds * offer.bond_price
));

let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()).unwrap();

let bob_reward = BondedFinance::do_bond(offer_id, &BOB, half_nb_of_bonds).unwrap();
prop_assert_acceptable_computation_error!(bob_reward, half_reward, 3);

Ok(())
})
.unwrap();
}

proptest! {
#![proptest_config(ProptestConfig::with_cases(10_000))]

Expand Down Expand Up @@ -401,8 +437,8 @@ proptest! {
prop_assert_ok!(charlie_reward);
let charlie_reward = charlie_reward.expect("impossible; qed;");

prop_assert_acceptable_computation_error!(bob_reward, half_reward);
prop_assert_acceptable_computation_error!(charlie_reward, half_reward);
prop_assert_acceptable_computation_error!(bob_reward, half_reward, 3);
prop_assert_acceptable_computation_error!(charlie_reward, half_reward, 3);

prop_assert!(Tokens::can_withdraw(offer.reward.asset, &BOB, bob_reward) == WithdrawConsequence::Frozen);
prop_assert!(Tokens::can_withdraw(offer.reward.asset, &CHARLIE, charlie_reward) == WithdrawConsequence::Frozen);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::{
slice::SliceIndex,
};
use frame_support::{traits::Get, BoundedVec};
use sp_std::{convert::TryFrom, fmt, marker::PhantomData, prelude::*};
use sp_std::{convert::TryFrom, marker::PhantomData, prelude::*};

/// A bounded, sorted vector.
///
Expand Down Expand Up @@ -137,12 +137,12 @@ impl<T: Ord, S> Default for BoundedSortedVec<T, S> {
}

#[cfg(feature = "std")]
impl<T: Ord, S> fmt::Debug for BoundedSortedVec<T, S>
impl<T: Ord, S> sp_std::fmt::Debug for BoundedSortedVec<T, S>
where
T: fmt::Debug,
T: sp_std::fmt::Debug,
S: Get<u32>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result {
f.debug_tuple("BoundedVec").field(&self.0).field(&Self::bound()).finish()
}
}
Expand Down
Loading