Incident,
The contract owner could disable the transfer function, which restricted users in selling their tokens.
Source: De.Fi incident database.
- Audits before it
- 0.
- Audits since
- 2, the latest dated 27 Feb 2025.
As of 15 Oct 2026, Pluto has 2 audit reports by 2 security firms on Trustblock; the latest is by Cyberscope, dated 27 Feb 2025. Those reports list no open critical findings. It also holds 1 deployed contract on 1 chain and 1 incident (latest 1 Jan 2021).
Record last updated . It holds audits and findings, contracts and incidents up to Oct 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Pluto | Security firm: Cyberscope | Date: | Scope: 1 address on BNB Chain | No open critical findings | Open · cyberscope.io |
| Pluto | Security firm: QuillAudits | Date: | Scope: Files named in the report | No open critical findings | Open · quillaudits.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 2 | 0 | 6 |
| Medium | 0 | 0 | 0 |
| Low | 1 | 0 | 5 |
The function handle in earn_vault_set_index & leverage_vault_set_index calculates the thirty_minute_apr based on the hourly_apr. This value is derived from higher APR values (e.g., hourly APR or daily APR) and is used in subsequent computations for updating vault indices. However, in both cases, the formula used to compute the thirty_minute_apr is flawed. The error affects downstream computations such as gain, borrow_gain resulting in incorrect indices.let thirty_minute_apr = decimals::div_ceil( INDEX_DECIMALS, hourly_apr, INDEX_DECIMALS, 3, 0)?;
Open the reportThe functions div_floor, div_ceil, mul_floor, and mul_ceil are designed to perform fractional arithmetic while applying either flooring or ceiling logic. However, upon closer inspection, the current implementation relies entirely on Rust's default behavior for division and multiplication without explicitly enforcing flooring or ceiling logic.No Explicit Logic for Floor or Ceil: The functions div_floor and div_ceil use the same logic and rely on Fraction::checked_div, which inherently performs truncation (flooring) in Rust for integers. There is no additional logic to enforce ceiling behavior. Similarly, mul_floor and mul_ceil behave identically because there is no logic to enforce rounding up or down. Potential for Incorrect Results: In cases where explicit ceiling behavior is required (e.g., rounding up fractional results), the current implementation will fail to deliver the expected results as the entire protocol is heaviliy dependednt on it.
Open the reportThe update_rate function in the Rate struct is indirectly called through the set_index methods in both earn_vault_set_index and leverage_vault_set_index. However, due to the bug in update_rate where time_diff always evaluates to 0, the EMA calculations for both APY and borrowing APY will fail to update, rendering the functionality ineffective.This can have the following implications: 1. Stale Rate Metrics: Both the hourly and daily EMA values remain uninitialized or outdated, misrepresenting the APY and borrowing APY trends. 2. Protocol Inaccuracy: Any logic depending on these rates, such as user-facing metrics or borrowing/lending terms, could behave incorrectly or mislead users.
Open the reportThe protocol's liquidation mechanism involves several sequential instructions, such as LeverageVaultKeeperRepayBorrow, LeverageVaultKeeperPayLiquidationFee, and LeverageVaultKeeperClosing. These instructions handle key operations such as repaying borrow amounts, paying liquidation fees, and closing positions. If the correct sequence of instructions is not enforced, liquidation fees can be bypassed
Open the reportThe update_rate function is invoked by calling the functions earn_vault_set_index & leverage_vault_set_index and has the following code respectively.// earn_vault_set_index() pub fn set_index(&mut self, last_index_updated: i64, index: u128, apy: u32) -> Result<()> { require!(index > 0, Errors::InvalidAmountZero); self.index = index; self.last_index_updated = last_index_updated; self.apy.update_rate(apy, self.last_index_updated)?; Ok(()) } Here, the update_rate function updates the APY rate and calculates the exponential moving averages (EMAs) over time intervals like hourly, daily, and beyond, based on the last_index_updated timestamp. // leverage_vault_set_index() pub fn set_index(&mut self, last_index_updated: i64, index: u128, apy: u32, borrowing_index: u128, borrowing_apy: u32) -> Result<()> { require!(index > 0, Errors::InvalidAmountZero); require!(borrowing_index > 0, Errors::InvalidAmountZero); self.last_index_updated = last_index_updated; self.index = index; self.borrowing_index = borrowing_index; self.apy.update_rate(apy, self.last_index_updated)?; self.borrowing_apy.update_rate(borrowing_apy, self.last_index_updated)?; self.update_time()?; Ok(()) }
Open the reportThe function handle in earn_vault_set_index operates on multiple accounts, including the leverage_vault. The leverage_vault account is passed into the function, and data is loaded from it to compute important metrics such as leverage_apy and other vault-related calculations The leverage_vault account lacks proper validation, which means any arbitrary vault can be passed as the leverage_vault parameter. If a malicious or incorrect vault is passed, the function will load and operate on unintended or invalid data, leading to incorrect calculations, protocol inconsistencies.
Open the reportThe function earn_vault_withdraw emits two events, EventEarnWithdraw and EventEarnWithdrawn, which contain overlapping information. This redundancy increases transaction size and storage costs on Solana.
Open the reportThe functions leverage_vault_create, leverage_vault_change_price_oracle, and earn_vault_change_price_oracle contain misleading parameter names, causing confusion:1. leverage_vault_create: The parameters token_collateral_decimal and native_collateral_decimal in handler_vault_leverage_create::handle imply they are decimals but actually represent price feed data for token and native collateral. 2. leverage_vault_change_price_oracle: The parameters token_collateral_decimal and native_collateral_decimal in handler_vault_leverage_change_price_oracle::handle also suggest decimals but are price feed data.earn_vault_change_price_oracle: The parameter token_decimal in handler_vault_earn_change_price_oracle::handle implies a decimal value but is actually price feed data for a token.
Open the reportThe earn_config_set function does not validate critical fee parameters (protocol_fee, deposit_fee, withdraw_fee, and borrow_fee). Without these validations, it is possible to set unreasonable values (e.g., extremely high or negative fees), which could disrupt the protocol and lead to misconfigurations.
Open the reportThe update_rate function in the provided code has a high level of redundant operations and repetitive calculations that can be optimized to save storage and compute resources when deployed on Solana
Open the reportThe function unwrap_sol contains an unnecessary check for the user's SOL lamport balance:require_gte!(user.lamports(), amount, Errors::InsufficientFunds); This check is irrelevant as the function only deals with WSOL tokens and their associated accounts, not the user's lamport balance.
Open the reportAttached through a shared contract address. Our incident data ends in Oct 2026.
The contract owner could disable the transfer function, which restricted users in selling their tokens.
Source: De.Fi incident database.
| Address | Chain | Source code |
|---|---|---|
| 0x409c…996c0x409cf201e81fc1e8538eb329e20a8513fcee996c | Chain: BNB Chain | Source code: Verified source |
Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.
Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="pluto"></div></body>
Paste the code where the label should appear. It uses no API credit and updates by itself.
Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us