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

Loans: Add multiple triggers for write-off #1314

Merged
merged 21 commits into from Apr 18, 2023
Merged

Conversation

lemunozm
Copy link
Contributor

@lemunozm lemunozm commented Apr 11, 2023

Description

Fixes #1305

Tasks

  • Changes
  • migration

Changes

  • Refactor WriteOffState::overdue_days to WriteOffState::triggers of type WriteOffTrigger enum.
  • Refactor WriteOffState::{penalty, percentage} removed and used instead of the WriteOffStatus` that already contains that information.
  • Renamed WriteOffState to WriteOffRule.
  • Find the best rule now is based of percentage and penalty instead of overdue_days

@lemunozm lemunozm added Q3-medium Can be done with good experience in the language, but little knowledge of the codebase. P5-soon Issue should be addressed soon. D5-breaks-api Pull request changes public api. Document changes publicly. crcl-protocol Circle protocol related. D8 - migration labels Apr 11, 2023
@lemunozm lemunozm self-assigned this Apr 11, 2023
@lemunozm
Copy link
Contributor Author

Initial commit from Jeroen at: bf77eb6

Copy link
Contributor Author

@lemunozm lemunozm left a comment

Choose a reason for hiding this comment

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

Some explanations of core parts:

pallets/loans-ref/src/lib.rs Show resolved Hide resolved
pallets/loans-ref/src/lib.rs Outdated Show resolved Hide resolved
pallets/loans-ref/src/types.rs Outdated Show resolved Hide resolved
pallets/loans-ref/src/types.rs Show resolved Hide resolved
@lemunozm lemunozm marked this pull request as ready for review April 13, 2023 12:08
@lemunozm
Copy link
Contributor Author

Changes are ready for review. Migration is still pending

Copy link
Contributor

@hieronx hieronx left a comment

Choose a reason for hiding this comment

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

The new policy implementation looks great to me!

@lemunozm
Copy link
Contributor Author

lemunozm commented Apr 14, 2023

@wischli I think the migration is ok (tested in altair and centrifuge), but it would be awesome if you could give a fast review in case you see something weird. It's the v1. Thanks 🙌🏻

EDIT: based on #1198 (comment) I think I need to add it too to development

@lemunozm
Copy link
Contributor Author

This is ready for a final review

hieronx
hieronx previously approved these changes Apr 17, 2023
pallets/loans-ref/src/write_off.rs Show resolved Hide resolved
Copy link
Contributor

@wischli wischli left a comment

Choose a reason for hiding this comment

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

I only have a few nitpicks. The migration read-write-count is off by one but the rest looks splendid to me, great work again!

@@ -473,7 +480,7 @@ pub mod pallet {
/// - Write off by admin with percentage 0.5 and penalty 0.2
/// - Time passes and the policy can be applied.
/// - Write of with a policy that says: percentage 0.3, penaly 0.4
/// - The loan is written off with the maximum between the policy and the current state:
/// - The loan is written off with the maximum between the policy and the current rule:
/// percentage 0.5, penaly 0.4
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit

Suggested change
/// percentage 0.5, penaly 0.4
/// percentage 0.5, penalty 0.4

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Realizing that only means you did a deep review, thanks!!

/// - overdue_days: 15, percentage 20%
///
/// If the loan is not overdue, it will not return any rule.
/// If the loan overdue by 4 days, it will not return any rule.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit

Suggested change
/// If the loan overdue by 4 days, it will not return any rule.
/// If the loan is overdue by 4 days, it will not return any rule.

@@ -679,16 +688,38 @@ pub mod pallet {
})
}

fn find_write_off_state(
/// From all overdue write off rules, it returns the one has highest percentage
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit

Suggested change
/// From all overdue write off rules, it returns the one has highest percentage
/// From all overdue write off rules, it returns the one with the highest percentage

.filter_map(|rule| {
rule.triggers
.iter()
.map(|trigger| loan.check_write_off_trigger(&trigger.0))
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Maybe it would be better to destructure into the 0th tuple element directly to make it more explicit?

Suggested change
.map(|trigger| loan.check_write_off_trigger(&trigger.0))
.map(|(trigger, _)| loan.check_write_off_trigger(&trigger))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It has only one element, the map part should be something like .map(|UniqueWriteOffTrigger(trigger)|), which maybe is more confusing (line breaks and adds a new indentation). It if was a tuple, I'd agree with you.


log::info!("Successful migration: v0 -> v1. Items: {count}");

T::DbWeight::get().reads_writes(count, count)
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: It's actually count + 1 since we read and write the StorageVersion:

Suggested change
T::DbWeight::get().reads_writes(count, count)
T::DbWeight::get().reads_writes(count.saturating_add(1), count.saturating_add(1))

You could also initialize count = 1 and log

		log::info!("Successful migration: v0 -> v1. Items: {count.saturating_sub(1)}");

Copy link
Contributor Author

@lemunozm lemunozm Apr 18, 2023

Choose a reason for hiding this comment

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

I thought the same at first, but then I checked some substrate pallets, and there, Substrate returns Weight::zero() after reading the StorageVersion, which maybe means the version is something stored in the memory, not in the database 🤔.

I've tried to check if I'm right, but it's done procedurally...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Anyways adding 1 does not hurt!

Comment on lines +82 to +96
old_policy
.into_iter()
.zip(new_police)
.all(|(old_vector, new_vector)| {
let mut policy = old_vector.iter().zip(new_vector.iter());
policy.all(|(old, new)| {
*new == WriteOffRule::new(
[WriteOffTrigger::PrincipalOverdueDays(old.overdue_days)],
old.percentage,
old.penalty,
)
})
})
.then_some(())
.ok_or("Error: policies differ")
Copy link
Contributor

Choose a reason for hiding this comment

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

Very elegantly written assertion 😍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! ❤️

Copy link
Contributor

@wischli wischli left a comment

Choose a reason for hiding this comment

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

Thanks for baking in my comments, looks great!

@lemunozm lemunozm merged commit a564e8f into main Apr 18, 2023
11 checks passed
@lemunozm lemunozm deleted the feature/write-off-triggers branch April 18, 2023 08:26
TypeInfo,
RuntimeDebug,
MaxEncodedLen,
EnumCount,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need that?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's used to bound the triggers vec (as the triggers need to be unique, thus the bound should be on the number of variants in this enum)

Comment on lines +39 to +43
pub mod migrations {
pub mod nuke;
pub mod v1;
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

We should not keep them around forever or hide them behind a feature flag to not bloat the wasm. But rather minor.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Once the migration is not used, the unused code should be removed from the wasm. Until I know, Substrate passes wasm-opt that removes unused symbols/code and things like those.

PrincipalOverdueDays(u32),

/// Seconds since the oracle valuation was last updated
OracleValuationOutdated(Moment),
Copy link
Collaborator

Choose a reason for hiding this comment

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

What do we think we need this for? in which scenario will this be a trigger?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When an oracle, has not updated a price for a long time, the chain logic somehow differs from the real value of that price, and affects to the portfolio valuation, so we need to write off that loan in a percentage if it exceeds the maximum updated period for its price.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crcl-protocol Circle protocol related. D5-breaks-api Pull request changes public api. Document changes publicly. P5-soon Issue should be addressed soon. Q3-medium Can be done with good experience in the language, but little knowledge of the codebase.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Loans: Write off policy with different triggers
4 participants