-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Introduce Vaults pallet (part of the pUSD Project) #10699
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
base: master
Are you sure you want to change the base?
Conversation
| /// 365.25 days × 24 hours × 60 minutes × 60 seconds × 1000 milliseconds = 31,557,600,000 | ||
| const MILLIS_PER_YEAR: u64 = 31_557_600_000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just put the calculation here instead of having it in a comment.
| // Cannot close a vault that's being liquidated | ||
| ensure!(vault.status == VaultStatus::Healthy, Error::<T>::VaultInLiquidation); | ||
|
|
||
| // Update fees |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please tell claude to not over comment stuff. The function name is descriptive enough.
| /// This ensures the Insurance Fund account is created with a provider reference so it can | ||
| /// receive any amount (including below ED) without risk of being reaped. | ||
| fn on_runtime_upgrade() -> Weight { | ||
| let on_chain_version = StorageVersion::get::<Pallet<T>>(); | ||
|
|
||
| if on_chain_version < 1 { | ||
| Self::ensure_insurance_fund_exists(); | ||
| StorageVersion::new(1).put::<Pallet<T>>(); | ||
|
|
||
| log::info!( | ||
| target: LOG_TARGET, | ||
| "Migrated storage from version {:?} to 1", | ||
| on_chain_version | ||
| ); | ||
|
|
||
| // Weight: 1 read (storage version) + 1 read (account_exists) + 2 writes | ||
| // (inc_providers + storage version) | ||
| T::DbWeight::get().reads_writes(2, 2) | ||
| } else { | ||
| log::debug!( | ||
| target: LOG_TARGET, | ||
| "No migration needed, on-chain version {:?}", | ||
| on_chain_version | ||
| ); | ||
| // Weight: 1 read (storage version check) | ||
| T::DbWeight::get().reads(1) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be some extra code in the runtime when we add this pallet.
| // Update cursor for next block | ||
| match last_processed { | ||
| Some(last) => { | ||
| if Vaults::<T>::iter_from(Vaults::<T>::hashed_key_for(&last)).nth(1).is_none() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we are doing one more iteration that isn't part of the weight? Maybe we should just do this at the top of the function.
| remaining_collateral, | ||
| total_obligation, | ||
| )? | ||
| .expect("total_obligation is non-zero; qed"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really a problem to convert this into an error, better safe than sorry here.
| CurrentLiquidationAmount::<T>::mutate(|current| { | ||
| current.saturating_accrue(total_debt); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| CurrentLiquidationAmount::<T>::mutate(|current| { | |
| current.saturating_accrue(total_debt); | |
| }); | |
| CurrentLiquidationAmount::<T>::put(new_liquidation_amount); |
| Self::deposit_event(Event::CollateralWithdrawn { owner: who.clone(), amount }); | ||
|
|
||
| // Remove empty vaults immediately (no collateral + no debt). | ||
| if remaining_collateral.is_zero() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we close a vault, we should call some do_close_vault method that ensures we do the same checks between this function here and close_vault. Because right now it looks like principal handling is different between both methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why these types are not part of the vault crate right now. This code should be clearly not be in this folder.
| } | ||
| } | ||
|
|
||
| /// Mock oracle adapter that provides a fixed price for noe. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
noe = now?
Description
This PR introduces
pallet-vaults, a new FRAME pallet that implements a Collateralized Debt Position (CDP) system for creating over-collateralized stablecoin loans on Substrate-based blockchains. The pallet allows users to lock up DOT as collateral and mint pUSD against it.Integration
For Runtime Developers
To integrate
pallet-vaultsinto your runtime:Cargo.toml:For Pallet Developers
Other pallets can interact with vaults via the
CollateralManagertrait:Review Notes
Key Features
Vault Lifecycle:
create_vault- Create a new Vault and lock initial collateraldeposit_collateral/withdraw_collateral- Manage collateralmint- Borrow pUSD against collateralrepay- Burn pUSD to reduce debt (interest paid first)close_vault- Close debt-free vault, release collateralliquidate_vault- Liquidate unsafe vaultsHold Reasons:
VaultDeposit- Collateral backing active vaultsSeized- Collateral under liquidation, pending auctionTesting
The pallet includes comprehensive tests covering: