diff --git a/packages/contracts/blend-adapter/src/lib.rs b/packages/contracts/blend-adapter/src/lib.rs index 0702b4f9..1b20724e 100644 --- a/packages/contracts/blend-adapter/src/lib.rs +++ b/packages/contracts/blend-adapter/src/lib.rs @@ -42,7 +42,7 @@ fn b_tokens_to_usdc(b_tokens: i128, b_rate: i128) -> Result .checked_mul(b_rate) .ok_or(ContractError::Overflow)? .checked_div(RATE_SCALAR) - .ok_or(ContractError::Overflow) + .ok_or(ContractError::DivisionByZero) } // --------------------------------------------------------------------------- @@ -133,6 +133,11 @@ pub enum ContractError { AlreadyInitialized = 1, /// An intermediate arithmetic operation would overflow `i128`. Overflow = 2, + /// A `checked_div` returned `None` because the divisor was zero. + /// Distinct from `Overflow`: this points to a degenerate adapter state + /// (e.g. a zero `b_rate` from a broken Blend pool) rather than a genuine + /// arithmetic overflow. + DivisionByZero = 3, /// A state-mutating call was made before `initialize`. NotInitialized = 3, } diff --git a/packages/contracts/vault/src/lib.rs b/packages/contracts/vault/src/lib.rs index 2da40543..64cd5ce4 100644 --- a/packages/contracts/vault/src/lib.rs +++ b/packages/contracts/vault/src/lib.rs @@ -125,6 +125,10 @@ pub enum ContractError { NoAdapterPosition = 13, /// `migrate_adapter` was called with `max_slippage_bps > 10_000`. InvalidSlippageBps = 14, + /// A `checked_div` returned `None` because the divisor was zero. + /// Distinct from `Overflow`: this points to a degenerate adapter state + /// (e.g. zero `total_assets`) rather than a genuine arithmetic overflow. + DivisionByZero = 19, /// `withdraw` was called with a `min_usdc_out` floor and the actual /// amount out fell below it. Distinct from `WithdrawalTooSmall` (which /// fires when `usdc_out` rounds to zero): this fires when `usdc_out > 0` @@ -208,7 +212,7 @@ impl MeridianVault { // Minting here would dilute every existing holder. if total_shares > 0 && total_assets <= 0 { return Err(ContractError::AdapterReportedNoAssets); - } + }https://github.com/drydocs/meridian/pull/671/conflict?name=packages%252Fcontracts%252Fvault%252Fsrc%252Flib.rs&ancestor_oid=5da2079f71a9c080d32edf55b78fafd79dbb877a&base_oid=9567e868a38dfec5c837a18cf35b890d6e172a59&head_oid=2da4054355f35c399d2f7f50c6c72e54bdc494b6 // shares_to_mint = amount * (total_shares + OFFSET) / (total_assets + OFFSET) // The virtual offset makes the first-deposit price 1 share = 1 stroop while @@ -220,6 +224,8 @@ impl MeridianVault { .ok_or(ContractError::Overflow)?, ) .ok_or(ContractError::Overflow)? + .checked_div(total_assets + OFFSET) + .ok_or(ContractError::DivisionByZero)?; .checked_div( total_assets .checked_add(OFFSET) @@ -346,7 +352,7 @@ impl MeridianVault { .checked_mul(total_adapter_shares) .ok_or(ContractError::Overflow)? .checked_div(total_shares) - .ok_or(ContractError::Overflow)?; + .ok_or(ContractError::DivisionByZero)?; // Adapter redeems protocol shares, delivers USDC to vault, returns amount. let usdc_out = AdapterClient::new(&env, &adapter_addr) @@ -384,7 +390,7 @@ impl MeridianVault { .checked_mul(shares) .ok_or(ContractError::Overflow)? .checked_div(caller_shares) - .ok_or(ContractError::Overflow)?; + .ok_or(ContractError::DivisionByZero)?; env.storage() .persistent() .set(&principal_key, &(principal - principal_out)); @@ -676,7 +682,7 @@ impl MeridianVault { .checked_mul(10_000i128 - max_slippage_bps as i128) .ok_or(ContractError::Overflow)? .checked_div(10_000i128) - .ok_or(ContractError::Overflow)?; + .ok_or(ContractError::DivisionByZero)?; if value_after < min_acceptable { return Err(ContractError::MigrationValueDrift); }