Skip to content
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() {
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