Halborn Logo

Mars Protocol Fields of Mars - Mars Protocol


Prepared by:

Halborn Logo

HALBORN

Last Updated 04/26/2024

Date of Engagement by: January 17th, 2022 - January 28th, 2022

Summary

100% of all REPORTED Findings have been addressed

All findings

2

Critical

0

High

0

Medium

1

Low

1

Informational

0


1. AUDIT SUMMARY

Mars Protocol engaged Halborn to conduct a security assessment on CosmWasm smart contracts beginning on January 17th, 2022 and ending January 28th, 2022.

The security engineers involved on the audit are blockchain and smart-contract security experts with advanced penetration testing, smart-contract hacking, and deep knowledge of multiple blockchain protocols.

The purpose of this audit is to achieve the following:

    • Ensure that smart contract functions work as intended.

    • Identify potential security issues with the smart contracts.

In summary, Halborn identified some improvements to reduce the likelihood and impact of risks, which were mostly addressed by Mars team. The main ones are the following:

    • Enforce the use of a valid routine in update_config

    • Enforce check of arithmetic operations

External threats, such as financial related attacks, oracle attacks, and inter-contract functions and calls should be validated for expected logic and state.

2. TEST APPROACH & METHODOLOGY

Halborn performed a combination of manual review of the code and automated security testing to balance efficiency, timeliness, practicality, and accuracy regarding the scope of the smart contract audit. While manual testing is recommended to uncover flaws in logic, process, and implementation; automated testing techniques help enhance coverage of smart contracts and can quickly identify items that do not follow security best practices. The following phases and associated tools were used throughout the term of the audit:

    • Research into architecture, purpose, and use of the platform.

    • Manual code read and walkthrough.

    • Manual assessment of use and safety for the critical Rust variables and functions in scope to identify any contracts logic related vulnerability.

    • Fuzz testing (Halborn custom fuzzing tool)

    • Checking the test coverage (cargo tarpaulin)

    • Scanning of Rust files for vulnerabilities (cargo audit) \newline

3. SCOPE

\begin{enumerate} \item CosmWasm Smart Contracts \begin{enumerate} \item Repository: \href{https://github.com/mars-protocol/fields-of-mars}{fields-of-mars} \item Commit ID: \href{https://github.com/mars-protocol/fields-of-mars/tree/dc2245ada036d7cfef94a82dd121474d1dd033f2 }{dc2245ada036d7cfef94a82dd121474d1dd033f2} \item Contracts in scope: \begin{enumerate} \item martian-field \end{enumerate} \end{enumerate} \end{enumerate}

Out-of-scope: External libraries and financial related attacks

4. RISK METHODOLOGY

Vulnerabilities or issues observed by Halborn are ranked based on the risk assessment methodology by measuring the LIKELIHOOD of a security incident and the IMPACT should an incident occur. This framework works for communicating the characteristics and impacts of technology vulnerabilities. The quantitative model ensures repeatable and accurate measurement while enabling users to see the underlying vulnerability characteristics that were used to generate the Risk scores. For every vulnerability, a risk level will be calculated on a scale of 5 to 1 with 5 being the highest likelihood or impact.
RISK SCALE - LIKELIHOOD
  • 5 - Almost certain an incident will occur.
  • 4 - High probability of an incident occurring.
  • 3 - Potential of a security incident in the long term.
  • 2 - Low probability of an incident occurring.
  • 1 - Very unlikely issue will cause an incident.
RISK SCALE - IMPACT
  • 5 - May cause devastating and unrecoverable impact or loss.
  • 4 - May cause a significant level of impact or loss.
  • 3 - May cause a partial impact or loss to many.
  • 2 - May cause temporary impact or loss.
  • 1 - May cause minimal or un-noticeable impact.
The risk level is then calculated using a sum of these two values, creating a value of 10 to 1 with 10 being the highest level of security risk.
Critical
High
Medium
Low
Informational
  • 10 - CRITICAL
  • 9 - 8 - HIGH
  • 7 - 6 - MEDIUM
  • 5 - 4 - LOW
  • 3 - 1 - VERY LOW AND INFORMATIONAL

5. SCOPE

Out-of-Scope: New features/implementations after the remediation commit IDs.

6. Assessment Summary & Findings Overview

Critical

0

High

0

Medium

1

Low

1

Informational

0

Impact x Likelihood

HAL-01

HAL-02

Security analysisRisk levelRemediation Date
CONFIG PARAMETERS VALUE CAN BE CHANGED UNRESTRICTEDLYMediumSolved - 02/09/2022
SOME RATES COULD BE SET TO VALUES GREATER THAN 1LowSolved - 02/09/2022

7. Findings & Tech Details

7.1 CONFIG PARAMETERS VALUE CAN BE CHANGED UNRESTRICTEDLY

// Medium

Description

instantiate and update_config functions in contracts/martian-field/src/execute.rs allow contract's owner to update max_ltv, bonus_rate and fee_rate fields with a potential unfair amount. This situation can produce the following consequences:

  • A malicious (or compromised) owner can change temporarily max_ltvto very low rate e.g., : 0.01 and bonus_rate to e.g., : 0 and liquidate all positions, draining users assets.
  • Owner could mistakenly change max_ltv rate to lower than released one, which could become current positions into “unhealthy” ones and ready to be liquidated.
  • If fee_rate is equal to 1, harvest operations will cause unfair reward distributions and owner could drain user assets. Furthermore, if fee_rate is higher than 1 it will cause an overflow.

It is worth noting that likelihood for this to happen is low because martian-field contract is intended to be owned by governance (Council) indefinitely, who is the responsible one for this operation.

Code Location

contracts/martian-field/src/execute.rs

    pub fn update_config(deps: DepsMut, info: MessageInfo, new_config: Config) -> StdResult<Response> {
        let config = CONFIG.load(deps.storage)?;

        if info.sender != config.governance {
            return Err(StdError::generic_err("only governance can update config"));
        }

        CONFIG.save(deps.storage, &new_config)?;

        Ok(Response::default())
    }

contracts/martian-field/src/execute.rs

    pub fn liquidate(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    user_addr: Addr,
) -> StdResult<Response> {
    let config = CONFIG.load(deps.storage)?;
    let state = STATE.load(deps.storage)?;
    let position = POSITION.load(deps.storage, &user_addr).unwrap_or_default();

    // position must be active (LTV is not `None`) and the LTV must be greater than `max_ltv`
    let health = compute_health(&deps.querier, &env, &config, &state, &position)?;

    // if `health.ltv` is `Some`, it must be greater than `max_ltv`
    // if `health.ltv` is `None`, indicating the position is already closed, then it is not liquidatable
    let ltv = health.ltv.ok_or_else(|| StdError::generic_err("position is already closed"))?;
    if ltv <= config.max_ltv {
        return Err(StdError::generic_err("position is healthy"));
    }

    // 1. unbond the user's liquidity tokens from Astro generator
    // 2. burn liquidity tokens, withdraw primary + secondary assets from the pool
    // 3. swap all primary assets to secondary assets
    // 4. repay all debts
    // 5. among all remaining assets, send the amount corresponding to `bonus_rate` to the liquidator
    // 6. refund all assets that're left to the user
    //
    // NOTE: in the previous versions, we sell **all** primary assets, which is not optimal because 
    // this will incur bigger slippage, causing worse liquidation cascade, and be potentially lucrative 
    // for sandwich attackers
    //
    // now, we calculate how much additional secondary asset is needed to fully pay off debt, and 
    // reverse-simulate how much primary asset needs to be sold
    //
    // TODO: add slippage checks to the swap step so that liquidation cannot be sandwich attacked
    let callbacks = [
        CallbackMsg::Unbond {
            user_addr: user_addr.clone(),
            bond_units_to_reduce: position.bond_units,
        },
        CallbackMsg::WithdrawLiquidity {
            user_addr: user_addr.clone(),
        },
        CallbackMsg::Cover {
            user_addr: user_addr.clone(),
        },
        CallbackMsg::Repay {
            user_addr: user_addr.clone(),
            repay_amount: health.debt_value,
        },
        CallbackMsg::Refund {
            user_addr: user_addr.clone(),
            recipient_addr: info.sender.clone(),
            percentage: config.bonus_rate,
        },
        CallbackMsg::Refund {
            user_addr: user_addr.clone(),
            recipient_addr: user_addr.clone(),
            percentage: Decimal::one(),
        },
    ];

Score
Impact: 5
Likelihood: 1
Recommendation

SOLVED: The issue was fixed in commit 0f9c959931fcde3ddf5cdb1907c9177f69284e31.

7.2 SOME RATES COULD BE SET TO VALUES GREATER THAN 1

// Low

Description

The instantiate and update_config functions in contracts/martian-field/src/execute.rs do not restrict that rates fields are lesser than 1.

If they are not correctly set, some operations will always panic and won't allow legitimate users to harvest or liquidate; thus generating a denial of service (DoS). The affected fields are the following:

  • max_ltv
  • fee_rate
  • bonus_rate

Code Location

contracts/martian-field/src/execute.rs

    pub fn update_config(deps: DepsMut, info: MessageInfo, new_config: Config) -> StdResult<Response> {
        let config = CONFIG.load(deps.storage)?;

        if info.sender != config.governance {
            return Err(StdError::generic_err("only governance can update config"));
        }

        CONFIG.save(deps.storage, &new_config)?;

        Ok(Response::default())
    }
Score
Impact: 3
Likelihood: 1
Recommendation

SOLVED: The issue was fixed in the following commits:

Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.

© Halborn 2024. All rights reserved.