Releases: mrgnlabs/marginfi-v2
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_update
timestamp 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_id
assigned 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_start
andliquidate_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_state
when 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_reserve
is 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
mrgn-0.1.4-rc3.2
Changes since rc3.1
Account transfers can now specify a separate fee payer.
Deployments
Mainnet - Oct 2, 2025 at ~4:30PM ET, hash: 866e5ae9e65c34d8e42b0ede0f20241f7ce3c0f270a2f78fb9142918b023fc62
mrgn - 0.1.5-rc1
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 |
Summary
- 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_update
timestamp 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_id
assigned 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)
- 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.
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)
- (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.
- liquidate_start and liquidate_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.
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_state
when propagated (see notes below)
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.
mrgn-0.1.4-rc3.1
Changes since rc3
- Added a condition that checks an accounts status before allow them to participate in a flashloan.
Deployments
Mainnet - Aug 14, 2025 at ~7PM ET, hash: 566fe2
mrgn - 0.1.4-rc3
Changes since rc2
- Type crate now matches the release data (marginfi_account did not pick up the changes in rc2). No change to program, no update to staging program.
Changes since rc1
- Fix account transfer logic to prevent the same account from being migrated to a new account twice.
- add migrated_to field to accounts to indicate where they have been moved
- 0.1.3 health caches are now still valid in 0.1.4 (previously were corrupted due to adding the migrated_from field prior to those accounts)
SUMMARY
- Adds a new way to transfer your account:
transfer_to_new_account
transfers all of your positions to a new account, with an authority of your choosing. This allows you to give your positions to others or move them between your own wallets. The process incurs a nominal fee in SOL (~$1 today) to avoid spam.- We expect that points earned by the source of the transfer will go to the destination account. For example, if account A migrates to B, then B migrates to C, then C will earn all of the points combined for A and B. Currently, points will continue to display on A and B separately, we will figure out how to combine them at a later date.
- Adds a bank cache, where consumers can view recent information about a bank's interest rates (APR), and interest recently earned.
- Removes Pyth legacy (aka v1, pythnet, or "push") oracle support from the program.
- Fixes a bug with the switchboard oracles where confidence was incorrectly either 0 or clamped at 5%. All users participating in swb banks should see a tiny improvement to their account health and corresponding increase in borrowing power
- Oracle pricing is now totally suspended during periods of poor price confidence, where the allowed confidence is now configurable per bank. We expect this will reduce unfair liquidations during periods of extreme price volatility, but should not affect normal operation in the vast majority of cases.
- Banks created after the release of 0.1.4 can now be closed by the group admin to recover rent, but only if they have no open positions, no emissions, and no assets. Banks created prior to 0.1.4 can never be closed.
- Banks now track the total number of open positions, subsequent to the release of 0.1.4 (Note: for new banks, this will always be 0 or greater, for banks created prior to 0.1.4, this may be negative as closed positions reduce the count).
- Adds delegate administrators for emissions, curve parameters, and deposit/borrow caps. These admins can modify only a small subset of settings, which makes them safe(r) to grant to a hot wallet or MS with limited signature threshold. The group admin is still free to modify most bank parameters.
Consolidates:
- #349 (adds bank cache to record spot interest rates, etc)
- #343 (removes Pyth legacy support from the program and test suite)
- #344 (Restores Rust CLI functionality which was broken in 0.1.3)
- #350 (Tests usage of multiple staked collateral banks at once)
- #351 (minor TS error handling update)
- #353 (remove pyth legacy from test suite)
- #356 (fix swb std dev issue)
- #354 (new account migration instruction)
- #355 (minor fixes following second emode audit suggestion)
- #356 (Fix usage of std dev aka confidence in swb oracles)
- #358 (Pyth accounts store the feed directly instead of feed id)
- #359 (Oracles fail when a confidence threshold is exceeded)
- #360 (Banks track open positions and can be closed)
- #361 (Delegate admins for setting various bank params)
- #369 (minor fix to account transfer logic)
BREAKING CHANGES
- Always remember to update your TS package to the latest version.
- Removes the old account migration instruction, which required the group admin (the multisig) to sign. Users can now migrate their balances to a new account at any time without admin approval using the new
transfer_to_new_account
ix - If you were deriving the Pyth oracle using oracles[0] (formerly the feed id) and a shard id, this is no longer possible. Banks that have migrated (e.g. where
bank.config.config_flags
& 1 != 0`) now store the feed directly on oracles[0], use that key directly as the oracle instead. - If you were using your own feed (e.g. neither Pyth nor Mrgn sponsored), you may no longer do so.
- Remember to update your Rust type-crate or program dependency.
BREAKING (ADMIN ONLY)
- set/unset user flags ixes removed (all user flags are now deprecated)
- When configuring banks with pyth oracles, pass the oracle directly instead of the feed id. You no longer ever need to worry about the feed id.
- When configuring banks, an additional argument is passed (
oracle_max_confidence
). Oracle checks fail if this is exceeded. Pass 0 to use the default (10%). - changing emissions now requires
delegate_emissions_admin
instead of regularadmin
.
NEW FIELDS AND OTHER NOTES
- Account authority is now immutable
- Frozen fields still can't update even with a delegated admin right, e.g. the delegate curve admin cannot do anything if a bank is frozen.
- Account gains
migrated_to
andmigrated_from
fields that indicate ithe key of the new/previous mrgnfi account when an account is migrated to a new authority. Accounts migrated like this form essentially a doubly linked list of accounts, so you can always follow these references to trace back to the "root" account or to the "current" one. - bank.config and the config input types added field
oracle_max_confidence
- bank added field bank.cache
- bank added field
lending_position_count
andborrowing_position_count
- Group added fields
delegate_curve_admin
,delegate_limit_admin
, anddelegate_emissions_admin
PYTH MIGRATION INSTRUCTIONS AND NOTES
- Banks that have not migrated will continue to function as normal until they migrate.
- Pyth banks that migrate will no longer store the feed id on oracles[0], instead they will store the key of the feed directly, just like switchboard oracles already do. After the ix completes, these banks will now accept that oracle and no other feeds.
- Simply run
migrate_pyth_push_oracle
for all banks that existed prior to 0.1.4 going live. Non-Pyth banks will set the migration flag and do nothing. Pyth banks (excluding staked collateral) will accept either the Pyth or Mrgn sponsored oracle feed. The feed must exist (e.g. not be a blank account). - Staked collateral banks must use
propagate_staked_settings
instead. These will always use the Pyth sponsored oracle. - Next time
edit_staked_settings
runs, remember to also update the oracle to use the SOL feed. This can happen any time in the future, it does not have to happen to complete migration, but propagation of future settings will fail until it's done. - New banks will now take the feed instead of the feed id when being created.
- Migration functionality will be removed in 0.1.5
Deployments
Staging - July 25, 2025 at ~7:15 ET
Mainnet - July 39, 2025 at ~11am ET, hash: 1229b8
mrgn - 0.1.4-rc2
Changes since rc1
- Fix account transfer logic to prevent the same account from being migrated to a new account twice.
- add migrated_to field to accounts to indicate where they have been moved
- 0.1.3 health caches are now still valid in 0.1.4 (previously were corrupted due to adding the migrated_from field prior to those accounts)
SUMMARY
- Adds a new way to transfer your account:
transfer_to_new_account
transfers all of your positions to a new account, with an authority of your choosing. This allows you to give your positions to others or move them between your own wallets. The process incurs a nominal fee in SOL (~$1 today) to avoid spam.- We expect that points earned by the source of the transfer will go to the destination account. For example, if account A migrates to B, then B migrates to C, then C will earn all of the points combined for A and B. Currently, points will continue to display on A and B separately, we will figure out how to combine them at a later date.
- Adds a bank cache, where consumers can view recent information about a bank's interest rates (APR), and interest recently earned.
- Removes Pyth legacy (aka v1, pythnet, or "push") oracle support from the program.
- Fixes a bug with the switchboard oracles where confidence was incorrectly either 0 or clamped at 5%. All users participating in swb banks should see a tiny improvement to their account health and corresponding increase in borrowing power
- Oracle pricing is now totally suspended during periods of poor price confidence, where the allowed confidence is now configurable per bank. We expect this will reduce unfair liquidations during periods of extreme price volatility, but should not affect normal operation in the vast majority of cases.
- Banks created after the release of 0.1.4 can now be closed by the group admin to recover rent, but only if they have no open positions, no emissions, and no assets. Banks created prior to 0.1.4 can never be closed.
- Banks now track the total number of open positions, subsequent to the release of 0.1.4 (Note: for new banks, this will always be 0 or greater, for banks created prior to 0.1.4, this may be negative as closed positions reduce the count).
- Adds delegate administrators for emissions, curve parameters, and deposit/borrow caps. These admins can modify only a small subset of settings, which makes them safe(r) to grant to a hot wallet or MS with limited signature threshold. The group admin is still free to modify most bank parameters.
Consolidates:
- #349 (adds bank cache to record spot interest rates, etc)
- #343 (removes Pyth legacy support from the program and test suite)
- #344 (Restores Rust CLI functionality which was broken in 0.1.3)
- #350 (Tests usage of multiple staked collateral banks at once)
- #351 (minor TS error handling update)
- #353 (remove pyth legacy from test suite)
- #356 (fix swb std dev issue)
- #354 (new account migration instruction)
- #355 (minor fixes following second emode audit suggestion)
- #356 (Fix usage of std dev aka confidence in swb oracles)
- #358 (Pyth accounts store the feed directly instead of feed id)
- #359 (Oracles fail when a confidence threshold is exceeded)
- #360 (Banks track open positions and can be closed)
- #361 (Delegate admins for setting various bank params)
- #369 (minor fix to account transfer logic)
BREAKING CHANGES
- Always remember to update your TS package to the latest version.
- Removes the old account migration instruction, which required the group admin (the multisig) to sign. Users can now migrate their balances to a new account at any time without admin approval using the new
transfer_to_new_account
ix - If you were deriving the Pyth oracle using oracles[0] (formerly the feed id) and a shard id, this is no longer possible. Banks that have migrated (e.g. where
bank.config.config_flags
& 1 != 0`) now store the feed directly on oracles[0], use that key directly as the oracle instead. - If you were using your own feed (e.g. neither Pyth nor Mrgn sponsored), you may no longer do so.
- Remember to update your Rust type-crate or program dependency.
BREAKING (ADMIN ONLY)
- set/unset user flags ixes removed (all user flags are now deprecated)
- When configuring banks with pyth oracles, pass the oracle directly instead of the feed id. You no longer ever need to worry about the feed id.
- When configuring banks, an additional argument is passed (
oracle_max_confidence
). Oracle checks fail if this is exceeded. Pass 0 to use the default (10%). - changing emissions now requires
delegate_emissions_admin
instead of regularadmin
.
NEW FIELDS AND OTHER NOTES
- Account authority is now immutable
- Frozen fields still can't update even with a delegated admin right, e.g. the delegate curve admin cannot do anything if a bank is frozen.
- Account gains
migrated_to
andmigrated_from
fields that indicate ithe key of the new/previous mrgnfi account when an account is migrated to a new authority. Accounts migrated like this form essentially a doubly linked list of accounts, so you can always follow these references to trace back to the "root" account or to the "current" one. - bank.config and the config input types added field
oracle_max_confidence
- bank added field bank.cache
- bank added field
lending_position_count
andborrowing_position_count
- Group added fields
delegate_curve_admin
,delegate_limit_admin
, anddelegate_emissions_admin
PYTH MIGRATION INSTRUCTIONS AND NOTES
- Banks that have not migrated will continue to function as normal until they migrate.
- Pyth banks that migrate will no longer store the feed id on oracles[0], instead they will store the key of the feed directly, just like switchboard oracles already do. After the ix completes, these banks will now accept that oracle and no other feeds.
- Simply run
migrate_pyth_push_oracle
for all banks that existed prior to 0.1.4 going live. Non-Pyth banks will set the migration flag and do nothing. Pyth banks (excluding staked collateral) will accept either the Pyth or Mrgn sponsored oracle feed. The feed must exist (e.g. not be a blank account). - Staked collateral banks must use
propagate_staked_settings
instead. These will always use the Pyth sponsored oracle. - Next time
edit_staked_settings
runs, remember to also update the oracle to use the SOL feed. This can happen any time in the future, it does not have to happen to complete migration, but propagation of future settings will fail until it's done. - New banks will now take the feed instead of the feed id when being created.
- Migration functionality will be removed in 0.1.5
Deployments
Staging - July 25, 2025 at ~7:15 ET
Mainnet - TBD
mrgn - 0.1.4-rc1
SUMMARY
- Adds a new way to transfer your account:
transfer_to_new_account
transfers all of your positions to a new account, with an authority of your choosing. This allows you to give your positions to others or move them between your own wallets. The process incurs a nominal fee in SOL (~$0.50 today) to avoid spam.- We expect that points earned by the source of the transfer will go to the destination account. For example, if account A migrates to B, then B migrates to C, then C will earn all of the points combined for A and B. Currently, points will continue to display on A and B separately, we will figure out how to combine them at a later date.
- Adds a bank cache, where consumers can view recent information about a bank's interest rates (APR), and interest recently earned.
- Removes Pyth legacy (aka v1, pythnet, or "push") oracle support from the program.
- Fixes a bug with the switchboard oracles where confidence was incorrectly either 0 or clamped at 5%. All users participating in swb banks should see a tiny improvement to their account health and corresponding increase in borrowing power
- Oracle pricing is now totally suspended during periods of poor price confidence, where the allowed confidence is now configurable per bank. We expect this will reduce unfair liquidations during periods of extreme price volatility, but should not affect normal operation in the vast majority of cases.
- Banks created after the release of 0.1.4 can now be closed by the group admin to recover rent, but only if they have no open positions, no emissions, and no assets. Banks created prior to 0.1.4 can never be closed.
- Banks now track the total number of open positions, subsequent to the release of 0.1.4 (Note: for new banks, this will always be 0 or greater, for banks created prior to 0.1.4, this may be negative as closed positions reduce the count).
- Adds delegate administrators for emissions, curve parameters, and deposit/borrow caps. These admins can modify only a small subset of settings, which makes them safe(r) to grant to a hot wallet or MS with limited signature threshold. The group admin is still free to modify most bank parameters.
Consolidates:
- #349 (adds bank cache to record spot interest rates, etc)
- #343 (removes Pyth legacy support from the program and test suite)
- #344 (Restores Rust CLI functionality which was broken in 0.1.3)
- #350 (Tests usage of multiple staked collateral banks at once)
- #351 (minor TS error handling update)
- #353 (remove pyth legacy from test suite)
- #356 (fix swb std dev issue)
- #354 (new account migration instruction)
- #355 (minor fixes following second emode audit suggestion)
- #356 (Fix usage of std dev aka confidence in swb oracles)
- #358 (Pyth accounts store the feed directly instead of feed id)
- #359 (Oracles fail when a confidence threshold is exceeded)
- #360 (Banks track open positions and can be closed)
- #361 (Delegate admins for setting various bank params)
BREAKING CHANGES
- Always remember to update your TS package to the latest version.
- Removes the old account migration instruction, which required the group admin (the multisig) to sign. Users can now migrate their balances to a new account at any time without admin approval using the new
transfer_to_new_account
ix - If you were deriving the Pyth oracle using oracles[0] (formerly the feed id) and a shard id, this is no longer possible. Banks that have migrated (e.g. where
bank.config.config_flags
& 1 != 0`) now store the feed directly on oracles[0], use that key directly as the oracle instead. - If you were using your own feed (e.g. neither Pyth nor Mrgn sponsored), you may no longer do so.
- Remember to update your Rust type-crate or program dependency.
BREAKING (ADMIN ONLY)
- set/unset user flags ixes removed (all user flags are now deprecated)
- When configuring banks with pyth oracles, pass the oracle directly instead of the feed id. You no longer ever need to worry about the feed id.
- When configuring banks, an additional argument is passed (
oracle_max_confidence
). Oracle checks fail if this is exceeded. Pass 0 to use the default (10%). - changing emissions now requires
delegate_emissions_admin
instead of regularadmin
.
NEW FIELDS AND OTHER NOTES
- Account authority is now immutable
- Frozen fields still can't update even with a delegated admin right, e.g. the delegate curve admin cannot do anything if a bank is frozen.
- bank.config and the config input types added field
oracle_max_confidence
- bank added field bank.cache
- bank added field
lending_position_count
andborrowing_position_count
- Group added fields
delegate_curve_admin
,delegate_limit_admin
, anddelegate_emissions_admin
PYTH MIGRATION INSTRUCTIONS AND NOTES
- Banks that have not migrated will continue to function as normal until they migrate.
- Pyth banks that migrate will no longer store the feed id on oracles[0], instead they will store the key of the feed directly, just like switchboard oracles already do. After the ix completes, these banks will now accept that oracle and no other feeds.
- Simply run
migrate_pyth_push_oracle
for all banks that existed prior to 0.1.4 going live. Non-Pyth banks will set the migration flag and do nothing. Pyth banks (excluding staked collateral) will accept either the Pyth or Mrgn sponsored oracle feed. The feed must exist (e.g. not be a blank account). - Staked collateral banks must use
propagate_staked_settings
instead. These will always use the Pyth sponsored oracle. - Next time
edit_staked_settings
runs, remember to also update the oracle to use the SOL feed. This can happen any time in the future, it does not have to happen to complete migration, but propagation of future settings will fail until it's done. - New banks will now take the feed instead of the feed id when being created.
- Migration functionality will be removed in 0.1.5
Deployments
Staging - ~4:45 ET
mrgn - 0.1.3-rc2
Summary
Adds Emode, updates to Anchor 0.31.1, creates a predictable order for remaining accounts, and improves Health Cache information.
Changes from 0.1.3 -> rc
Various memory usage improvements.
Changes from 0.1.2 and earlier
Breaking Changes (Everyone)
- Upgraded to Anchor 0.31.1. To build and run all tests, the toolset we use is:
- rust/cargo - latest stable
- node - 23.0.0
- yarn - 1.22.22
- avm - 0.30.1 or later
- anchor - 0.31.1
- solana - 2.1.20
If updating from a previous version, we suggest cargo clean
anchor clean
and yarn install
before rebuilding. You may also need to rustup update
if your nightly version is outdated (Anchor uses it to build the idl) and you may need to upgrade your Linux version to support Solana 2.0+ (e.g. Ubuntu 22LTS or later).
- Account Health Caches from 0.1.2 are no longer valid. The account Health Cache now has considerably more information about internal risk state. See #325 for a full list of changes. Liquidators and indexers of marginfi should be particularly interested.
bank_liquidity_vault_authority
is no no longer mut in withdraw, this should not affect consumers who have updated to the most recent idl.- Gapless accounts - remaining accounts are now always packed in sorted order, and so are the balances in user lending accounts. No more guessing the order positions go in! This should be especially helpful to consumers who store user account information in a database, as you no longer need to track the order that positions appear in. Some additional notes on this feature:
- Accounts that are not currently in sorted order will sort themselves when they next interact with the platform (e.g. borrow, deposit, withdraw, repay, etc). Pass accounts for these in sorted order as well (NOT in their original order).
- When an account picks up a new positions (e.g. during borrow or liquidation), that account should be passed the same way as all the others, i.e. it will also become sorted.
- You can crank
lending_account_sort_balances
on any legacy user account to sort it immediately. We will (eventually) crank this for all users that have active balances. - Accounts will now never have gaps, when encountering a blank space in the user's lending balances, you may safely assume the rest is blank.
- All consumers must now pass remaining accounts in sorted order by pubkey, use the helpful utility function like this:
composeRemainingAccounts([
[someBank, someOracle],
[anotherBank, anotherOracle],
[yetAnotherBank, yetAnotherOracle],
]
Breaking Changes (Admin Only)
- configure group now accepts an additional pubkey (the emode admin)
- configure_bank_emode added to set up and change emode configurations.
Changes and Additions
- Emode: a powerful enhancement that enables us to treat certain kinds of collateral more favorably when the user is borrowing a correlated asset. Learn more at #318 or read the guide under guides/EMODE_ADMIN.md
- Various logging and error reporting improvements.
- Switchboard v2 (the legacy push style oracle) is deprecated and will panic on any attempted use. This does not affect any banks in production.
- CI, compile, and test times have improved across the board.
- The "Liquidity Incentive" program is no longer part of the workspace. While any campaigns currently in prod should continue to function, we have no plans to continue development on this program.
- Various logs that emitted a I80F48 as a u128 interpreted in le bytes now emit an f64 that is actually human readable instead.
- Adds a Rust types crate to the repo with minimal dependencies, useful if you don't want to clone the entire repo just to access our types. We will update this in every major version release and expect to publish this eventually.
Full List of Changes
- #316
- #318
- #321
- #323
- #324
- #325 (actually merged #330 but discussion is in previous)
- #326
- #327
- #320
- #332
- #333
Bugfixes
- Now builds without cargo.lock, cargo clean to your heart's content.
- The IDL now builds with errors/events types. No more hacking them in manually!
- Fixes an issue that would sometimes occur when testing switchboard pull accounts on certain machines locally due to the 16-byte alignment of swb accounts.
test-program-remix.sh
no longer occasionally hangs for 10s when a tx fails to simulate.- We now enforce that the maintenance weight is less than 200%. No weight has ever been over 100%, this mitigation is simply to prevent sausage fingers.
Known Issues
- Building marginfi-v2 will throw up stack warnings from libsecp256k1 and other deps, these can be ignored.
- Some type issues may occur with Bankrun's older web3.js implementation in the TS test suite, the fix in tsconfig generally addresses this.
- The fuzz test suite may require cargo patches to get functional (see the cargo.toml in the fuzz suite if you care about running it locally).
Release Times:
- Staging: April 30, 2025 ~1:30pm ET -- No hash check
- Mainnet: May 27, 2025 ~1pm ET - ae9adb
mrgn - 0.1.3
Summary
Adds Emode, updates to Anchor 0.31.1, creates a predictable order for remaining accounts, and improves Health Cache information.
Breaking Changes (Everyone)
- Upgraded to Anchor 0.31.1. To build and run all tests, the toolset we use is:
- rust/cargo - latest stable
- node - 23.0.0
- yarn - 1.22.22
- avm - 0.30.1 or later
- anchor - 0.31.1
- solana - 2.1.20
If updating from a previous version, we suggest cargo clean
anchor clean
and yarn install
before rebuilding. You may also need to rustup update
if your nightly version is outdated (Anchor uses it to build the idl) and you may need to upgrade your Linux version to support Solana 2.0+ (e.g. Ubuntu 22LTS or later).
- Account Health Caches from 0.1.2 are no longer valid. The account Health Cache now has considerably more information about internal risk state. See #325 for a full list of changes. Liquidators and indexers of marginfi should be particularly interested.
bank_liquidity_vault_authority
is no no longer mut in withdraw, this should not affect consumers who have updated to the most recent idl.- Gapless accounts - remaining accounts are now always packed in sorted order, and so are the balances in user lending accounts. No more guessing the order positions go in! This should be especially helpful to consumers who store user account information in a database, as you no longer need to track the order that positions appear in. Some additional notes on this feature:
- Accounts that are not currently in sorted order will sort themselves when they next interact with the platform (e.g. borrow, deposit, withdraw, repay, etc). Pass accounts for these in sorted order as well (NOT in their original order).
- When an account picks up a new positions (e.g. during borrow or liquidation), that account should be passed the same way as all the others, i.e. it will also become sorted.
- You can crank
lending_account_sort_balances
on any legacy user account to sort it immediately. We will (eventually) crank this for all users that have active balances. - Accounts will now never have gaps, when encountering a blank space in the user's lending balances, you may safely assume the rest is blank.
- All consumers must now pass remaining accounts in sorted order by pubkey, use the helpful utility function like this:
composeRemainingAccounts([
[someBank, someOracle],
[anotherBank, anotherOracle],
[yetAnotherBank, yetAnotherOracle],
]
Breaking Changes (Admin Only)
- configure group now accepts an additional pubkey (the emode admin)
- configure_bank_emode added to set up and change emode configurations.
Changes and Additions
- Emode: a powerful enhancement that enables us to treat certain kinds of collateral more favorably when the user is borrowing a correlated asset. Learn more at #318 or read the guide under guides/EMODE_ADMIN.md
- Various logging and error reporting improvements.
- Switchboard v2 (the legacy push style oracle) is deprecated and will panic on any attempted use. This does not affect any banks in production.
- CI, compile, and test times have improved across the board.
- The "Liquidity Incentive" program is no longer part of the workspace. While any campaigns currently in prod should continue to function, we have no plans to continue development on this program.
- Various logs that emitted a I80F48 as a u128 interpreted in le bytes now emit an f64 that is actually human readable instead.
- Adds a Rust types crate to the repo with minimal dependencies, useful if you don't want to clone the entire repo just to access our types. We will update this in every major version release and expect to publish this eventually.
Full List of Changes
- #316
- #318
- #321
- #323
- #324
- #325 (actually merged #330 but discussion is in previous)
- #326
- #327
- #320
- #332
- #333
Bugfixes
- Now builds without cargo.lock, cargo clean to your heart's content.
- The IDL now builds with errors/events types. No more hacking them in manually!
- Fixes an issue that would sometimes occur when testing switchboard pull accounts on certain machines locally due to the 16-byte alignment of swb accounts.
test-program-remix.sh
no longer occasionally hangs for 10s when a tx fails to simulate.- We now enforce that the maintenance weight is less than 200%. No weight has ever been over 100%, this mitigation is simply to prevent sausage fingers.
Known Issues
- Building marginfi-v2 will throw up stack warnings from libsecp256k1 and other deps, these can be ignored.
- Some type issues may occur with Bankrun's older web3.js implementation in the TS test suite, the fix in tsconfig generally addresses this.
- The fuzz test suite may require cargo patches to get functional (see the cargo.toml in the fuzz suite if you care about running it locally).
Release Times:
- Staging: April 30, 2025 ~1:30pm ET -- No hash check
- Mainnet: TBD
mrgn - 0.1.2
Summary of New Features
- Implied anchor args everywhere - TS consumers rejoice, no more having to pass every account the instruction requires. Most instructions now require only a handful of accounts, and infer the rest.
- Deposit up to limit - pass a flag to deposit up to the bank's deposit cap. No more guessing if a bank has capacity.
- Permissionless incentives - program-level support to designate a wallet that can receive your earned incentives without any input from you. We'll crank users that opt-in on a regular basis, so no more missing out on rewards because you forgot to claim them (front end for this is coming soon at a date TBD)
- Logging improvements everywhere
- Health pulse instruction to view internal account health
- Preparations for Arena permissionless pools launch
Breaking Changes
account.lending_account.balances[n]
is now a u8 instead of bool (0 = false, 1 = true)MarginfiAccount
padding now split intopadding0
andpadding1
BankConfig
padding now split intopadding0
andpadding1
- Almost all instructions are now modified to use implied anchor args. Some argument names have changed (e.g. marginfi_group -> group), but order is maintained. This should be non-breaking to Rust clients passing simple account meta, but may be breaking to TS clients passing account manually, or to CPI consumers. All accounts that have undergone a name change will now be inferred and can be omitted. Use accountsPartial as a fallback if this fails.
- deposit instruction now accepts one additional argument (an
Option<bool>
) to flag if the depositor wants to deposit up to the bank's available limit. Actual deposit will bemin(amount specified in deposit arg, deposit limit remaining in bank)
- Various Stale Oracle and Illegal Liquidation errors now emit a more specific custom error. Update is only required if you were checking for a specific error code.
marginfiGroupInitialize
now takes an admin and a bool arg (true to set as an arena group)marginfiGroupConfigure
now takes an admin and a bool arg (true to set as an arena group)MarginfiGroup
now has a banks field which tracks the number of banks created under that group
New Instructions
marginfi_account_update_emissions_destination_account
- allows a user to designate a wallet where their earned emissions can be permissionlessly withdrawn into. Users who do not opt into this feature can only withdraw manuallylending_account_withdraw_emissions_permissionless
- a permissionless ix that withdraws emissions into an account users chose when they opted into permissionless emissions.lending_account_health_pulse
- a permissionless ix that caches the internal health information computed by the risk engine. Fetch the user account and read the health_cache to see information about prices used, net asset and liability prices, etc.
New Logging
- On risk engine failure, now anchor logs various internal information.
- Many new error messages, replacing existing generic errors like
StaleOracle
andIllegalLiquidation
- On any add or config instruction (add bank, configure group, configure bank, etc) now echos the settings being changed in anchor logs
Known Bugs/limitations
- group.banks only tracks the number of banks created after 0.1.2 goes live
- Groups created prior to the 0.1.2 update can be incorrectly configured as arena groups since we do not count banks created prior to that update.
- Since this basically only affects the mrgn-owned main group and mrgn-owned Arena group used for testing, this is a non-issue. We will, prior to Arena launch, double check that there are no other affected groups.
Deployment details
Deployed staging: March 14, 2025 ~3:00pm ET (hash 65bbbe)
Deployed mainnet: April 14, 2024 ~1:00pm ET (hash 65bbbe)