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

Merge investor into TOCC #525

Merged
merged 30 commits into from
Dec 1, 2021
Merged

Merge investor into TOCC #525

merged 30 commits into from
Dec 1, 2021

Conversation

branan
Copy link
Contributor

@branan branan commented Nov 23, 2021

No description provided.

Branan Riley and others added 27 commits June 28, 2021 19:43
This expands `close_epoch` to have most of the top-level epoch
closing logic, with most of the meat still stubbed out.
These extrinsics are really an interface to do fake borrowing/payback
until we have a borrower side to interact with. They are renamed to
indicate now that that is what they do.
This removes some confusing code where the terms `pool` or `tranche`
were being used to refer to the id in some cases but the struct data
in others. IDs are now always delimited as such
* Add Reserve

* wip: checkpoint epoch validation

* checkpoint - sub ratio validation

* checkpoint - return errors + simplify balance to perquintil conversion

* address comments 1

* address comments 2

* moved currency/tranchetoken as primitive crate
* Integrates crowdloan pallets to altait

* Pump rt-version 1005, minDep democ 1000 AIR
…e#474)

* Changed validate-unsigned

The changes to the validate unsigned are here to reflect more
detailed error messages at failure with the costum error
instead of the misleading 'BadProof' return value.

Furthermore, this fixes an issue, where somebody could have a
signature of any parachain-relay-chain account and then use
a proof of any other relay-chain contribution to gain those
rewards.

* Enable claim_reward calls

* Remove indicator for claim failures
* Epoch execution phase 1

This is the beginning of epoch execution. It updates tranche state and
stores the execution results, but since token pricing is not yet
implemented it cannot do rebalancing or other bits like that.

* Epoch close pricing calculation

This now calculates a price (including dripping
interest) for the tranches at epoch close.

There are other locations where dripping interest needs to occur, to
come in further commits.

* Store additional state at epoch close

In addition to the per-tranche supply/redeem targets for an epoch, we
now also store the nav, reserve, per-tranche price, and per-tranche
total value at the time of close.

* Update epoch validation tests for new epoch storage model

* Implement tranche rebalancing during epoch execution

This also includes a new `fake_nav` to make testing easier

* Track tranche debt/balance amounts in borrow/repay fns

* Account for updated tranche value in epoch validity

* Fixes for epoch execution / rebalancing

* Epoch execution testing

* Use a less-bad pow() impl for calculating interest

* Avoid rounding issues when round-tripping between currencies
@branan
Copy link
Contributor Author

branan commented Nov 23, 2021

Things left to do:

  • Create a mock reserve so that loan tests don't rely on pool pallet
  • Unify pool creation within the pool pallet

@branan

This comment has been minimized.

@NunoAlexandre
Copy link
Contributor

@branan there are some merge conflicts; and is this PR ready for review?

Copy link
Contributor

@vedhavyas vedhavyas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some questions on the tranche balancing


#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)]
pub struct Tranche<Balance> {
pub interest_per_sec: Perquintill,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any specific reason why we are not using substrate fixed point types?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this needs to be using 27 precision instead of 18

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perquintill is a fixed point type, technically. It's the semantically-correct type for a number which cannot exceed 1.0.

This only stores the base interest rate and is not used as an accumulator. Intermediate values for interest calculations do use 27 decimals. I think 18 decimals is sufficient here, but if we really want to store 27 we should make a Peroctill type

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use the 27 precision

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. I'll add an item to the things-to-do in December to add a Peroctill we can use for 27-decimal proper fractions and update this. Should be a one-liner in our substrate fork and here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this mean we will have to use the fork of substrate again?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're already still using a fork for the other 27-digit fixed points, right? Or did we finally get that upstream?

I may actually use Fixed27 instead of Peroctill, so that the interest is in the form of 1.<rate>. it saves one addition for every interest calculation

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We ware using the main repo on parachain at least. Would prefer to keep it that way 😄

Copy link
Contributor

@vedhavyas vedhavyas Dec 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We dont use the fork anymore. I have moved the macro to our repo. You can already use the macro from runtime-common

@@ -0,0 +1,49 @@
[package]
authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this Cargo toml needs an update

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, still copied from the template

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do a separate PR doing an update here as well?

pallets/tinlake-investor-pool/src/lib.rs Show resolved Hide resolved
) -> DispatchResult {
let owner = ensure_signed(origin)?;

// TODO: Ensure owner is authorized to create a pool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if this is still valid

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this gets lifted out into the pool pallet now, I believe

.map_err(|_| Error::<T>::TrancheId)?,
};
Self::update_tranche_for_epoch(
loc,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have to handle the execution failure so that we have an way to close it through a call

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update_tranche_for_epoch is infallible here, since it can only fail on transfers and has no transfers to make. I can leave a comment to that effect (or add a .expect())

tranche_id: T::TrancheId::try_from(tranche_id)
.map_err(|_| Error::<T>::TrancheId)?,
};
Self::update_tranche_for_epoch(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should handle the failed case down the line for theese storage changes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it probably makes sense to catch that the transfer failed and fail cleanly in one place, with the pool marked as "broken" somehow to prevent further epoch operations until we can fix it with sudo somehow.

That's a big enough change it probably deserves it's own PR separately from the merge work?

tranche.debt = remaining_nav;
tranche.reserve = remaining_reserve;
} else {
tranche.debt = ratio.mul_ceil(nav);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn;t this be the debtratio instead of tranch share of the pool ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't track separate debt and reserve ratios. We track a single pool ratio, and the goal of this step is to readjust the debt/reserve values of each tranche based on the new debt/reserve totals and the tranche's recomputed ratio from the epoch close.

@branan
Copy link
Contributor Author

branan commented Nov 30, 2021

@branan there are some merge conflicts; and is this PR ready for review?

@NunoAlexandre Just needs a rebase on the last couple commits from the borrower benchmarking, it's otherwise ready to go

@NunoAlexandre
Copy link
Contributor

@branan there are some merge conflicts; and is this PR ready for review?

@NunoAlexandre Just needs a rebase on the last couple commits from the borrower benchmarking, it's otherwise ready to go

Do we have a spec this PR is implementing that I can look to for a basis of review?

@branan
Copy link
Contributor Author

branan commented Nov 30, 2021

@NunoAlexandre The point of this PR was really just the merge, which doesn't have its own standalone spec.

It is, however, a convenient place for folks that haven't had eyes on the lender side to comment on things. The overall lender spec is at https://centrifuge.hackmd.io/l1HoQDTUSHKDO8-HbD0NaQ, and the original Tinlake components are the lender folder in the tinlake contracts - especially the coordinator and assessor contracts.

@branan
Copy link
Contributor Author

branan commented Nov 30, 2021

I'm trying not to clutter this PR with changes to the underlying Lender work right now, since the goal here is to get everything in one branch to make continued development more straightforward. I'd like to see this get through once the merge part is unobjectionable, and issues can be filed to fix up anything that folks find while going over this.

@vedhavyas
Copy link
Contributor

@branan it is fine to merge as is but I would suggest we add these relevent issue as either todo(s), or actual issues that we can actively track. Also helps us to what to pick immediately next

@branan
Copy link
Contributor Author

branan commented Nov 30, 2021

Yes, will absolutely file real tickets to track it all.

I'll resolve the merge conflicts momentarily and get things ticketed out this afternoon.

@branan
Copy link
Contributor Author

branan commented Dec 1, 2021

This is re-re-based on top of the TOCC branch with the updates from the final borrower benchmarking PR

@vedhavyas
Copy link
Contributor

@branan okay, merge this up when you are ready. We can talk next steps in sync then :-D

@branan branan merged commit 38926d3 into centrifuge:tocc Dec 1, 2021
Copy link
Collaborator

@mustermeiszer mustermeiszer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit late, but regarding the some important things I wanted to remark here.

Comment on lines +58 to +68
- if: matrix.target == 'build-runtime'
name: Setup - gcloud / gsutil
uses: google-github-actions/setup-gcloud@master
with:
service_account_key: ${{ secrets.GCS_SA_KEY }}
project_id: ${{ secrets.GCS_PROJECT }}
export_default_credentials: true
- if: matrix.target == 'build-runtime'
name: Publish to GCS
run: |
gsutil cp ./runtime/altair/target/srtool/release/wbuild/altair-runtime/altair_runtime.compact.wasm gs://centrifuge-artifact-releases/parachain/altair_runtime-$(git rev-parse --short HEAD).compact.wasm
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where and why do we store the wasms now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @mikiquantum wrote this originally? I'm not sure why we decided to push things to google storage.


#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)]
pub struct Tranche<Balance> {
pub interest_per_sec: Perquintill,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this mean we will have to use the fork of substrate again?

pallets/tinlake-investor-pool/src/lib.rs Show resolved Hide resolved
pallets/tinlake-investor-pool/src/lib.rs Show resolved Hide resolved
pallets/tinlake-investor-pool/src/lib.rs Show resolved Hide resolved
Comment on lines +403 to +429
Order::<T>::try_mutate(&tranche, &who, |order| -> DispatchResult {
if amount > order.redeem {
let transfer_amount = amount - order.redeem;
Pool::<T>::try_mutate(pool_id, |pool| {
let pool = pool.as_mut().ok_or(Error::<T>::NoSuchPool)?;
let epoch_redeem = &mut pool.tranches[tranche_id.into()].epoch_redeem;
*epoch_redeem = epoch_redeem
.checked_add(&transfer_amount)
.ok_or(Error::<T>::Overflow)?;
T::Tokens::transfer(currency, &who, &pool_account, transfer_amount)
})?;
} else if amount < order.redeem {
let transfer_amount = order.redeem - amount;
Pool::<T>::try_mutate(pool_id, |pool| {
let pool = pool.as_mut().ok_or(Error::<T>::NoSuchPool)?;
let epoch_redeem = &mut pool.tranches[tranche_id.into()].epoch_redeem;
*epoch_redeem = epoch_redeem
.checked_sub(&transfer_amount)
.ok_or(Error::<T>::Overflow)?;
T::Tokens::transfer(currency, &pool_account, &who, transfer_amount)
})?;
}
order.redeem = amount;
order.epoch = epoch;
Ok(())
})
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Frontrunning as mentioned above.

Comment on lines +476 to +483
// If closing the epoch would wipe out a tranche, the close is invalid.
// TODO: This should instead put the pool into an error state
ensure!(
!epoch_tranche_prices
.iter()
.any(|price| *price == Zero::zero()),
Error::<T>::WipedOut
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When does this potentially happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only happen if the NAV has dropped precipitously (due to defaults or something like that)

let pool_address = PoolLocator {
pool_id: loc.pool_id,
}
.into_account();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment on PoolLocatpr above.

pool_id: T::PoolId,
amount: T::Balance,
) -> DispatchResult {
let pool_account = PoolLocator { pool_id }.into_account();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment on PoolLocator above.

pallets/tinlake-investor-pool/src/lib.rs Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants