Releases: mrgnlabs/marginfi-v2
mrgn-0.1.8
Summary
Orders
Introduces "Orders". An Order is a stop-loss and/or take-profit trigger that a "Keeper" can permissionlessly execute. For example, a user is lending $100 in SOL and borrowing $50 in BONK. They set a take-profit at $70. If SOL goes to $120, the Keeper can execute, closing their BONK position and leaving them with $70 in SOL. A Keeper can also execute if BONK falls to $30, likewise leaving the user with $70 in SOL.
Project Zero will run Keepers initially upon feature public launch (ETA Q2/Q3 2026), but any third-party can run a Keeper. Users configure their max slippage tolerance when setting the order, Keepers are permitted to keep whatever is leftover after completing the order execution as profit, and they also get to keep the rent from the Order (currently worth about $0.25). If you are an integrator expecting to use this feature, you are strongly recommended to run your own Keepers. Keepers are permissionless, any wallet can be a Keeper.
Juplend
Juplend banks can now be used as collateral! See JUPLEND_INTEGRATION.md for more details of how juplend banks work.
Other
"Rate Limiter" feature: Implements a sliding window rate limiter system at both bank and group levels to protect against rapid fund extraction. Limits are net outflow: outflows minus inflows, so deposits/repays offset usage. Banks enforce a daily limit in tokens, and the group (all banks that live on the 0.xyz app) enforces a USD limit. Flashloans and liquidations do not affect the window.
Substantial reductions in CU and heap usage, especially in receivership liquidation flows, enabling liquidators to burn more CU on other tasks, especially for accounts with more positions.
Breaking Changes (Rust Integrators only)
lending_account_deposit:groupaccount is now writable (mut).lending_account_repay:groupaccount is now writable (mut); forrepay_all = truethere is new remaining-accounts validation requiring risk accounts for all active balances.lending_account_borrow:groupaccount is now writable (mut).kamino_deposit,solend_deposit,drift_deposit:groupaccount is now writable (mut).lending_pool_pulse_bank_price_cache:groupaccount is now writable (mut).
Breaking Changes (everyone)
lending_account_withdraw,kamino_withdraw,solend_withdraw,drift_withdraw: withwithdraw_all = true, now requires the bank being withdrawn to be passed last in risk accounts (formerly omitted entirely).
Example
User has balances:
[0] kamino bank (0)
[1] some balance being closed upon withdraw_all (1)
[2] drift bank (2)
[3] some mrgn bank (3)
Before this update:
[bank0, oracle0, kamino_reserve0],
[bank2, oracle2, drift_spot_market2],
[bank3, oracle3],
After this update:
[bank0, oracle0, kamino_reserve0],
[bank2, oracle2, drift_spot_market2],
[bank3, oracle3],
[bank1, oracle1, ....other accounts if this is kamino/drift/jup],
Noting that the bank to closed does NOT respect the all-accounts-must-be-ordered-by-bank rule: it is always passed last.
New Accounts
Order- tracks information about a single take-profit and/or stop-loss order for an asset/liability pair on the user's account.ExecuteOrderRecord- an ephemeral account that is always closed in the same TX it is opened in, used to pass information between the start and end of order execution. None of these should exist in production.
New Instructions
Orders
PlaceOrder(user) - Place a new Stop Loss, Take Profit, or Both type Order on a pair of balances the user currently holds.StartExecuteOrder(Keeper) - Keepers run this to begin the execution of an Order. Must be at the start of the tx, andEndExecuteOrdermust appear last in the tx. Withdraw/Repay of the involved balances typically follows this ix. Requires a risk check of just the balances involved in the Order.EndExecuteOrder(Keeper) - Must be the last tx in executing an Order. Requires a risk check of just the balances involved in the Order.CloseOrder(user) - Clear an unwanted Order, user gets their rent back.SetKeeperCloseFlags(user) - Enables the Keeper to close Orders viaKeeperCloserOrder, typically useCloseOrderinstead.KeeperCloseOrder(Keeper) - Close an Order on an account where neither of the original positions exists or all the tags have been cleared by the user
Juplend
lendingPoolAddBank_juplend(admin) - Adds a wrapped JupLend bank to a group. The bank starts
inPausedstate and is unusable untiljuplend_init_positionruns.juplendInitPosition(permissionless, one-time per bank) - Performs a seed deposit into JupLend
and flips the bank fromPausedtoOperational. This activates the bank for user flows.juplendDeposit(amount)(user) - Deposit underlying tokens (native amount). Internally calls
JupLendupdateRate, deposits through CPI, verifies minted fTokens, and credits the user's
marginfi position.juplendWithdraw(amount, withdraw_all)(user) - Withdraw underlying tokens (native amount).
Internally calls JupLendupdateRate, burns fTokens via CPI, then transfers tokens from the
withdraw intermediary ATA to the user's destination token account.
Other
configureBankRateLimits(admin) - Configure hourly/daily bank-level outflow limits for withdraw/borrow (in native token units).configureGroupRateLimits(admin) - Configure hourly/daily group-level aggregate outflow limits (in USD). Same net-outflow model, applied across the group.
Changes to Existing Instructions
Admin-only
marginfi_group_configure: admin key args changed from requiredPubkeytoOption<Pubkey>(new_admin,new_emode_admin,new_curve_admin,new_limit_admin,new_emissions_admin,new_metadata_admin,new_risk_admin), whereNonenow means "leave unchanged".init_global_fee_stateandedit_global_fee_state: added argsorder_init_flat_sol_feeandorder_execution_max_fee.lending_pool_update_emissions_parameters: Fixed a bug where the emissions admin could update other flags.
User
lending_account_deposit:groupaccount is now writable (mut).lending_account_repay:groupaccount is now writable (mut); forrepay_all = truethere is new remaining-accounts validation requiring risk accounts for all active balances.lending_account_borrow:groupaccount is now writable (mut).kamino_deposit,solend_deposit,drift_deposit:groupaccount is now writable (mut).lending_pool_pulse_bank_price_cache:groupaccount is now writable (mut).lending_account_withdraw,kamino_withdraw,solend_withdraw,drift_withdraw: withwithdraw_all = true, now requires the bank being withdrawn to be passed last in risk accounts (formerly omitted entirely).lending_account_repay,lending_account_withdraw,kamino_withdraw,drift_withdrawnow allowed during order-execution context.
Liquidator
start_liquidationinstruction gating was extended: allowed pre-actions now include JuplendupdateRate; allowed body instructions now includeJUPLEND_WITHDRAW.start_liquidation,start_deleverage,end_liquidation,end_deleverage,lending_account_start_flashloan, andlending_account_end_flashloancannot run during Order execution.
Changes to Existing Accounts
FeeState- Added
order_init_flat_sol_fee: u32- a fixed fee paid to open Orders - Added
order_execution_max_fee: WrappedI80F48- Max profit Keepers can earn
- Added
MarginfiGroup:- Added
rate_limiter(seeGroupRateLimiter) - used to enforce global withdrawal windows
- Added
Bank(existing account):- Added
rate_limiter(seeBankRateLimiter) - used to enforce per-bank withdrawal windows BankCache(inBank) - various read-only fields used in receivership liquidation
*liq_cache_flags: u8
*liquidation_price_rt: WrappedI80F48
*liquidation_price_rt_confidence: WrappedI80F48
*liquidation_price_twap: WrappedI80F48
*liquidation_price_twap_confidence: WrappedI80F48
- Added
MarginfiAccount- Added flag bit
ACCOUNT_IN_ORDER_EXECUTION = 1 << 7. LendingAccount(inMarginfiAccount):- Added
last_tag_used: u16- Enables Balances to have a unique tag for Orders
- Added
Balance(inLendingAccount):- Added
tag: u16- used for orders, not to be confused withbank_asset_tag
- Added
- Added flag bit
OracleSetup(used in Bank config), added variants:FixedKamino = 13FixedDrift = 14JuplendPythPull = 15JuplendSwitchboardPull = 16FixedJuplend = 17
Other Information
Consolidates
Minor bugfixes
- Fixes an issue where the
test-program-remixscript corrupts metadata and requires ananchor cleanwhen the program is updated, however the tests now build to a different target directory, which increases disk usage. - Partially fixes a
BlockhashNotFoundsome longer Rust tests occasionally run into.
Credits
Thank you to https://github.com/abelmarnk for contributing most of the work to the Orders feature.
Audit Information
TBD
Release information
Staging (stag8sTKds2h4KzjUw3zKTsxbqvT4XKHdaR9X9E6Rct) - Approximately Feb 18, 2026
Mainnet - ETA late March 2026
mrgn - 0.1.7a
Changes since 0.1.7-rc3
- Fixes a bug where Drift refresh instructions were forbidden during receivership liquidation
Deployed Mainnet: Jan 27 @ ~ 6pm ET - hash 59e065
mrgn - 0.1.7-rc3
Summary
Adds Drift and Solend support for P0, enabling Drift and Solend (aka "Save") positions to be used as collateral for borrowing on P0!
Removes deprecated Arena features.
Reduce-only banks no longer count towards borrowing power. Existing account health is not affected, only new borrows.
Adds compliance functionality for AML or similar requests, enabling the administrator to freeze accounts if e.g. served with a court order demanding it. Our foundation is committed not to freeze any account unless legally ordered to do.
Terminology Notes
Drift calls their Bank-equivalent "Markets" and Solend calls them "Reserves". A "Bank" on P0 tracks a single Drift Market or Solend Reserve, much like Kamino banks track a single Kamino Reserve.
Changes since rc1
Changed the way integration accounts are stored on the Bank (see changes to Bank below)
Changes since rc2
- Fixed a bug where the price cache wasn't being updated for Drift/Solend banks
- Minor doc updates, updated terms of security policy
- Minor logging improvements
Breaking Changes
Liquidators and other parties that index all banks must now accommodate for Drift and Solend banks. To detect if a Bank uses a Kamino, Drift, or Solend integration, check the config.asset_tag, and then read integration_acc_1/2/3 to get the associated Reserve, Obligation, etc as needed.
If you were using the kamino_reserve or kamino_obligation fields, note that the names have changed (see Updated Fields, but they are in the same location in the buffer.
Instructions
New Instructions (users)
- drift_deposit - deposit collateral to a drift bank to be used as collateral on P0.
- drift_withdraw - withdraw collateral from a drift position
- solend_deposit - - deposit collateral to a solend bank to be used as collateral on P0.
- solend_withdraw - withdraw collateral from a solend position
- (permissionless) lending_pool_pulse_bank_price_cache - refresh a bank's price cache, enabling read-only viewing of the price currently observed by the bank from its oracle (note: all instructions that consume prices now also update the same cached value).
New Instructions (admin only)
- (admin) lending_pool_add_bank_drift - create a new drift bank
- (permissionless) drift_init_user - called after
lending_pool_add_bank_driftto complete Drift bank configuration. - (permissionless) drift_harvest_reward - shifts earned Drift rewards into the admin's global fee wallet to be distributed to depositors OTC
- (admin) lending_pool_add_bank_solend - create a new solend bank
- solend_init_obligation - called after
lending_pool_add_bank_solendto complete Solend bank configuration. - (admin) set_account_freeze - toggle freeze on/off. Frozen accounts are unable to perform any action that modifies their balances. The admin will use this to comply with court-ordered legal obligations e.g. AML.
Changes to Existing Instructions (users)
None
Changes to Existing Instructions (admin only)
- initialize_group - removed
is_arena_grouparg - configure - removed
is_arena_grouparg, addedemode_max_init_leverageandemode_max_maint_leverage.
Updated Fields
MarginfiGroup
- emode_max_init_leverage/emode_max_maint_leverage - controls the maximum allowed leverage used in emode for all banks in this group. Used to ensure even the emode admin is unable to accidentally set "infinite" or "under-collateralized" leverage.
Bank
- integration_acc_1 (formerly kamino_reserve) - For Drift banks, the associated Market. For Solend banks, the associated Reserve. For Kamino banks, also the associated Reserve. For all other bank types, does nothing.
- integration_acc_2 (formerly kamino_obligation) - For Drift banks, the associated user account, which all depositors into this bank share. For Solend banks, the associated Obligation, which all depositors into this bank share. For Kamino banks, also the associated Obligation. For all other bank types, does nothing.
- integration_acc_3 - for Drift banks, the associated user stats, which all depositors into this bank share. For all other bank types, does nothing.
Bank.cache
For any instruction which consumes a price, the bank caches now stores that last-used price for better read-only insight into the price used by a Bank. If a Bank's timestamp is sufficiently recent, lazy consumers can use these values of lieu of fetching an actual price, but should not treat it as authoritative once the Bank's last updated timestamp is sufficiently old.
- last_oracle_price
- last_oracle_price_timestamp
- last_oracle_price_confidence
MarginfiAccount
- account_flags - added
ACCOUNT_FROZENoption (1 << 6)
Notes on Drift Rewards
Drift rewards paid in the same token (e.g. USDS rewards for the USDS Market) are automatically credited to depositors at the program level, no special claim instruction is required. Drift rewards paid in a different token (E.g. JTO incentives for the SOL Market), as well as special rewards which Drift itself might "admin deposit" directly to accounts as part of various campaigns, are sent to the administrator's fee wallet, and will be distributed to users like other incentives (typically via weekly airdrop). We will announce how FUEL incentives will be handled at a later date.
Consolidates
Audits
See attached
Release Times
Staging - ~Jan 20
Mainnet - Jan 27 @ 11AM ET
mrgn - 0.1.7-rc2
Summary
Adds Drift and Solend support for P0, enabling Drift and Solend (aka "Save") positions to be used as collateral for borrowing on P0!
Removes deprecated Arena features.
Reduce-only banks no longer count towards borrowing power. Existing account health is not affected, only new borrows.
Adds compliance functionality for AML or similar requests, enabling the administrator to freeze accounts if e.g. served with a court order demanding it. Our foundation is committed not to freeze any account unless legally ordered to do.
Terminology Notes
Drift calls their Bank-equivalent "Markets" and Solend calls them "Reserves". A "Bank" on P0 tracks a single Drift Market or Solend Reserve, much like Kamino banks track a single Kamino Reserve.
Changes since rc1
Changed the way integration accounts are stored on the Bank (see changes to Bank below)
Breaking Changes
Liquidators and other parties that index all banks must now accommodate for Drift and Solend banks. To detect if a Bank uses a Kamino, Drift, or Solend integration, check the config.asset_tag, and then read integration_acc_1/2/3 to get the associated Reserve, Obligation, etc as needed.
If you were using the kamino_reserve or kamino_obligation fields, note that the names have changed (see Updated Fields, but they are in the same location in the buffer.
Instructions
New Instructions (users)
- drift_deposit - deposit collateral to a drift bank to be used as collateral on P0.
- drift_withdraw - withdraw collateral from a drift position
- solend_deposit - - deposit collateral to a solend bank to be used as collateral on P0.
- solend_withdraw - withdraw collateral from a solend position
- (permissionless) lending_pool_pulse_bank_price_cache - refresh a bank's price cache, enabling read-only viewing of the price currently observed by the bank from its oracle (note: all instructions that consume prices now also update the same cached value).
New Instructions (admin only)
- (admin) lending_pool_add_bank_drift - create a new drift bank
- (permissionless) drift_init_user - called after
lending_pool_add_bank_driftto complete Drift bank configuration. - (permissionless) drift_harvest_reward - shifts earned Drift rewards into the admin's global fee wallet to be distributed to depositors OTC
- (admin) lending_pool_add_bank_solend - create a new solend bank
- solend_init_obligation - called after
lending_pool_add_bank_solendto complete Solend bank configuration. - (admin) set_account_freeze - toggle freeze on/off. Frozen accounts are unable to perform any action that modifies their balances. The admin will use this to comply with court-ordered legal obligations e.g. AML.
Changes to Existing Instructions (users)
None
Changes to Existing Instructions (admin only)
- initialize_group - removed
is_arena_grouparg - configure - removed
is_arena_grouparg, addedemode_max_init_leverageandemode_max_maint_leverage.
Updated Fields
MarginfiGroup
- emode_max_init_leverage/emode_max_maint_leverage - controls the maximum allowed leverage used in emode for all banks in this group. Used to ensure even the emode admin is unable to accidentally set "infinite" or "under-collateralized" leverage.
Bank
- integration_acc_1 (formerly kamino_reserve) - For Drift banks, the associated Market. For Solend banks, the associated Reserve. For Kamino banks, also the associated Reserve. For all other bank types, does nothing.
- integration_acc_2 (formerly kamino_obligation) - For Drift banks, the associated user account, which all depositors into this bank share. For Solend banks, the associated Obligation, which all depositors into this bank share. For Kamino banks, also the associated Obligation. For all other bank types, does nothing.
- integration_acc_3 - for Drift banks, the associated user stats, which all depositors into this bank share. For all other bank types, does nothing.
Bank.cache
For any instruction which consumes a price, the bank caches now stores that last-used price for better read-only insight into the price used by a Bank. If a Bank's timestamp is sufficiently recent, lazy consumers can use these values of lieu of fetching an actual price, but should not treat it as authoritative once the Bank's last updated timestamp is sufficiently old.
- last_oracle_price
- last_oracle_price_timestamp
- last_oracle_price_confidence
MarginfiAccount
- account_flags - added
ACCOUNT_FROZENoption (1 << 6)
Notes on Drift Rewards
Drift rewards paid in the same token (e.g. USDS rewards for the USDS Market) are automatically credited to depositors at the program level, no special claim instruction is required. Drift rewards paid in a different token (E.g. JTO incentives for the SOL Market), as well as special rewards which Drift itself might "admin deposit" directly to accounts as part of various campaigns, are sent to the administrator's fee wallet, and will be distributed to users like other incentives (typically via weekly airdrop). We will announce how FUEL incentives will be handled at a later date.
Consolidates
Audits
TBD
Release Times
Staging - TBD
Mainnet - TBD (ETA ~ January 23)
mrgn - 0.1.7-rc1
Summary
Adds Drift and Solend support for P0, enabling Drift and Solend (aka "Save") positions to be used as collateral for borrowing on P0!
Removes deprecated Arena features.
Reduce-only banks no longer count towards borrowing power. Existing account health is not affected, only new borrows.
Adds compliance functionality for AML or similar requests, enabling the administrator to freeze accounts if e.g. served with a court order demanding it. Our foundation is committed not to freeze any account unless legally ordered to do.
Terminology Notes
Drift calls their Bank-equivalent "Markets" and Solend calls them "Reserves". A "Bank" on P0 tracks a single Drift Market or Solend Reserve, much like Kamino banks track a single Kamino Reserve.
Breaking Changes
Liquidators and other parties that index all banks must now accommodate for Drift and Solend banks.
Instructions
New Instructions (users)
- drift_deposit - deposit collateral to a drift bank to be used as collateral on P0.
- drift_withdraw - withdraw collateral from a drift position
- solend_deposit - - deposit collateral to a solend bank to be used as collateral on P0.
- solend_withdraw - withdraw collateral from a solend position
- (permissionless) lending_pool_pulse_bank_price_cache - refresh a bank's price cache, enabling read-only viewing of the price currently observed by the bank from its oracle (note: all instructions that consume prices now also update the same cached value).
New Instructions (admin only)
- (admin) lending_pool_add_bank_drift - create a new drift bank
- (permissionless) drift_init_user - called after
lending_pool_add_bank_driftto complete Drift bank configuration. - (permissionless) drift_harvest_reward - shifts earned Drift rewards into the admin's global fee wallet to be distributed to depositors OTC
- (admin) lending_pool_add_bank_solend - create a new solend bank
- solend_init_obligation - called after
lending_pool_add_bank_solendto complete Solend bank configuration. - (admin) set_account_freeze - toggle freeze on/off. Frozen accounts are unable to perform any action that modifies their balances. The admin will use this to comply with court-ordered legal obligations e.g. AML.
Changes to Existing Instructions (users)
None
Changes to Existing Instructions (admin only)
- initialize_group - removed
is_arena_grouparg - configure - removed
is_arena_grouparg, addedemode_max_init_leverageandemode_max_maint_leverage.
Updated Fields
MarginfiGroup
- emode_max_init_leverage/emode_max_maint_leverage - controls the maximum allowed leverage used in emode for all banks in this group. Used to ensure even the emode admin is unable to accidentally set "infinite" or "under-collateralized" leverage.
Bank
- drift_spot_market - for Drift banks, the associated Market. For all other bank types, does nothing.
- drift_user - for Drift banks, the associated user account, which all depositors into this bank share. For all other bank types, does nothing.
- drift_user_stats - for Drift banks, the associated user stats, which all depositors into this bank share. For all other bank types, does nothing.
- solend_reserve - for Solend banks, the associated Reserve. For all other bank types, does nothing.
- solend_obligation - for Solend banks, the associated Obligation, which all depositors into this bank share. For all other bank types, does nothing.
Bank.cache
For any instruction which consumes a price, the bank caches now stores that last-used price for better read-only insight into the price used by a Bank. If a Bank's timestamp is sufficiently recent, lazy consumers can use these values of lieu of fetching an actual price, but should not treat it as authoritative once the Bank's last updated timestamp is sufficiently old.
- last_oracle_price
- last_oracle_price_timestamp
- last_oracle_price_confidence
MarginfiAccount
- account_flags - added
ACCOUNT_FROZENoption (1 << 6)
Notes on Drift Rewards
Drift rewards paid in the same token (e.g. USDS rewards for the USDS Market) are automatically credited to depositors at the program level, no special claim instruction is required. Drift rewards paid in a different token (E.g. JTO incentives for the SOL Market), as well as special rewards which Drift itself might "admin deposit" directly to accounts as part of various campaigns, are sent to the administrator's fee wallet, and will be distributed to users like other incentives (typically via weekly airdrop). We will announce how FUEL incentives will be handled at a later date.
Consolidates
Audits
TBD
Release Times
Staging - TBD
Mainnet - TBD (ETA ~ January 23)
mrgn-0.1.6a-hotfix
- Restores support for jup and Titan swaps during receivership liquidation.
For full patches notes, see mrgn-0.1.6-rc3
mrgn - 0.1.6-rc3
Summary
Implementation of a seven-point curve structure that enables deeper control of interest rates at various utilization levels. Deprecates the simple three-point plateau rate/max rate model. The new curve approach allows the admin to set up to 5 points (plus the points at util = 0 and util = 100). Each point corresponding to a utilization and base interest rate. Points must be in ascending order (util increasing, rates increasing or equal to previous). To determine what the rate is at a given utilization, we linearly interpolate between the nearest two points.
Adds a fixed-price oracle type. Banks using this type have a declared price that can be read at bank.config.fixed_price. They use no external oracle, the price is completely set by the group administrator and never goes stale. This is useful for e.g. stablecoins, assets that are worthless and/or being sunset, or assets that are extremely stable in price for some other reason.
Risk management gets a major upgrade: banks that are defunct and being sunset can now be deleveraged and unwound. Deleverage is essentially a liquidation of a healthy account, but for no profit in dollar terms. We expect that banks at risk of deleveraging will get a LOT of warning (looking at you, UXD). The operation is admin-only.
Bank Metadata: an on-chain account where you can read the plain-English token name and description of a corresponding bank.
Big readme rewrites! More guides!
Bug Fixes
- Kamino refresh instructions are now allowed before
start_liquidationin receivership liquidations.
New Accounts
- BankMetadata - 1:1 with Banks, contains the utf-8 encoded token name and a brief description. No more running to solscan to figure out what token a bank is using! A pda with one non-static seed: the bank.
New/Changed Fields
- Banks now have:
zero_util_rate- The base rate at utilization = 0. A %, as u32, out of 1000%, e.g. 100% = 0.1 * u32::MAXhundred_util_rate- The base rate at full utilization (100%). A %, as u32, out of 1000%, e.g. 100% = 0.1 * u32::MAXpoints- The base rate at various points between 0 and 100% utilization, exclusive. Exactly five points large. Unused points have util = 0. Util is a %, as u32, out of 100%, e.g. 50% = .5 * u32::MAX. Rate is a %, as u32, out of 1000%, e.g. 100% = 0.1 * u32::MAX.curve_type- For all newly created banks, INTEREST_CURVE_SEVEN_POINT (1). For all banks created prior to this update, INTEREST_CURVE_LEGACY (0). After migration is completed, all banks will have INTEREST_CURVE_SEVEN_POINT.OracleSetuphas a new enum value: Fixedbank.config.fixed_price: A WrappedI80F48, storing the declared price for Fixed banks, does nothing for banks for other OracleSetups. Note: a bank can swap from Fixed to another OracleSetup type. If it does so, this field might be populated with a junk value.
- Groups now have:
deleverage_withdraw_window_cache- Limits how much the risk_admin can deleverage in a day, in the even the admin is compromisedrisk_admin- can perform bankruptcies and deleveragesmetadata_admin- can update bank metadata
Breaking Changes (admin instructions)
- All config instructions affecting interest (add_pool, add_pool_with_seed, configure_bank, configure_bank_interest_only) now take fundamentally different arguments.
Breaking Changes (Everyone)
- All instructions that require risk checks (borrow, liquidate, withdraw, etc) must now accommodate fixed-price banks. For these banks, pass just the bank in remaining_accounts, no oracle is required. See
load_observation_account_metasfor a Rust example. For Typescript, assuming you have a list of banks and loaded bank accounts:
for (let i = 0; i < bankAccs.length; i++) {
const setup = bankAccs[i].account.config.oracleSetup;
const keys = bankAccs[i].account.config.oracleKeys;
if ("fixed" in setup) {
remainingAccounts.push([banks[i]]);
} else if ("stakedWithPythPush" in setup) {
remainingAccounts.push([banks[i], keys[0], keys[1], keys[2]]);
} else if ("kaminoPythPush" in setup) {
remainingAccounts.push([banks[i], keys[0], keys[1]]);
} else if ("kaminoSwitchboardPull" in setup) {
remainingAccounts.push([banks[i], keys[0], keys[1]]);
} else {
remainingAccounts.push([banks[i], keys[0]]);
}
}
Breaking Changes (Rust integrators only)
- in the
withdrawandkamino_withdrawinstructions,groupis now mutable
Breaking Changes (Liquidators)
- The classic liquidate instruction has two new arguments, now requiring the caller to declare the length of the liquidator's and liquidatee's remaining accounts slice. In normal usage, this simply looks like:
await liquidateIx(liquidator.mrgnProgram, {
//.... base accounts
remaining: [
assetOracle,
liabOracle,
...liquidatorAccounts,
...liquidateeAccounts,
],
amount: amt,
liquidateeAccounts: liquidateeAccounts.length,
liquidatorAccounts: liquidatorAccounts.length,
})
- If any asset or liability is fixed, note that you do not have to pass that oracle (see fixed oracle tests in m01/m02 for examples), e.g.:
await liquidateIx(liquidator.mrgnProgram, {
//.... base accounts
remaining: [
// no asset oracle if fixed
// no liab oracle if fixed
// liquidator/ee accounts also respect the fixed-oracle rules above.
...liquidatorAccounts,
...liquidateeAccounts,
],
amount: amt,
liquidateeAccounts: liquidateeAccounts.length,
liquidatorAccounts: liquidatorAccounts.length,
})
New/Removed instructions
- migrate_curve (permissionless) - convert a bank from the legacy curve setup to the new seven-point approach. Does not affect bank operations in any way, the bank is immediately able to function as normal.
- set_fixed_oracle_price (admin only) - sets a price for the bank, like a permanent oracle.
- start/end_deleverage (risk admin only) - a permissioned liquidation: used to unwind banks that are being sunset. Functions almost identically to receivership liquidation, except that it earns no profit and can be used even on healthy accounts.
- init_bank_metadata (permissionless) - pay the rent for a bank's metadata
- write_bank_metadata (metadata admin only) - write token name/description to a bank's metadata
- clone_emode (group admin or emode admin) - copy one bank's emode settings to another
- purge_delev_balance (risk admin only) - when a bank has been fully deleveraged, and is completely out of tokens to withdraw, closes a balance without repaying it
- configure_withdrawal_limit (admin only) - configures the amount that can be deleveraged in a given day
- admin_super_withdraw (removed) - arena has been sunset, and this is no longer needed.
- sort_balances (removed) - all accounts are now sorted, at all times, and this is no longer needed.
Additional Notes on Fixed Oracle Banks
- The oracle_keys[0] slot of Fixed oracle banks is always pubkey default. Other oracle_keys[] fields might still be populated, e.g. the lst mint and sol pool for staked banks, or the reserve for the Kamino banks, this is to simplify switching these banks back into a normal oracle operational mode if needed.
- Staked collateral banks can't take a fixed price. Kamino banks CAN (and so can future integrator banks).
Additional Notes on new Curves
- add_bank_permissionless, and add_pool (kamino) now create different placeholders (using the new curve system). Staked and Kamino banks created prior to this update should still be migrated so they don't die when "accruing interest" (even though it doesn't do anything for them, since they never earn interest).
- Banks on the legacy approach will continue to function as normal before/after migration. The legacy approach will cease to function in 1.7.
Samples
See the referenced functions for more details on how to convert to/from a float to a u32 representation or to a 5-length points slice.
Sample points creation (Rust):
points: make_points(&vec![RatePoint::new(
p100_to_u32(I80F48!(0.9)),
p1000_to_u32(I80F48!(1)),
)]),
Sample points creation (TS):
points: makeRatePoints([0.5], [0.6])
Audit Notes
- See attached audit from Sec3
Consolidates:
Changes since RC1
- CU usage optimizations
- Minor audit fixes
- Added clone_emode ix
Deploy Information
Hash - 65e54c
Staging - mid-November
Mainnet - 11am ET, Thursday, December 18, 2025
mrgn-0.1.6-rc2
Summary
Implementation of a seven-point curve structure that enables deeper control of interest rates at various utilization levels. Deprecates the simple three-point plateau rate/max rate model. The new curve approach allows the admin to set up to 5 points (plus the points at util = 0 and util = 100). Each point corresponding to a utilization and base interest rate. Points must be in ascending order (util increasing, rates increasing or equal to previous). To determine what the rate is at a given utilization, we linearly interpolate between the nearest two points.
Adds a fixed-price oracle type. Banks using this type have a declared price that can be read at bank.config.fixed_price. They use no external oracle, the price is completely set by the group administrator and never goes stale. This is useful for e.g. stablecoins, assets that are worthless and/or being sunset, or assets that are extremely stable in price for some other reason.
Risk management gets a major upgrade: banks that are defunct and being sunset can now be deleveraged and unwound. Deleverage is essentially a liquidation of a healthy account, but for no profit in dollar terms. We expect that banks at risk of deleveraging will get a LOT of warning (looking at you, UXD). The operation is admin-only.
Bank Metadata: an on-chain account where you can read the plain-English token name and description of a corresponding bank.
Big readme rewrites! More guides!
Bug Fixes
- Kamino refresh instructions are now allowed before
start_liquidationin receivership liquidations.
New Accounts
- BankMetadata - 1:1 with Banks, contains the utf-8 encoded token name and a brief description. No more running to solscan to figure out what token a bank is using! A pda with one non-static seed: the bank.
New/Changed Fields
- Banks now have:
zero_util_rate- The base rate at utilization = 0. A %, as u32, out of 1000%, e.g. 100% = 0.1 * u32::MAXhundred_util_rate- The base rate at full utilization (100%). A %, as u32, out of 1000%, e.g. 100% = 0.1 * u32::MAXpoints- The base rate at various points between 0 and 100% utilization, exclusive. Exactly five points large. Unused points have util = 0. Util is a %, as u32, out of 100%, e.g. 50% = .5 * u32::MAX. Rate is a %, as u32, out of 1000%, e.g. 100% = 0.1 * u32::MAX.curve_type- For all newly created banks, INTEREST_CURVE_SEVEN_POINT (1). For all banks created prior to this update, INTEREST_CURVE_LEGACY (0). After migration is completed, all banks will have INTEREST_CURVE_SEVEN_POINT.OracleSetuphas a new enum value: Fixedbank.config.fixed_price: A WrappedI80F48, storing the declared price for Fixed banks, does nothing for banks for other OracleSetups. Note: a bank can swap from Fixed to another OracleSetup type. If it does so, this field might be populated with a junk value.
- Groups now have:
deleverage_withdraw_window_cache- Limits how much the risk_admin can deleverage in a day, in the even the admin is compromisedrisk_admin- can perform bankruptcies and deleveragesmetadata_admin- can update bank metadata
Breaking Changes (admin instructions)
- All config instructions affecting interest (add_pool, add_pool_with_seed, configure_bank, configure_bank_interest_only) now take fundamentally different arguments.
Breaking Changes (Everyone)
- All instructions that require risk checks (borrow, liquidate, withdraw, etc) must now accommodate fixed-price banks. For these banks, pass just the bank in remaining_accounts, no oracle is required. See
load_observation_account_metasfor a Rust example. For Typescript, assuming you have a list of banks and loaded bank accounts:
for (let i = 0; i < bankAccs.length; i++) {
const setup = bankAccs[i].account.config.oracleSetup;
const keys = bankAccs[i].account.config.oracleKeys;
if ("fixed" in setup) {
remainingAccounts.push([banks[i]]);
} else if ("stakedWithPythPush" in setup) {
remainingAccounts.push([banks[i], keys[0], keys[1], keys[2]]);
} else if ("kaminoPythPush" in setup) {
remainingAccounts.push([banks[i], keys[0], keys[1]]);
} else if ("kaminoSwitchboardPull" in setup) {
remainingAccounts.push([banks[i], keys[0], keys[1]]);
} else {
remainingAccounts.push([banks[i], keys[0]]);
}
}
Breaking Changes (Liquidators)
- The classic liquidate instruction has two new arguments, now requiring the caller to declare the length of the liquidator's and liquidatee's remaining accounts slice. In normal usage, this simply looks like:
await liquidateIx(liquidator.mrgnProgram, {
//.... base accounts
remaining: [
assetOracle,
liabOracle,
...liquidatorAccounts,
...liquidateeAccounts,
],
amount: amt,
liquidateeAccounts: liquidateeAccounts.length,
liquidatorAccounts: liquidatorAccounts.length,
})
- If any asset or liability is fixed, note that you do not have to pass that oracle (see fixed oracle tests in m01/m02 for examples), e.g.:
await liquidateIx(liquidator.mrgnProgram, {
//.... base accounts
remaining: [
// no asset oracle if fixed
// no liab oracle if fixed
// liquidator/ee accounts also respect the fixed-oracle rules above.
...liquidatorAccounts,
...liquidateeAccounts,
],
amount: amt,
liquidateeAccounts: liquidateeAccounts.length,
liquidatorAccounts: liquidatorAccounts.length,
})
New/Removed instructions
- migrate_curve (permissionless) - convert a bank from the legacy curve setup to the new seven-point approach. Does not affect bank operations in any way, the bank is immediately able to function as normal.
- set_fixed_oracle_price (admin only) - sets a price for the bank, like a permanent oracle.
- start/end_deleverage (risk admin only) - a permissioned liquidation: used to unwind banks that are being sunset. Functions almost identically to receivership liquidation, except that it earns no profit and can be used even on healthy accounts.
- init_bank_metadata (permissionless) - pay the rent for a bank's metadata
- write_bank_metadata (metadata admin only) - write token name/description to a bank's metadata
- admin_super_withdraw (removed) - arena has been sunset, and this is no longer needed.
Additional Notes on Fixed Oracle Banks
- The oracle_keys[0] slot of Fixed oracle banks is always pubkey default. Other oracle_keys[] fields might still be populated, e.g. the lst mint and sol pool for staked banks, or the reserve for the Kamino banks, this is to simplify switching these banks back into a normal oracle operational mode if needed.
- Staked collateral banks can't take a fixed price. Kamino banks CAN (and so can future integrator banks).
Additional Notes on new Curves
- add_bank_permissionless, and add_pool (kamino) now create different placeholders (using the new curve system). Staked and Kamino banks created prior to this update should still be migrated so they don't die when "accruing interest" (even though it doesn't do anything for them, since they never earn interest).
- Banks on the legacy approach will continue to function as normal before/after migration. The legacy approach will cease to function in 1.7.
Samples
See the referenced functions for more details on how to convert to/from a float to a u32 representation or to a 5-length points slice.
Sample points creation (Rust):
points: make_points(&vec![RatePoint::new(
p100_to_u32(I80F48!(0.9)),
p1000_to_u32(I80F48!(1)),
)]),
Sample points creation (TS):
points: makeRatePoints([0.5], [0.6])
Audit Notes
TBD
Consolidates:
Changes since RC1
CU usage optimizations
Deploy Information
Hash - TBD
Staging - TBD
Mainnet -TBD
mrgn - 0.1.6-rc1
Summary
Implementation of a seven-point curve structure that enables deeper control of interest rates at various utilization levels. Deprecates the simple three-point plateau rate/max rate model. The new curve approach allows the admin to set up to 5 points (plus the points at util = 0 and util = 100). Each point corresponding to a utilization and base interest rate. Points must be in ascending order (util increasing, rates increasing or equal to previous). To determine what the rate is at a given utilization, we linearly interpolate between the nearest two points.
Adds a fixed-price oracle type. Banks using this type have a declared price that can be read at bank.config.fixed_price. They use no external oracle, the price is completely set by the group administrator and never goes stale. This is useful for e.g. stablecoins, assets that are worthless and/or being sunset, or assets that are extremely stable in price for some other reason.
Risk management gets a major upgrade: banks that are defunct and being sunset can now be deleveraged and unwound. Deleverage is essentially a liquidation of a healthy account, but for no profit in dollar terms. We expect that banks at risk of deleveraging will get a LOT of warning (looking at you, UXD). The operation is admin-only.
Bank Metadata: an on-chain account where you can read the plain-English token name and description of a corresponding bank.
Big readme rewrites! More guides!
Bug Fixes
- Kamino refresh instructions are now allowed before
start_liquidationin receivership liquidations.
New Accounts
- BankMetadata - 1:1 with Banks, contains the utf-8 encoded token name and a brief description. No more running to solscan to figure out what token a bank is using! A pda with one non-static seed: the bank.
New/Changed Fields
- Banks now have:
zero_util_rate- The base rate at utilization = 0. A %, as u32, out of 1000%, e.g. 100% = 0.1 * u32::MAXhundred_util_rate- The base rate at full utilization (100%). A %, as u32, out of 1000%, e.g. 100% = 0.1 * u32::MAXpoints- The base rate at various points between 0 and 100% utilization, exclusive. Exactly five points large. Unused points have util = 0. Util is a %, as u32, out of 100%, e.g. 50% = .5 * u32::MAX. Rate is a %, as u32, out of 1000%, e.g. 100% = 0.1 * u32::MAX.curve_type- For all newly created banks, INTEREST_CURVE_SEVEN_POINT (1). For all banks created prior to this update, INTEREST_CURVE_LEGACY (0). After migration is completed, all banks will have INTEREST_CURVE_SEVEN_POINT.OracleSetuphas a new enum value: Fixedbank.config.fixed_price: A WrappedI80F48, storing the declared price for Fixed banks, does nothing for banks for other OracleSetups. Note: a bank can swap from Fixed to another OracleSetup type. If it does so, this field might be populated with a junk value.
- Groups now have:
deleverage_withdraw_window_cache- Limits how much the risk_admin can deleverage in a day, in the even the admin is compromisedrisk_admin- can perform bankruptcies and deleveragesmetadata_admin- can update bank metadata
Breaking Changes (admin instructions)
- All config instructions affecting interest (add_pool, add_pool_with_seed, configure_bank, configure_bank_interest_only) now take fundamentally different arguments.
Breaking Changes (Everyone)
- All instructions that require risk checks (borrow, liquidate, withdraw, etc) must now accommodate fixed-price banks. For these banks, pass just the bank in remaining_accounts, no oracle is required. See
load_observation_account_metasfor a Rust example. For Typescript, assuming you have a list of banks and loaded bank accounts:
for (let i = 0; i < bankAccs.length; i++) {
const setup = bankAccs[i].account.config.oracleSetup;
const keys = bankAccs[i].account.config.oracleKeys;
if ("fixed" in setup) {
remainingAccounts.push([banks[i]]);
} else if ("stakedWithPythPush" in setup) {
remainingAccounts.push([banks[i], keys[0], keys[1], keys[2]]);
} else if ("kaminoPythPush" in setup) {
remainingAccounts.push([banks[i], keys[0], keys[1]]);
} else if ("kaminoSwitchboardPull" in setup) {
remainingAccounts.push([banks[i], keys[0], keys[1]]);
} else {
remainingAccounts.push([banks[i], keys[0]]);
}
}
Breaking Changes (Liquidators)
- The classic liquidate instruction has two new arguments, now requiring the caller to declare the length of the liquidator's and liquidatee's remaining accounts slice. In normal usage, this simply looks like:
await liquidateIx(liquidator.mrgnProgram, {
//.... base accounts
remaining: [
assetOracle,
liabOracle,
...liquidatorAccounts,
...liquidateeAccounts,
],
amount: amt,
liquidateeAccounts: liquidateeAccounts.length,
liquidatorAccounts: liquidatorAccounts.length,
})
- If any asset or liability is fixed, note that you do not have to pass that oracle (see fixed oracle tests in m01/m02 for examples), e.g.:
await liquidateIx(liquidator.mrgnProgram, {
//.... base accounts
remaining: [
// no asset oracle if fixed
// no liab oracle if fixed
// liquidator/ee accounts also respect the fixed-oracle rules above.
...liquidatorAccounts,
...liquidateeAccounts,
],
amount: amt,
liquidateeAccounts: liquidateeAccounts.length,
liquidatorAccounts: liquidatorAccounts.length,
})
New/Removed instructions
- migrate_curve (permissionless) - convert a bank from the legacy curve setup to the new seven-point approach. Does not affect bank operations in any way, the bank is immediately able to function as normal.
- set_fixed_oracle_price (admin only) - sets a price for the bank, like a permanent oracle.
- start/end_deleverage (risk admin only) - a permissioned liquidation: used to unwind banks that are being sunset. Functions almost identically to receivership liquidation, except that it earns no profit and can be used even on healthy accounts.
- init_bank_metadata (permissionless) - pay the rent for a bank's metadata
- write_bank_metadata (metadata admin only) - write token name/description to a bank's metadata
- admin_super_withdraw (removed) - arena has been sunset, and this is no longer needed.
Additional Notes on Fixed Oracle Banks
- The oracle_keys[0] slot of Fixed oracle banks is always pubkey default. Other oracle_keys[] fields might still be populated, e.g. the lst mint and sol pool for staked banks, or the reserve for the Kamino banks, this is to simplify switching these banks back into a normal oracle operational mode if needed.
- Staked collateral banks can't take a fixed price. Kamino banks CAN (and so can future integrator banks).
Additional Notes on new Curves
- add_bank_permissionless, and add_pool (kamino) now create different placeholders (using the new curve system). Staked and Kamino banks created prior to this update should still be migrated so they don't die when "accruing interest" (even though it doesn't do anything for them, since they never earn interest).
- Banks on the legacy approach will continue to function as normal before/after migration. The legacy approach will cease to function in 1.7.
Samples
See the referenced functions for more details on how to convert to/from a float to a u32 representation or to a 5-length points slice.
Sample points creation (Rust):
points: make_points(&vec![RatePoint::new(
p100_to_u32(I80F48!(0.9)),
p1000_to_u32(I80F48!(1)),
)]),
Sample points creation (TS):
points: makeRatePoints([0.5], [0.6])
Audit Notes
TBD
Consolidates:
Deploy Information
Hash - TBD
Staging - TBD
Mainnet -TBD
mrgn - 0.1.5-rc2
Consolidates
| PR | Description |
|---|---|
| #357 | remove rent from various ixes |
| #362 | Bankruptcy handling improvements for super-bankrupt banks |
| #364 | Broad refactor |
| #370 | Remove Pyth migration functions |
| #371 | Remove type layout |
| #384 | Panic button to pause protocol |
| #373 | Last update time for user accounts |
| #382 | PDA-based mrgn accounts |
| #372 | New Liquidation approach "Receivership" |
| #386 | Emode no brakes |
| #391 | Arena sunset ix |
| #401 | Various minor fixes |
| #394 | Kamino Lending integration |
Summary
- Kamino integration is now live! Allows users to deposit into Kamino Reserves through this program, using their positions as collateral to borrow while continuing to earn any yields or rewards they would normally earn on Kamino! See #394 for more details.
- New liquidation approach: execute liquidation without a mrgn account, simply by withdrawing and repaying as if you are the user! This novel approach also has a slightly higher premium to attract new developers to move over to it! We will support the old approach for the foreseeable future as well. See #372 for more details.
- All on-chain structs and many on-chain utility functions are now represented in the type-crate, which can be built without any dependencies. Rust consumers no longer to need to depend on our entire program with all of its cruft and layers of dependencies!
- Something you wanted missing from type-crate? Contact us or open an issue!
- Fixes to loss socialization and liquidation of heavily bankrupted banks. Certain bankrupted arena banks that were formerly frozen are now eligible to be liquidated. In the future, we expect banks will not be able to enter the super-bankrupt state currently affecting arena unless a price rapidly collapses or liquidators fail for an extended time.
- The global fee admin is now able to suspend all financial transactions in all groups in the entire protocol for a few minutes. This power has a limited number of uses per day (currently 2) and a limited time (currently 30 minutes). The purpose of this power is to respond quickly in event of a suspected hack/exploit or to give groups a brief window to conduct complex risk re-configurations. Once expired, the pause lifts permissionlessly.
- User accounts now have a
last_updatetimestamp that can be used to see when they were last mutated in a meaningful way, for example when they last borrowed, deposited, withdrew, etc, but not when they did a no-op task like health pulse. Backend consumers can now use this timestamp as a "dirty flag" to know when they must update a database entry. - User accounts can now be created as a PDA. Legacy user accounts created with a keypair will also be supported indefinitely.
- Removes the 100% initial asset weight limit from emode, now enabling weights up to 200%. LTVs to the moon!
- Arena sunsetting: an arena-only instruction will withdraw all funds from the remaining Arena banks, to be returned to their owners OTC. Non-arena banks, e.g. those on the main mrgn or p0 app, are unaffected.
Important for Integrators
- Mrgn accounts can now be created with a PDA (see marginfi_account_initialize_pda). If you would like a
third_party_idassigned to just your program, so you can easily fetch all accounts your program has created by CPI, contact us or open an issue in this repo. Seeds are shall-issue, and will be included in the next update, you don't need any special relationship with mrgn to request a seed.
Breaking Changes (Everyone)
- Many instructions require an idl update. Upgrade your IDL to the one attached to this release. We removed mut from various accounts that didn't need it. The only user facing instructions are: LendingAccountBorrow/LendingAccountLiquidate -> removed mut from liquidity vault authority
- Banks that did not yet migrate to the new Pyth oracle model are no longer supported, all functions associated with permissionless migration have been removed. Pyth banks configured in 1.3 and earlier that have not migrated will no longer be able to transact until the admin configures a new oracle. This does not affect any banks in production.
- Any instruction involving a risk check (borrow, withdraw, liquidate, etc) must now also support Kamino banks. Unlike regular banks, these have two oracle accounts: (1) the oracle, and (2) the Kamino reserve. You can still extract these from
oracle_keys.
Breaking Changes (Rust consumers)
- The "Rent" sysvar has not been needed in a long time and has been removed from various ixes
New instructions
- (global fee admin only)
panic_pause- suspend all financial interactions (borrow, withdraw, repay, etc) for a short preset time. Can only be called twice per day and twice consecutively. - (global fee admin only)
panic_unpause- resume all financial interactions - (permissionless)
panic_unpause_permissionless- reset the global pause state after a pause expires (does not need to be called for ixes to resume) - (group admin only)
lending_pool_add_bank_kamino- Adds a new Kamino bank - (permissionless)
kamino_init_obligation- Sets up the obligation for a new Kamino bank, which must occur before it can get deposits. Typically, the admin will do this, but anyone can pay the rent if they're feeling generous. - (permissionless)
kamino_harvest_reward- Collect "farm rewards" (aka token emissions) from a Kamino lending bank. We currently collect these funds to an account under our control, then airdrop them to users at regular intervals. More details to follow. - (user)
marginfi_account_initialize_pda- create a mrgn account with a PDA instead of a keypair - (user)
transfer_to_new_account_pda- transfer an existing mrgn account to a new one that is PDA-based. - (user)
liquidate_startandliquidate_end- the novel liquidation approach no longer requires a mfi account. Calling start enables a liquidator to act as if they are the mfi user, but ONLY to withdraw or repay until the end of the tx. The user's health must improve at the end of the tx. For example, a liquidator might do [start, withdraw A, swap A->B on jup, repay B, end]. Typically the value of is A is slightly greater than B, allowing the liquidator to turn a profit. - (user)
kamino_deposit- deposit funds to a Kamino bank - (user)
kamino_withdraw- withdraw funds from a Kamino bank
New fields
- user accounts now have
last_update, tracking the timestamp when they were last mutated in a meaningful way. - user accounts generated with the new PDA approach have the following fields. user accounts generated with the legacy keypair approach use all-zeros for these fields:
- account_index - a seed chosen arbitrarily
- third_party_index - if < 10,000, a seed chosen arbitrarily. third parties can reserve seeds above 10,000 by contacting us.
- bump - the bump used to derive the PDA
- user accounts now have
liquidation_record, which points to the liquidation record if they have one, or pubkey default if they've never had a receivership liquidation. - the global FeeState now has
panic_state, which tracks if the protocol is paused and when it can unpause. - groups have
panic_state_cache, which tracks the global fee state'spanic_statewhen propagated (see notes below) - Banks now have
kamino_reserve/kamino_obligation- tracks the Kamino position for Kamino banks, Pubkey Default for all other banks. Note thatkamino_reserveis the second account that needs to be passed for any risk checks related to Kamino banks. - Banks and user balances have a new possible Asset Tag (3 - Kamino)
New accounts
- liquidation records - 1:1 relationship with accounts. the first time any user is liquidated using the Receivership approach, the liquidator must pay to create a liquidation record. This account stores intermediate information during liquidation events and also has a record of the last few successful receivership liquidations events on the associated account
Notes on Pause
- The pause state propagates to groups via propagate_fee_state, which is permissionless. Until propagated, the group is not participating in the pause, and can function normally. Typically, the global fee admin will queue up a pause and propagation to all major groups at the same time. Note that mrgn currently only maintains one group for the main pool you see on the app front page, but this may not always be the case, and anyone can open their own group as well. Message the global fee admin to make sure your group also receives the propagation instruction immediately after any pause.
Notes on Receivership Liquidation
- Like our old approach, this new approach is also permissionless, we encourage third-parties to build liquidators that utilize it.
- The classic liquidation approach will be supported indefinitely, but may be cumbersome to use with future integrations e.g. Kamino positions.
Audit Notes
Kamino-related commit hash and pr notes relate to #394, the original audit report was completed based on our internal private mirror of the public repo.
Hash: 4e7867