-
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
Waiting to generate the weights after the implementation is approved.
substrate/frame/vaults/src/lib.rs
Outdated
| /// 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.
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.
Addressed in 054c6e6.
substrate/frame/vaults/src/lib.rs
Outdated
| // 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.
substrate/frame/vaults/src/lib.rs
Outdated
| /// 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.
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.
Removed in 65030aa. I also changed the StorageVersion to 0.
substrate/frame/vaults/src/lib.rs
Outdated
| // 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.
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.
Reworked a bit in 054c6e6.
substrate/frame/vaults/src/lib.rs
Outdated
| 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.
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.
Converted the .expects into errors in 054c6e6.
| 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.
Consolidated the logic into a a do_close_vault method in 8d87807.
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.
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.
These types will be reused by the other pallets in the pUSD family. Currently they're only used by this pallet, but once we start adding the other pallets, they'll be imported from this common crate. If you have a suggestion for better placement, I'm happy to move them accordingly!
| } | ||
| } | ||
|
|
||
| /// 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?
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.
Fixed in ff5479b.
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: