Skip to content

Feat/solana missing features#21

Draft
kostyamospan wants to merge 62 commits intomainfrom
feat/solana-missing-features
Draft

Feat/solana missing features#21
kostyamospan wants to merge 62 commits intomainfrom
feat/solana-missing-features

Conversation

@kostyamospan
Copy link
Copy Markdown
Collaborator

No description provided.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @kostyamospan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the Midas Vaults protocol by introducing a maximum supply cap for mTokens, providing more robust control over token issuance. It also refactors and expands the approval mechanisms for both mint and redeem requests with new 'safe' instructions, offering greater flexibility and error handling. Furthermore, the changes include improvements to data feed management and a comprehensive set of new developer tools for better monitoring and verification of the system's state.

Highlights

  • Minter Vault Max Supply Cap: Introduced a new max_supply_cap feature for Minter Vaults, allowing administrators to set a maximum limit on the total supply of mTokens that can be minted. This includes adding a new error MaxSupplyCapExceeded and integrating the cap into instant minting and mint request approval processes.
  • New Safe Approval Instructions for Vaults: Implemented new 'safe' approval instructions for both Minter and Redeemer Vaults. These instructions (safe_approve_mint_request_at_current_rate, safe_approve_mint_request_at_request_rate, safe_approve_redeem_request_at_current_rate, safe_approve_redeem_request_at_request_rate) provide more granular control, allowing approvals to be based on current market rates or original request rates, and include options to skip processing if supply caps are exceeded or liquidity is insufficient.
  • Refactored Approval Logic into Utility Functions: Centralized the core logic for approving mint and redeem requests into new utility functions (minter::approve_mint_request and redeemer::approve_redeem_request). This improves code reusability and maintainability across different approval mechanisms.
  • Enhanced Switchboard Feed Pulling: Updated the Switchboard feed pulling mechanism to intelligently check for staleness before attempting to update a feed. This optimization reduces unnecessary transactions and improves efficiency by only pulling data when required.
  • Expanded Developer Verification Scripts: Added a suite of new verification scripts to aid developers in debugging and monitoring the state of the protocol. These include scripts for listing all pending requests, minting test payment tokens, verifying data feed configurations, checking mint/redeem vault states, inspecting roles, and confirming program upgrade authorities.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • package.json
    • Removed the 'anchor:script' command from the scripts section.
  • programs/access-control/Cargo.toml
    • Added the 'anchor-debug' feature.
  • programs/data-feed/Cargo.toml
    • Added the 'anchor-debug' feature.
  • programs/midas-vault/Cargo.toml
    • Added the 'anchor-debug' feature.
  • programs/midas-vault/src/errors.rs
    • Added a new error variant MaxSupplyCapExceeded.
  • programs/midas-vault/src/events.rs
    • Added max_supply_cap as an optional field to MinterVaultUpdatedEvent.
  • programs/midas-vault/src/instructions/minter_vault/approve_mint_request.rs
    • Updated imports, modified vault_common account constraint, and refactored the handle function to use a new minter::approve_mint_request utility, adding skip_on_supply_cap_exceeded parameter.
  • programs/midas-vault/src/instructions/minter_vault/mint_instant.rs
    • Imported validate_max_supply_cap and integrated a check for max_supply_cap before minting.
  • programs/midas-vault/src/instructions/minter_vault/mod.rs
    • Added new modules for safe_approve_mint_request_at_current_rate and safe_approve_mint_request_at_request_rate.
  • programs/midas-vault/src/instructions/minter_vault/new_minter_vault.rs
    • Added max_supply_cap parameter to the handle function and included it in the MinterVaultUpdatedEvent.
  • programs/midas-vault/src/instructions/minter_vault/reject_mint_request.rs
    • Modified the vault_common account constraint.
  • programs/midas-vault/src/instructions/minter_vault/safe_approve_mint_request_at_current_rate.rs
    • Added a new instruction to safely approve mint requests at the current data feed rate, including a skip_on_supply_cap_exceeded option.
  • programs/midas-vault/src/instructions/minter_vault/safe_approve_mint_request_at_request_rate.rs
    • Added a new instruction to safely approve mint requests at the original request rate, including a skip_on_supply_cap_exceeded option.
  • programs/midas-vault/src/instructions/minter_vault/update_minter_vault.rs
    • Added max_supply_cap as an optional parameter to the handle function and included it in the MinterVaultUpdatedEvent.
  • programs/midas-vault/src/instructions/redeemer_vault/approve_redeem_request.rs
    • Removed mut from vault_common account, added safe_validate_liquidity parameter, and refactored the handle function to use a new redeemer::approve_redeem_request utility.
  • programs/midas-vault/src/instructions/redeemer_vault/approve_redeem_request_fiat.rs
    • Modified the vault_common account constraint and refactored the handle function to use the new redeemer::approve_redeem_request utility.
  • programs/midas-vault/src/instructions/redeemer_vault/mod.rs
    • Added new modules for safe_approve_redeem_request_at_current_rate and safe_approve_redeem_request_at_request_rate.
  • programs/midas-vault/src/instructions/redeemer_vault/reject_redeem_request.rs
    • Modified the vault_common account constraint.
  • programs/midas-vault/src/instructions/redeemer_vault/safe_approve_redeem_request_at_current_rate.rs
    • Added a new instruction to safely approve redeem requests at the current data feed rate, including a safe_validate_liquidity option.
  • programs/midas-vault/src/instructions/redeemer_vault/safe_approve_redeem_request_at_request_rate.rs
    • Added a new instruction to safely approve redeem requests at the original request rate, including a safe_validate_liquidity option.
  • programs/midas-vault/src/lib.rs
    • Updated the new_minter_vault, update_minter_vault, approve_mint_request, and approve_redeem_request public functions to incorporate new parameters, and added new public functions for the 'safe' approval instructions.
  • programs/midas-vault/src/state/minter_vault_state.rs
    • Added a max_supply_cap field to the MinterVaultState struct.
  • programs/midas-vault/src/utils.rs
    • Imported MintVaultRequestState, added validate_max_supply_cap and redeemer::validate_liquidity functions, and refactored minter::approve_mint_request and redeemer::approve_redeem_request to use new parameters and logic.
  • programs/token-authority/Cargo.toml
    • Added the 'anchor-debug' feature.
  • scripts/README.md
    • Updated the 'Local test utilities' section to reflect new and moved verification scripts.
  • scripts/approve-redeem-request.ts
    • Added safeValidateLiquidity argument to the script and passed it to the approveRedeemRequest instruction.
  • scripts/configs/types.ts
    • Added maxSupplyCap as an optional field to the minterVaultConfigSchema.
  • scripts/deploy/feeds/switchboard.ts
    • Exported SWITCHBOARD_PROGRAM_IDS for broader use.
  • scripts/deploy/vaults.ts
    • Imported MAX_U64, added maxSupplyCap to DeployMinterVaultConfig, and updated deployMinterVault to utilize the new maxSupplyCap.
  • scripts/mint-instant.ts
    • Updated pullSwitchboardFeeds call to include maxStalenessSeconds and added a usage example.
  • scripts/mint-request.ts
    • Updated pullSwitchboardFeeds call to include maxStalenessSeconds and added a usage example.
  • scripts/redeem-instant.ts
    • Updated pullSwitchboardFeeds call to include maxStalenessSeconds and added a usage example.
  • scripts/redeem-request-fiat.ts
    • Updated pullSwitchboardFeeds call to include maxStalenessSeconds and added a usage example.
  • scripts/redeem-request.ts
    • Updated pullSwitchboardFeeds call to include maxStalenessSeconds and added a usage example.
  • scripts/tasks/deploy/deploy-minter-vault.ts
    • Updated the deployMinterVault call to pass the maxSupplyCap from the configuration.
  • scripts/utils/switchboardHelpers.ts
    • Added maxStalenessSeconds to SwitchboardFeedInfo, introduced isSwitchboardFeedStale to check feed freshness, and modified pullSwitchboardFeeds to only update stale feeds.
  • scripts/verify/get-all-requests.ts
    • Added a new script to fetch and display all pending mint and redeem requests, including detailed information and approval status for redeem requests.
  • scripts/verify/mint-payment-token.ts
    • Added a new script to facilitate minting of test payment tokens to a specified recipient.
  • scripts/verify/verify-feed.ts
    • Added a new script to verify the configuration and current price of data feeds, supporting manual and Switchboard modes.
  • scripts/verify/verify-mint-state.ts
    • Added a new script to verify the state of a minter vault, including balances and daily limits.
  • scripts/verify/verify-payment-tokens.ts
    • Added a new script to check the on-chain state of payment tokens associated with a vault.
  • scripts/verify/verify-redeem-request.ts
    • Added a new script to provide detailed verification and analysis of a specific redeem request, including allowance checks and recommendations.
  • scripts/verify/verify-roles.ts
    • Added a new script to verify the roles assigned to a given public key for a specific mToken.
  • scripts/verify/verify-upgrade-authority.ts
    • Added a new script to check the upgrade authority for various programs on the Solana blockchain.
  • test/constants/vaults.constants.ts
    • Added MaxSupplyCapExceeded to the VaultError enum.
  • test/fixture/vaults.fixture.ts
    • Imported MAX_U64 and updated the newMinterVault call to initialize with MAX_U64 as the default max supply cap.
  • test/minter-vault.test.ts
    • Added new test cases for updateMinterVault with maxSupplyCap, mintInstant with supply cap checks, approveMintRequest with skipOnSupplyCapExceeded, and comprehensive tests for the new safe_approve_mint_request_at_current_rate and safe_approve_mint_request_at_request_rate instructions.
  • test/redeemer-vault.test.ts
    • Added new test cases for approveRedeemRequest with safeValidateLiquidity, and extensive tests for the new safe_approve_redeem_request_at_current_rate and safe_approve_redeem_request_at_request_rate instructions, including bulk approval scenarios and transaction size analysis.
  • test/testers/minter-vault.testers.ts
    • Updated newMinterVault and updateMinterVault testers to handle maxSupplyCap, enhanced approveMintRequest to support skipOnSupplyCapExceeded and expectSkipped, and introduced testers for safeApproveMintRequestAtCurrentRate and safeApproveMintRequestAtRequestRate.
  • test/testers/redeem-vault.testers.ts
    • Updated approveRedeemRequest tester to include safeValidateLiquidity and expectSkipped parameters, and added testers for safeApproveRedeemRequestAtCurrentRate and safeApproveRedeemRequestAtRequestRate.
  • vitest.config.ts
    • Configured Vitest to run test files sequentially (fileParallelism: false) and adjusted timeouts for hooks and teardown to accommodate Solana test environments.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several significant features, including a max supply cap for mTokens, safer approval flows for mint/redeem requests with options to skip on certain conditions, and substantial refactoring of scripts and tests. The changes are extensive and well-structured. My review focuses on ensuring the new logic is sound and doesn't introduce vulnerabilities. I've identified a critical issue in the order of operations for redeem approvals that could lead to fund loss, along with several potential panic points in the new utility functions due to the use of unwrap(). I've also suggested some simplifications for improved code clarity.

Comment on lines +692 to +698
let amount_to_mint = (request.deposited_usd_wo_fees as u128)
.checked_mul(ONE.into())
.unwrap()
.checked_div(new_out_rate)
.unwrap();

if !validate_max_supply_cap(m_mint, minter_vault, amount_to_mint.try_into().unwrap()) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

This function uses .unwrap() in two places, which can cause the program to panic:

  1. checked_div(new_out_rate).unwrap(): If new_out_rate is 0, this will panic. An admin could provide 0 as an argument.
  2. amount_to_mint.try_into().unwrap(): This converts a u128 to a u64. If amount_to_mint exceeds u64::MAX, this will panic.

These should be handled by returning a Result::Err instead of panicking to make the program more robust.

        let amount_to_mint = (request.deposited_usd_wo_fees as u128)
            .checked_mul(ONE.into())
            .ok_or(MidasVaultsError::InvalidOutAmount)?
            .checked_div(new_out_rate)
            .ok_or(MidasVaultsError::InvalidRate)?;

        let amount_to_mint_u64: u64 = amount_to_mint.try_into().map_err(|_| MidasVaultsError::InvalidOutAmount)?;
        if !validate_max_supply_cap(m_mint, minter_vault, amount_to_mint_u64) {

Comment on lines +235 to +238
pub fn validate_max_supply_cap(m_mint: &Mint, minter: &MinterVaultState, mint_amount: u64) -> bool {
let new_supply = m_mint.supply.checked_add(mint_amount).unwrap();
minter.max_supply_cap >= new_supply
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The use of .unwrap() on checked_add can cause a panic if the total supply overflows a u64. While this is an edge case, it's safer to handle potential overflows gracefully by returning false instead of panicking.

Suggested change
pub fn validate_max_supply_cap(m_mint: &Mint, minter: &MinterVaultState, mint_amount: u64) -> bool {
let new_supply = m_mint.supply.checked_add(mint_amount).unwrap();
minter.max_supply_cap >= new_supply
}
pub fn validate_max_supply_cap(m_mint: &Mint, minter: &MinterVaultState, mint_amount: u64) -> bool {
match m_mint.supply.checked_add(mint_amount) {
Some(new_supply) => minter.max_supply_cap >= new_supply,
None => false, // Overflow implies the cap is exceeded.
}
}

Comment on lines +133 to 156
match minter::approve_mint_request(
&ctx.accounts.mint_request,
&ctx.accounts.vault_common,
&ctx.accounts.minter_vault,
&ctx.accounts.m_mint,
&ctx.accounts.m_mint_user_ata,
&ctx.accounts.m_mint_token_program,
&ctx.accounts.user_account,
&ctx.accounts.token_authority,
&ctx.accounts.vault_minter_role,
&ctx.accounts.system_program,
&ctx.accounts.token_authority_program,
request_id,
new_out_rate.into(),
is_safe,
skip_on_supply_cap_exceeded,
) {
Ok(true) => {
ctx.accounts.close()?;
Ok(())
}
Ok(false) => Ok(()),
Err(e) => Err(e),
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The match statement for handling the Result<bool> can be simplified for better readability and conciseness. Using if let or the ? operator is more idiomatic in this case.

    if minter::approve_mint_request(
        &ctx.accounts.mint_request,
        &ctx.accounts.vault_common,
        &ctx.accounts.minter_vault,
        &ctx.accounts.m_mint,
        &ctx.accounts.m_mint_user_ata,
        &ctx.accounts.m_mint_token_program,
        &ctx.accounts.user_account,
        &ctx.accounts.token_authority,
        &ctx.accounts.vault_minter_role,
        &ctx.accounts.system_program,
        &ctx.accounts.token_authority_program,
        request_id,
        new_out_rate.into(),
        is_safe,
        skip_on_supply_cap_exceeded,
    )? {
        ctx.accounts.close()?;
    }

    Ok(())

Comment on lines +149 to +172
match minter::approve_mint_request(
&ctx.accounts.mint_request,
&ctx.accounts.vault_common,
&ctx.accounts.minter_vault,
&ctx.accounts.m_mint,
&ctx.accounts.m_mint_user_ata,
&ctx.accounts.m_mint_token_program,
&ctx.accounts.user_account,
&ctx.accounts.token_authority,
&ctx.accounts.vault_minter_role,
&ctx.accounts.system_program,
&ctx.accounts.token_authority_program,
request_id,
current_rate,
true,
skip_on_supply_cap_exceeded,
) {
Ok(true) => {
ctx.accounts.close()?;
Ok(())
}
Ok(false) => Ok(()),
Err(e) => Err(e),
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The match statement for handling the Result<bool> can be simplified for better readability and conciseness. Using if let or the ? operator is more idiomatic in this case.

    if minter::approve_mint_request(
        &ctx.accounts.mint_request,
        &ctx.accounts.vault_common,
        &ctx.accounts.minter_vault,
        &ctx.accounts.m_mint,
        &ctx.accounts.m_mint_user_ata,
        &ctx.accounts.m_mint_token_program,
        &ctx.accounts.user_account,
        &ctx.accounts.token_authority,
        &ctx.accounts.vault_minter_role,
        &ctx.accounts.system_program,
        &ctx.accounts.token_authority_program,
        request_id,
        current_rate,
        true,
        skip_on_supply_cap_exceeded,
    )? {
        ctx.accounts.close()?;
    }

    Ok(())

Comment on lines +131 to +154
match minter::approve_mint_request(
&ctx.accounts.mint_request,
&ctx.accounts.vault_common,
&ctx.accounts.minter_vault,
&ctx.accounts.m_mint,
&ctx.accounts.m_mint_user_ata,
&ctx.accounts.m_mint_token_program,
&ctx.accounts.user_account,
&ctx.accounts.token_authority,
&ctx.accounts.vault_minter_role,
&ctx.accounts.system_program,
&ctx.accounts.token_authority_program,
request_id,
new_out_rate,
false,
skip_on_supply_cap_exceeded,
) {
Ok(true) => {
ctx.accounts.close()?;
Ok(())
}
Ok(false) => Ok(()),
Err(e) => Err(e),
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The match statement for handling the Result<bool> can be simplified for better readability and conciseness. Using if let or the ? operator is more idiomatic in this case.

    if minter::approve_mint_request(
        &ctx.accounts.mint_request,
        &ctx.accounts.vault_common,
        &ctx.accounts.minter_vault,
        &ctx.accounts.m_mint,
        &ctx.accounts.m_mint_user_ata,
        &ctx.accounts.m_mint_token_program,
        &ctx.accounts.user_account,
        &ctx.accounts.token_authority,
        &ctx.accounts.vault_minter_role,
        &ctx.accounts.system_program,
        &ctx.accounts.token_authority_program,
        request_id,
        new_out_rate,
        false,
        skip_on_supply_cap_exceeded,
    )? {
        ctx.accounts.close()?;
    }

    Ok(())

Comment on lines +170 to +193
match redeemer::approve_redeem_request(
&ctx.accounts.redeem_request,
&ctx.accounts.vault_common,
&ctx.accounts.redeemer_vault,
&ctx.accounts.m_mint_token_program,
&ctx.accounts.m_mint,
&ctx.accounts.m_mint_vault_ata,
&mut ctx.accounts.payment_mint_state,
Some(&ctx.accounts.payment_mint),
Some(&ctx.accounts.payment_mint_token_program),
Some(&ctx.accounts.payment_mint_redeemer_ata),
Some(&ctx.accounts.payment_mint_user_ata),
request_id,
new_m_token_rate.into(),
true,
safe_validate_liquidity,
) {
Ok(true) => {
ctx.accounts.close()?;
Ok(())
}
Ok(false) => Ok(()),
Err(e) => Err(e),
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The match statement for handling the Result<bool> can be simplified for better readability and conciseness. Using if let or the ? operator is more idiomatic in this case.

    if redeemer::approve_redeem_request(
        &ctx.accounts.redeem_request,
        &ctx.accounts.vault_common,
        &ctx.accounts.redeemer_vault,
        &ctx.accounts.m_mint_token_program,
        &ctx.accounts.m_mint,
        &ctx.accounts.m_mint_vault_ata,
        &mut ctx.accounts.payment_mint_state,
        Some(&ctx.accounts.payment_mint),
        Some(&ctx.accounts.payment_mint_token_program),
        Some(&ctx.accounts.payment_mint_redeemer_ata),
        Some(&ctx.accounts.payment_mint_user_ata),
        request_id,
        new_m_token_rate.into(),
        true,
        safe_validate_liquidity,
    )? {
        ctx.accounts.close()?;
    }

    Ok(())

Comment on lines +151 to +174
match redeemer::approve_redeem_request(
&ctx.accounts.redeem_request,
&ctx.accounts.vault_common,
&ctx.accounts.redeemer_vault,
&ctx.accounts.m_mint_token_program,
&ctx.accounts.m_mint,
&ctx.accounts.m_mint_vault_ata,
&mut ctx.accounts.payment_mint_state,
Some(&ctx.accounts.payment_mint),
Some(&ctx.accounts.payment_mint_token_program),
Some(&ctx.accounts.payment_mint_redeemer_ata),
Some(&ctx.accounts.payment_mint_user_ata),
request_id,
new_m_token_rate.into(),
false,
safe_validate_liquidity,
) {
Ok(true) => {
ctx.accounts.close()?;
Ok(())
}
Ok(false) => Ok(()),
Err(e) => Err(e),
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The match statement for handling the Result<bool> can be simplified for better readability and conciseness. Using if let or the ? operator is more idiomatic in this case.

    if redeemer::approve_redeem_request(
        &ctx.accounts.redeem_request,
        &ctx.accounts.vault_common,
        &ctx.accounts.redeemer_vault,
        &ctx.accounts.m_mint_token_program,
        &ctx.accounts.m_mint,
        &ctx.accounts.m_mint_vault_ata,
        &mut ctx.accounts.payment_mint_state,
        Some(&ctx.accounts.payment_mint),
        Some(&ctx.accounts.payment_mint_token_program),
        Some(&ctx.accounts.payment_mint_redeemer_ata),
        Some(&ctx.accounts.payment_mint_user_ata),
        request_id,
        new_m_token_rate.into(),
        false,
        safe_validate_liquidity,
    )? {
        ctx.accounts.close()?;
    }

    Ok(())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants