Canonical page: <https://www.guvenkaya.co/reports/jump-backend>

[Work & reports](https://www.guvenkaya.co/work) Report

# Jump DeFi Backend & Frontend Security Assessment

[View PDF on GitHub](https://github.com/Guvenkaya/public-reports/blob/master/Jump-Defi-Backend-And-Frontend-Security-Assessment.pdf)

![Jump DeFi logo](https://www.guvenkaya.co/v2/clients/jump.svg)

- All findings

  13

- Critical

  8

- High

  1

- Medium

  3

- Low

  1

- Informational

  0

Date of engagement: 10th December 2024 - 6th January 2025

![Timur Güvenkaya](https://www.guvenkaya.co/v2/portraits/timur-guvenkaya.png)

Security review by

## Timur Guvenkaya

[Meet the team](https://www.guvenkaya.co/about#team)

## About Us

Guvenkaya is a security research firm specializing in Rust security, Web3 security of Rust-based protocols, and Web2 security. With our expertise, we provide both security auditing services and custom security solutions

## About Jump Defi

Jump Defi is the only one-stop decentralized finance platform on NEAR Protocol. Jump DeFi lowers the barrier of entry to decentralized finance for users and developers.

## Audit Results

Guvenkaya conducted a security assessment of the Jump Defi backend and Jump Defi frontend from 10th December 2024 to 6th January 2025. During this engagement, a total of 13 findings were reported. 8 of the findings were critical, 1 high, 3 medium, and 1 low severity. All major issues were fixed by the Jump Defi team.

## Project Scope

| Files                                                 | Link                                                                                                          |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| Indexer Helper (Excluding Backend Deployment Scripts) | <https://github.com/BlockApex/jump-DeFi-backend/tree/e188e0a2d9ba419d9ace6eeaf3f9a5c8bc2f15ed/indexer-helper> |
| Cache                                                 | <https://github.com/BlockApex/jump-DeFi-backend/tree/e188e0a2d9ba419d9ace6eeaf3f9a5c8bc2f15ed/cache>          |
| Aggregator                                            | <https://github.com/BlockApex/jump-DeFi-backend/tree/e188e0a2d9ba419d9ace6eeaf3f9a5c8bc2f15ed/aggregator>     |
| AMM Indexer                                           | <https://github.com/BlockApex/jump-DeFi-backend/tree/e188e0a2d9ba419d9ace6eeaf3f9a5c8bc2f15ed/amm-indexer>    |
| Indexer                                               | <https://github.com/BlockApex/jump-DeFi-backend/tree/e188e0a2d9ba419d9ace6eeaf3f9a5c8bc2f15ed/indexer>        |
| NEAR Service Web Package                              | <https://github.com/BlockApex/jump-DeFi-backend/tree/e188e0a2d9ba419d9ace6eeaf3f9a5c8bc2f15ed/near_service>   |
| (Excluding tests and assets)                          | <https://github.com/BlockApex/jump-web-dev/tree/0b6679ed376b430c5ae324e1e53c8e17bc6e0776/packages/web>        |

## Out of Scope

The audit will include reviewing the code for security vulnerabilities. The audit does not include a review of the tests and dependencies.

## Timeline

1. Start of the audit

   10th December 2024

2. Draft report

   6th January 2025

3. Final report

   18th January 2025

## Methodology

- RESEARCH INTO PROJECT ARCHITECTURE
- PREPARING ATTACK VECTORS
- SETTING UP AN ENVIRONMENT
- MANUAL CODE REVIEW OF THE CODE
- ASSESSMENT OF RUST SECURITY ISSUES
- ASSESSMENT OF NEAR SECURITY ISSUES
- ASSESSMENT OF ARITHMETIC ISSUES
- BUSINESS LOGIC VULNERABILITY ASSESSMENT
- ONCHAIN TESTING USING NEAR WORKSPACES
- BEST PRACTICES AND CODE QUALITY
- CHECKING FOR CODE REFACTORING/SIMPLIFICATION POSSIBILITIES
- ARCHITECTURE IMPROVEMENT SUGGESTIONS
- PREPARING POCS AND/OR TESTS FOR EACH CRITICAL/HIGH/MEDIUM ISSUES

## Severity Breakdown

### Likelihood Ratings

- Likely

  The vulnerability is easily discoverable and not overly complex to exploit.

- Possible

  The vulnerability presents some challenges either in discovery or in the complexity of the attack.

- Rare

  The vulnerability is either very difficult to discover or complex to exploit, or both. This matrix provides a nuanced view, taking into account both the ease of discovering a vulnerability and the complexity involved in exploiting it.

### Impact

- Severe

  The vulnerability is easily discoverable and not overly complex to exploit.

- Moderate

  The vulnerability presents some challenges either in discovery or in the complexity of the attack.

- Negligible

  The vulnerability is either very difficult to discover or complex to exploit, or both.

### Severity Ratings

- Critical

  Assigned to vulnerabilities with severe impact and a likely likelihood of exploitation.

- High

  For vulnerabilities with either severe impact but only a possible likelihood, or moderate impact with a likely likelihood.

- Medium

  Used for vulnerabilities with severe impact but a rare likelihood, moderate impact with a possible likelihood, or negligible impact with a likely likelihood.

- Low

  For vulnerabilities with moderate impact and rare likelihood, or negligible impact with a possible likelihood.

- Informational

  The lowest severity rating, typically for vulnerabilities with negligible impact and a rare likelihood of exploitation.

### Likelihood Matrix

| Attack Complexity / Discovery Ease | Obvious  | Concealed | Hidden   |
| ---------------------------------- | -------- | --------- | -------- |
| Complex                            | Possible | Rare      | Rare     |
| Moderate                           | Likely   | Possible  | Rare     |
| Straightforward                    | Likely   | Possible  | Possible |

### Likelihood/Impact Matrix

| Likelihood / Impact | Severe   | Moderate | Negligible    |
| ------------------- | -------- | -------- | ------------- |
| Likely              | Critical | High     | Medium        |
| Possible            | High     | Medium   | Low           |
| Rare                | Medium   | Low      | Informational |

## Findings Summary

### Remediation Complexity

This measures how difficult it is to fix the vulnerability once it has been identified.

- Simple

  Patches or fixes are readily available and easily implemented.

- Moderate

  Requires some time and resources to remediate, but well within the capabilities of most organizations.

- Difficult

  Remediation requires significant resources, specialized skills, or substantial changes to systems or architecture.

### Status

This measures how difficult it is to fix the vulnerability once it has been identified.

- Not Fixed

  Indicates that the vulnerability has been identified but no remedial action has been taken yet. This status is crucial for newly discovered vulnerabilities or those awaiting prioritization.

- Fixed

  This status is applied when the vulnerability has been successfully remediated. It implies that appropriate measures (like patching, configuration changes, or architectural modifications) have been implemented to resolve the issue.

- Acknowledged

  This status is used for vulnerabilities that have been recognized, but for various reasons (such as risk acceptance, cost, or other business decisions), have not been fixed. It indicates that the risk posed by the vulnerability is known and has been consciously accepted.

| Finding                                                                        | Impact     | Likelihood | Severity | Remediation complexity | Remediation status |
| ------------------------------------------------------------------------------ | ---------- | ---------- | -------- | ---------------------- | ------------------ |
| [GUV-1: Indexer Crash Due to Invalid UTF-8 Character](#guv-1)                  | Severe     | Likely     | Critical | Simple                 | Fixed              |
| [GUV-2: Indexer Crash Due To Invalid Message Format](#guv-2)                   | Severe     | Likely     | Critical | Simple                 | Fixed              |
| [GUV-3: Aggregator Crash Due To Not Matching Pool](#guv-3)                     | Severe     | Likely     | Critical | Simple                 | Fixed              |
| [GUV-4: Indexer Crash Due to Invalid Argument Formats](#guv-4)                 | Severe     | Likely     | Critical | Simple                 | Fixed              |
| [GUV-5: Aggregator Crash Due To Integer Overflow](#guv-5)                      | Severe     | Likely     | Critical | Simple                 | Fixed              |
| [GUV-6: SQL Injection in User Wallet Addition](#guv-6)                         | Severe     | Likely     | Critical | Simple                 | Fixed              |
| [GUV-7: SQL Injection In Liquidation Result Adding](#guv-7)                    | Severe     | Likely     | Critical | Simple                 | Fixed              |
| [GUV-8: Indexer Denial Of Service Due To Exceesive Number Of Messages](#guv-8) | Moderate   | Likely     | Critical | Simple                 | Fixed              |
| [GUV-9: Artificial Data Can Be Added Through AMM-Indexer](#guv-9)              | Moderate   | Likely     | High     | Simple                 | Fixed              |
| [GUV-10: Any Pool Can Be Marked As Blacklisted On Aggregator](#guv-10)         | Negligible | Likely     | Medium   | Simple                 | Fixed              |
| [GUV-11: Missing Tests Across The System](#guv-11)                             | Moderate   | Possible   | Medium   | Moderate               | Acknowledged       |
| [GUV-12: Error-Prone Parsing of Liquidity Pools](#guv-12)                      | Severe     | Rare       | Medium   | Moderate               | Fixed              |
| [GUV-13: Usage of Panic Macro in Production Code](#guv-13)                     | Moderate   | Rare       | Low      | Simple                 | Fixed              |

## Findings Details

### GUV-1: Indexer Crash Due to Invalid UTF-8 Character

Critical

The Indexer uses String::from\_utf8 to convert base64-decoded argument bytes to strings. However, it lacks proper error handlingand instead uses unwrap(), which causes a panic on None and Error results. The indexer also fails to verify whether transactions sent to valid addresses are successful.

indexer:handle\_message:indexer/src/chains/near/stream.rs

```
     let keywords = [
             self.config.ref_finance_contract_id.clone(),
             self.config.veax_contract_id.clone(),
             self.config.jump_contract_id.clone(),
          ];
          let contains_keyword = keywords.contains(&receiver_id);
          if contains_keyword {
             let r = receipt.receipt;
             if let ReceiptEnumView::Action { actions, .. } = &r {
                 for action in actions {
                   if let ActionView::FunctionCall { method_name, args, .. } = action {
                       let args_base64: String =
     serde_json::from_value(serde_json::to_value(args).unwrap()).unwrap();
                       let decoded_args = STANDARD.decode(args_base64).unwrap();
                    let decoded_str = String::from_utf8(decoded_args).unwrap();
                       let mut decoded_json: Value = serde_json::from_str(&decoded_str).unwrap();}
```

The root causes:

The indexer does not verify transaction success The indexer uses unwrap() instead of proper error handling, causing panic on None/Error results

This vulnerability enables:

A malicious actor to crash the indexer with a single transaction

POC

Compile the indexer in release mode and launch it Send a transaction to any valid contract address with an argument containing a non-UTF8 character. The transaction does not need to execute successfully Example: near contract call-function as-transaction ref-finance-101.testnet ft\_transfer\_call json- args "{"msg": "жжж"} prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as attacker.testnet network-config testnet sign-with-keychain send

#### Recommendation

Verify that transactions are successful Implement proper error handling for all Option/Result values

#### Remediation - Fixed

The Jump Defi team has fixed the issue by verifying the success of the receipt and replaced unwrap() with proper error handling

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=12)

### GUV-2: Indexer Crash Due To Invalid Message Format

Critical

The Indexer attempts to parse the msg argument from JSON into an array for ft\_on\_transfer transactions sent to the VEAXaddress. The issue arises from using unwrap() after .as\_array() without proper error handling. The indexer also fails to verify transaction success.

indexer:handle\_message:indexer/src/chains/near/stream.rs

```
     if !self.config.exclude_veax && receiver_id == self.config.veax_contract_id
          && method_name == "ft_on_transfer"
           && !decoded_json["msg"].as_str().unwrap_or("").is_empty() {
              // msg contain stringify value, need to convert it to JSON
              let msg_json = serde_json::from_str(
                 decoded_json["msg"].as_str().unwrap()
              ).unwrap();
              decoded_json["msgs"] = msg_json;
```

for msg in decoded\_json\["msgs"].as\_array().unwrap() { if let Some(obj) = msg.as\_object() { if obj.contains\_key("OpenPosition") { tracing::info!("stream::handle\_message() Handling Veax OpenPosition Action");

The root causes:

The indexer does not verify transaction success The indexer uses unwrap() instead of proper error handling, causing panic on None/Error results

This vulnerability enables:

A malicious actor to crash the indexer with a single transaction

POC

Compile the indexer in release mode and launch it Send a transaction to VEAX contract address with the msg argument containing a non-array value. The transaction does not need to execute successfully Example: near contract call-function as-transaction veax-dex15.testnett ft\_on\_transfer json- args{"msg":"hak"} prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as attacker.testnet network-config testnet sign-with-keychain send

#### Recommendation

Verify that transactions are successful Implement proper error handling for all Option/Result values

#### Remediation - Fixed

The Jump Defi team has fixed the issue by verifying the success of the receipt and replaced unwrap() with proper error handling

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=14)

### GUV-3: Aggregator Crash Due To Not Matching Pool

Critical

The aggregator computes routes that are sent to the smart router contract. A mock router creation route ("/route/mock") is exposed in production without access control. Its create\_route function attempts to fetch decimals for token\_in and token\_out by iterating over pools, but it uses .expect() instead of proper error handling.

aggregator:create\_mock\_route:aggregator/src/services/route\_mock.rs

```
     if let Some(pools) = mock_pools.clone() {
             token_in_decimals = pools
               .iter()
               .find_map(|pool| {
                  if pool.token_in == token_in {
                     Some(pool.token_in_decimals)
                  } else if pool.token_out == token_in {
                     Some(pool.token_out_decimals)
                  } else {
                     None
                  }
               })
              .expect("No matching pool found for token_in");
```

```
            token_out_decimals = pools
              .iter()
              .find_map(|pool| {
                 if pool.token_in == token_out {
                    Some(pool.token_in_decimals)
                 } else if pool.token_out == token_out {
                    Some(pool.token_out_decimals)
                 } else {
                    None
                 }
              })
             .expect("No matching pool found for token_out");
```

The root causes:

The aggregator has exposed test route in production The aggregator uses .expect() instead of proper error handling, causing panics on None/Error results

This vulnerability enables:

A malicious actor to crash the aggregator with a single request

POC

Compile the aggregator in release mode and launch it Send the request to the /route/mock with token\_in and/or token\_out which do not match any of the pools:

Example request

```
     curl -X POST 'http://127.0.0.1:8000/route/mock' -H 'Content-Type: application/json'      -d
     '{
               "token_in": "token121.near",
               "token_out": "token212.near",
               "amount": 1000.0, "slippage": "0.5",
               "providers": null, "pools": [{
                  "kind": "STABLE_SWAP", "liquidity_provider": "RefFinance",
                  "amp": 100, "key": "pool_key_1",
                  "pool_id": 1, "token_in": "token1.near",
                  "token_out": "token2.near", "reserves_in": "1000000",
                  "reserves_out": "1000000", "fees": null,
                  "fee_divisor": null, "liquidities": ["1000000", "1000000"],
                  "prices": null, "spot_prices": null,
                  "symbols": ["TOKEN1", "TOKEN2"], "token_in_decimals": 18,
                  "token_out_decimals": 18, "amounts": ["1000000", "1000000"],
                  "token_account_ids": ["token1.near", "token2.near"],
                  "decimals": [18, 18], "swap_path": {
                     "token_in": "token1.near", "token_out": "token2.near",
                     "amount_in": "1000", "amount_out": "995",
                     "internal_swap": null, "actual_order_book": null,
                     "calculated_order_book": null, "order_type": null,
                     "order_quantity": null,"slippage_tolerance_bp": null
                  }
               }]
            }'
```

#### Recommendation

Remove the mock route from production code by utilizing test config Implement proper error handling for all Option/Result values

#### Remediation - Fixed

The Jump Defi team has fixed the issue by removing the mock route.

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=16)

### GUV-4: Indexer Crash Due to Invalid Argument Formats

Critical

For each supported method, the Indexer attempts to parse arguments from JSON into their respective types. The issue stems from using unwrap() without proper error handling. Additionally, the indexer fails to verify transaction success.

indexer:handle\_message:indexer/src/chains/near/stream.rs

if \["ft\_transfer\_call"].contains(\&method\_name.as\_str()) {

```
            if !decoded_json["msg"].as_str().unwrap_or("").is_empty() {
                let msg_json = serde_json::from_str(
                   decoded_json["msg"].as_str().unwrap()
                ).unwrap();
```

decoded\_json\["msg"] = msg\_json;

```
              let ft_transfer_call: FtTransferCall =
     from_value(decoded_json.clone()).unwrap();
               actions = ft_transfer_call.msg.actions;
            }
        }
        ...
        if method_name == "add_liquidity" {
```

```
         let add_liquidity: AddLiquidity =
             from_value(decoded_json.clone()).unwrap();...}
          ...
          if method_name == "remove_liquidity" {
```

```
         let remove_liquidity: RemoveLiquidity =
           from_value(decoded_json.clone()).unwrap();...}
```

indexer:handle\_message:indexer/src/chains/near/stream.rs

if method\_name == "add\_stable\_liquidity" { tracing::info!( "stream::handle\_message() Handling {} method", method\_name );

```
                let add_stable_liquidity: AddStableLiquidity =
                 from_value(decoded_json.clone()).unwrap();
          ...
          for msg in decoded_json["msgs"].as_array().unwrap() {
              if let Some(obj) = msg.as_object() {
                  if obj.contains_key("OpenPosition") {
                     tracing::info!(
                        "stream::handle_message() Handling Veax OpenPosition Action"
                     );
                    let open_position: OpenPosition =
                      from_value(msg["OpenPosition"].clone()).unwrap();
```

The affected methods include:

⇒ ft\_transfer\_call FtTransferCall type ⇒ add\_liquidity AddLiquidity remove\_liquidity ⇒ RemoveLiquidity add\_stable\_liquidity ⇒ AddStableLiquidity ft\_on\_transfer (VEAX) ⇒ OpenPosition

The root causes:

The indexer does not verify transaction success The indexer uses unwrap() instead of proper error handling

POC

Compile the indexer in release mode and launch it Send a transaction to any valid contract address with supported method and an argument which does not match the type expected by the method Example: near contract call-function as-transaction ref-finance-101.testnet remove\_liquidity json- args '"something":33' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as attacker.testnet network-config testnet sign-with-keychain send

#### Recommendation

Verify that transactions are successful Implement proper error handling for all Option/Result values

#### Remediation - Fixed

The Jump Defi team has fixed the issue by verifying the success of the receipt and replaced unwrap() with proper error handling

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=19)

### GUV-5: Aggregator Crash Due To Integer Overflow

Critical

The Aggregator allows users to calculate routes by accepting various arguments, including the amount parameter. The core issue lies in the use of unchecked mathematics operations throughout the codebase.

aggregator:get\_amounts\_distribution:aggregator/src/services/route.rs

```
     fn get_amounts_distribution(amount: u128, distribution_percentage: u128) -> (Vec<u128>,
     Vec<u128>) {
           tracing::info!("router::get_amounts_distribution() getting amounts distribution...");
```

```
              let mut amounts: Vec<u128> = Vec::new();
              let mut percents: Vec<u128> = Vec::new();
```

```
              let iterations = (100u128 / distribution_percentage) as usize;
```

```
              for i in 1..=iterations {
                let percent = distribution_percentage * i as u128;
               let amount = amount * percent / 100u128;
```

```
                  percents.push(percent);
                  amounts.push(amount);
              }
```

```
              (amounts, percents)
          }
```

The root cause:

The aggregator uses unchecked maths throughout the code

POC

Compile the aggregator in release mode and launch it Send the request to the /route with amount which equals to the u128::MAX

Example request

```
      curl -X POST http://127.0.0.1:8000/route -H "Content-Type: application/json" -d       '{
                "token_out": "usdt.tether-token.near",
                "token_in": "wrap.near",
                "amount": 340282366920938463463374607431768211455,
                "slippage": "0.5",
                "providers": ["Jump", "RefFinance"]
             }'
```

#### Recommendation

Utilize checked maths throughout the aggregator

#### Remediation - Fixed

The Jump Defi team has fixed the issue by utilizing the checked maths.

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=22)

### GUV-6: SQL Injection in User Wallet Addition

Critical

The indexer helper exposes an endpoint for adding user wallets to the database via /add-user- wallet. The endpoint lacks verification of provided arguments before constructing SQL queries. Both account\_id and wallet\_address parameters are directly concatenated into the query string.

indexer\_helper:add\_user\_wallet\_info:indexer-helper/db\_provider.py

query\_sql = "select id from t\_user\_wallet\_info where account\_id = '%s' and wallet\_address = '%s'" % (account\_id, wallet\_address) sql = "insert into t\_user\_wallet\_info(account\_id, wallet\_address, \`created\_time\`, \`updated\_time\`) " \ "values('%s','','b','c'%s', now(), now())" % (account\_id, wallet\_address) cursor = db\_conn.cursor() try: cursor.execute(query\_sql) row = cursor.fetchone()

if row is None: cursor.execute(sql) db\_conn.commit() except Exception as e: db\_conn.rollback() print("insert t\_user\_wallet\_info to db error:", e) raise e

The root causes:

Missing access control on /add-user-wallet endpoint Missing validation of user-provided arguments

This vulnerability enables a malicious actor to perform SQL injection attacks that can:

Read unauthorized data from the database Insert malicious data into the database Cause denial of service on the database Potentially execute arbitrary code remotely

POC

Launch indexer helper Send request to /add-wallet-connection with Sleep command

Example request

curl -X POST "http\://localhost:9000/add-user-wallet" -H "Content-Type: application/json" - d '{ "account\_id": "test\_account3333", "wallet\_address": "' UNION SELECT 1 AND SLEEP(20) -- " }'

#### Recommendation

Add access control to the add-user-wallet endpoint Provide named parameters in .execute to prevent SQL injection

#### Remediation - Fixed

The Jump Defi team has fixed the issue by removing the add-user-wallet endpoint.

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=24)

### GUV-7: SQL Injection In Liquidation Result Adding

Critical

The indexer helper exposes an endpoint for adding liquidation result to the database via /add- liquidation-result. The endpoint lacks verification of provided arguments before constructing SQL queries. Both key and values parameters are directly concatenated into the query string.

indexer\_helper:add\_liquidation\_result:indexer-helper/db\_provider.py

sql = "insert into liquidation\_result\_info(\`key\`, \`values\`, \`timestamp\`, \`created\_time\`, \`updated\_time\`) " \ "values('%s','%s',%s, now(), now())" % (key, values, now\_time) cursor = db\_conn.cursor(cursor=pymysql.cursors.DictCursor) try: cursor.execute(sql) db\_conn.commit()

The root causes:

Missing access control on /add-liquidation-result endpoint Missing validation of user-provided arguments

This vulnerability enables a malicious actor to perform SQL injection attacks that can:

Read unauthorized data from the database Insert malicious data into the database Cause denial of service on the database Potentially execute arbitrary code remotely

POC

Launch indexer helper Send request to /add-liquidation-result with Sleep command

Example request

curl -X POST "http\://localhost:9000/add-liquidation-result" -H "Content-Type: application/json" -d '{ "key": "pwned','pwned632622',(SELECT SLEEP(50)),'2023-01-01','2023-01-01')-- ", "values": "1" }'

#### Recommendation

Add access control to the add-liquidation-result endpoint Provide named parameters in .execute to prevent SQL injection

#### Remediation - Fixed

The Jump Defi team has fixed the issue by removing the add-liquidation-result endpoint.

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=26)

### GUV-8: Indexer Denial Of Service Due To Exceesive Number Of Messages

Critical

The Indexer iterates over a messages array to process individual messages. Since it verifies neither the number of messages nor the success of the receipt, an attacker can force the indexer to process a call containing an excessive number of messages. This prevents the indexer from processing any other blocks until it completes the current messages, resulting in a denial of service.

indexer:handle\_message:indexer/src/chains/near/stream.rs

for msg in decoded\_json\["msgs"].as\_array().unwrap() { if let Some(obj) = msg.as\_object() { if obj.contains\_key("OpenPosition") { tracing::info!("stream::handle\_message() Handling Veax OpenPosition Action");

The root cause:

The indexer does not verify transaction success

This vulnerability enables:

A malicious actor to cause denial of service of the indexer

POC

Compile the indexer in release mode and launch it Send a transaction to VEAX contract address with the msg argument containing a large number of entries

Example exploit code:

exploit

import json

```
            def generate_open_position(index):
              return {
                "OpenPosition": {
                  "fee_rate": 30,
                  "position": {
                     "amount_ranges": [{
                         "max": "1000000000",
                         "min": "100000000"
                     }],
                     "ticks_range": [100 + index, 200 + index]
                  },
                  "tokens": [f"token{index}a.testnet", f"token{index}b.testnet"]
                }
              }
```

\# Generate array with 100 messages messages = \[generate\_open\_position(i) for i in range(100)]

```
            # Create the full payload
            payload = {
              "sender_id": "malicious_acc.testnet",
              "amount": "1000000000",
              "msg": json.dumps(messages)
            }
```

exploit

\# Write the command to a file command = f"""near contract call-function as-transaction veax-dex15.testnet ft\_on\_transfer json-args '{json.dumps(payload)}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as malicious\_acc.testnet network-config testnet sign-with-keychain send"""

with open("run\_attack.sh", "w") as f: f.write(command)

print("Command written to run\_attack.sh")

\# Also print just the messages array for inspection print(" Messages array (first 2 for verification):") print(json.dumps(messages\[:2], indent=2))

#### Recommendation

Verify that transactions are successful

#### Remediation - Fixed

The Jump Defi team has fixed the issue by verifying the success of the receipt.

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=28)

### GUV-9: Artificial Data Can Be Added Through AMM-Indexer

High

The AMM indexer saves transaction data to the database based on the method called. Due to missing transaction validation, malicious users can insert artificial or incorrect data into the database.

Validation Issues per supported method:

⇒ ft\_transfer\_call | add\_liquidity | remove\_liquidity No validation of transaction success, allowing anyone to update pool data and add transactions to the database ⇒ swap No validation of transaction success, allowing anyone to add transactions to the database ⇒ add\_simple\_pool Has transaction success validation, but the receiver ID check can be bypassed

amm\_indexer:handle\_streamer\_message:amm-indexer/src/main.rs

```
     if receiver_id.contains("jump_amm.testnet") {
          let timestamp = streamer_message.block.header.timestamp_nanosec;
          let signer_id = receipt.predecessor_id.to_string();
          let receipt_id = receipt.receipt_id.to_string();
```

An attacker can:

Create an account such as jump\_amm.testnet.attackerjump.testnet, which will bypass this check Deploy smart contract with the function add\_simple\_pool which returns success Call jump\_amm.testnet.attackerjump.testnet with any add\_simple\_pool arguments to save the data to the indexer database

This vulnerability enables:

Bloating the database to make it costly to run and query Causing system components to operate on invalid data

#### Recommendation

Transaction success must be verified, and exact equality should be used instead of contains() when matching supported contracts

#### Remediation - Fixed

The Jump Defi team has fixed the issue by verifying the success of the receipt and replaced the contains() with exact equality.

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=31)

### GUV-10: Any Pool Can Be Marked As Blacklisted On Aggregator

Medium

The Aggregator's /pool route allows pools to be blacklisted without any access control mechanism.

aggregator:update\_pool:aggregator/src/main.rs

```
     #[put("/pool")]
       async fn update_pool(payload: web::Json<BlacklistPool>) -> impl Responder {
         let BlacklistPool {
            pool_id,
            liquidity_provider,
            token_in,
            token_out,
            blacklisted,
         } = payload.into_inner();
         tracing::info!(
            "main::blacklist_pool() - Updating pool with pool_id: {}, blacklisted: {}",
            pool_id,
            blacklisted
         );
```

```
          let key = format!(
             "pool:{}:{}:{}:{}",
             liquidity_provider, pool_id, token_in, token_out
          );
```

match pool::update\_pool(\&key, blacklisted)

#### Recommendation

Implement access control for this route

#### Remediation - Fixed

The Jump Defi team has fixed the issue by removing the pool endpoint.

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=33)

### GUV-11: Missing Tests Across The System

Medium

The system components lack test coverage. Given the numerous cases and complex calculations performed by the indexers and aggregator, comprehensive test coverage is essential.

#### Recommendation

Write both unit and integration tests for indexer, amm-indexer, and aggregator

#### Remediation - Acknowledged

The Jump Defi team has acknowledged the issue and will fix it later.

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=34)

### GUV-12: Error-Prone Parsing of Liquidity Pools

Medium

The parse\_liquidity\_pools function relies on array indexes to extract data from bulk\_data. This approach is error-prone as changes to data format or missing fields will cause crashes. The function's validation is also incorrect — it checks if bulk\_data.len() >= 8, but accesses index 43.

cache:parse\_liquidity\_pools:cache/src/services/parser.rs

```
     if let Value::Bulk(bulk_data) = value {
                // Extract required data from bulk data
               if bulk_data.len() >= 8 {
                  let pool_id = get_value_as_string(&bulk_data[1]);
                  let liquidity_provider = get_value_as_string(&bulk_data[3]);
                    let token_in: String = get_value_as_string(&bulk_data[5]);
                   ...
                 let chain_id = get_value_as_string(&bulk_data[43]);
```

#### Recommendation

Do not rely on indexes to fetch data from Redis Implement a proper deserializer using FromRedisValue trait for the expected type

#### Remediation - Fixed

The Jump Defi team has fixed the issue by rewriting the logic to parse the bulk data without relying on indexes.

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=35)

### GUV-13: Usage of Panic Macro in Production Code

Low

The divide\_and\_floor function uses the panic! macro when encountering a zero divisor. Although this function is currently unused in the main codebase, it should be removed to prevent potential crashes if implemented in the future.

aggregator:divide\_and\_floor:aggregator/src/services/pool.rs

```
      fn divide_and_floor(&self, dividend: BigUint, divisor: BigUint) -> BigUint {
               if divisor.is_zero() {
                  panic!("Division by zero");
               }
                dividend / divisor // In BigUint, division is inherently floor division
             }
```

#### Recommendation

Remove divide\_and\_floor function

#### Remediation - Fixed

The Jump Defi team has fixed the issue by removing the divide\_and\_floor function.

[View this finding in the original PDF](https://www.guvenkaya.co/reports/pdfs/jump-backend.pdf#page=36)

Source: [published GitHub report](https://github.com/Guvenkaya/public-reports/blob/master/Jump-Defi-Backend-And-Frontend-Security-Assessment.pdf) · 36 pages. The original PDF includes the source formatting, figures, and linked references.

## Table of Contents

- [Overview](#overview)
- [About Us](#about-us)
- [About Jump Defi](#about-jump-defi)
- [Audit Results](#audit-results)
- [Project Scope](#project-scope)
- [Out of Scope](#out-of-scope)
- [Timeline](#timeline)
- [Methodology](#methodology)
- [Severity Breakdown](#severity-breakdown)
- [Findings Summary](#findings-summary)
- [Findings Details](#findings-details)

## Share

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.guvenkaya.co%2Freports%2Fjump-backend\&text=Jump%20DeFi%3A%20Backend%20%26%20Frontend%20Security%20Assessment) [Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.guvenkaya.co%2Freports%2Fjump-backend) [Share on Threads](https://www.threads.net/intent/post?text=Jump%20DeFi%3A%20Backend%20%26%20Frontend%20Security%20Assessment%20https%3A%2F%2Fwww.guvenkaya.co%2Freports%2Fjump-backend)

[Discuss a security review](https://www.guvenkaya.co/contact?source=report) [View PDF on GitHub](https://github.com/Guvenkaya/public-reports/blob/master/Jump-Defi-Backend-And-Frontend-Security-Assessment.pdf)

## Tell us what you need to secure.

Describe your system, main concern, and deadline. We will reply with scoping questions and a proposed next step.

[Discuss your scope](https://www.guvenkaya.co/contact?source=report)
