All audits

Web3 · Smart contract audit

Coinversa

softstack has completed 2 smart contract audits for Coinversa in March 2026, reporting 33 findings in total (4 high, 13 medium and 16 low), of which 29 were resolved or mitigated before the final reports. Every report is published in the softstack public audit archive.

Key facts

Client
Coinversa
Audits completed
2
Latest audit
Type
Smart contract audit
Chains
Canton, Solana, Ethereum

About the project

Coinversa provides on-chain market intelligence for applications, traders and AI agents, covering wallet performance, trading cohorts, liquidation risk and cross-market assets. Data is served through a REST API, WebSocket streams and a hosted MCP server for Hyperliquid. Coinversa Inc is incorporated in Delaware and covers the Canton, Solana and Ethereum ecosystems.

Findings

Combined across all 2 reviews softstack has completed for Coinversa. Each report is broken out below.

0Critical
4High
13Medium
16Low
0Informational

29 of 33 findings resolved before the final reports.

Reports

Newest first. Every report covers its own scope and commit.

  1. Backend & Frontend Codebase Security smart contract audit

    PDF
    0Critical
    4High
    8Medium
    1Low
    0Informational

    13 of 13 resolved

    ScopeSource repositorygithub.com/Coinversaa/backend

    Components reviewed

    1 module
    1. See the published report for the file list
    All 13 findings
    IDTitleSeverityStatus
    6.2.1privyAuth GET Bypass: Inconsistent Auth Model

    The `privyAuth` middleware explicitly bypasses token verification for all GET, HEAD, and OPTIONS requests.

    Highfixed
    6.2.2privyAuth No Ownership Check: Trading IDOR

    After verifying the Privy JWT, `privyAuth` sets `req.privyUser.userId` but never asserts that target wallet fields in the request (`address`, `masterAddress`, `fromAddress`) belong to that authenticated user.

    Highfixed
    6.2.3Hardcoded PostgreSQL Credentials in Fallback Connection String

    The PostgreSQL connection pool is initialised with a hardcoded fallback connection string that contains live database credentials.

    Highfixed
    6.2.4Notifications.jsx innerHTML XSS (Stored XSS Vector)

    The `Notifications.jsx` toast renderer builds the notification DOM by setting `toast.innerHTML` to a template literal that directly includes the `message` variable, which is populated from server- provided API error responses…

    Highfixed
    6.2.5Canton Passkey Secret Stored Unencrypted in localStorage

    A passkey-derived cryptographic secret (`coinversaa-id-secret`) is stored unencrypted in `localStorage`. The developer left a TODO comment directly above the storage call acknowledging this is insecure.

    Mediumfixed
    6.2.6Missing Security Hardening Middleware

    The Express backend is missing all standard security hardening middleware: no `helmet` (X- Powered-By header leaks Express framework/version, no Content-Security-Policy, HSTS, X-Frame- Options), no `express-rate-limit` (no brute-force…

    Mediumfixed
    6.2.7JWT Tokens Never Expire

    `jwt.sign()` is called without an `expiresIn` option in `cantonService.ts`. Tokens created without an expiry never expire.

    Mediumfixed
    6.2.8HTML Injection in Email Bodies

    The `/register-interest` endpoint and developer API access request handler interpolate user-supplied `name`, `email`, and `reasonForInterest` fields directly into HTML email templates sent to the admin mailbox.

    Mediumfixed
    6.2.9WebSocket No maxPayload Limit (DoS Risk)

    The `/ws/hyperliquid` WebSocket server is created without a `maxPayload` option. The default `ws` library behaviour is to accept frames of unlimited size.

    Mediumfixed
    6.2.10Auth Tokens in localStorage (Session Theft Risk)

    Auth tokens (`accessToken`, `privy:token`) are stored in `localStorage`, making them readable by any JavaScript on the page.

    Mediumfixed
    6.2.11Vulnerable Dependencies: Backend (121 CVEs, 6 Critical)

    121 CVEs found across 90 packages (6 critical, 58 high, 37 medium, 20 low). Critical packages `pbkdf2`, `sha.js`, `elliptic` are cryptographic libraries — vulnerabilities in these carry elevated risk given the blockchain/trading context.

    Mediumfixed
    6.2.12Vulnerable Dependencies: Frontend (95 CVEs, 4 Critical)

    95 CVEs found across 65 packages (4 critical, 46 high, 43 medium, 2 low).

    Mediumfixed
    6.2.13Express X-Powered-By Header Disclosure

    Express sends `X-Powered-By: Express` in every HTTP response by default. This header advertises the framework to any observer, reducing the cost of reconnaissance for an attacker.

    Lowfixed
  2. Canton DAML Smart Contracts smart contract audit

    PDF
    0Critical
    0High
    5Medium
    15Low
    0Informational

    16 of 20 resolved

    All 20 findings
    IDTitleSeverityStatus
    6.2.1Operator Controls UserIdentity Mutations That Should Belong to the User

    UserIdentity is owned by `userParty`, but `LinkWallet`, `UnlinkWallet`, and `ArchiveIdentity` are all controlled by `operator`.

    Mediumfixed
    6.2.2Core Records Lack Enforced Uniqueness in the Current Canton 3 Design

    `TransactionCommitment`, `UserStatistics`, and `TermsAcceptance` contain commented-out key declarations for the uniqueness properties the system appears to expect.

    Mediumfixed
    6.2.4Terms Acceptance Is Not Enforced by the Transaction Workflow

    The reviewed DAML code does not link `TermsAcceptance` into `TransactionCommitment` creation or redemption.

    Mediumfixed
    6.2.7Transaction Hash Validation Accepts Invalid Pending and EVM Forms

    `validateTxHash` accepts any `pending_`, `solana_pending_`, or `hl_` prefix with no remainder bounds, and accepts 66-character `0x` hashes without verifying that the payload is hexadecimal.

    Lowfixed
    6.2.9sourceWallet Is Not Validated Against walletType in TransactionCommitment

    The `TransactionCommitment` ensure clause validates `txHash`, numeric fields, token symbols, and `dataHash`, but never validates `sourceWallet`.

    Lowfixed
    6.2.14Same-State UpdateStatus Calls Can Still Change blockNumber

    `UpdateStatus` permits `Pending -> Pending`, `Confirmed -> Confirmed`, and `Failed -> Failed`, while also allowing `updatedBlockNumber` to overwrite `blockNumber`.

    Lowacknowledged
    6.2.18signedMessage Is Not Bound to Wallet, Terms Version, or Terms Hash

    `signedMessage` is required to be non-empty, but the code never checks whether it corresponds to `walletAddress`, `termsVersion`, or `termsHash`.

    Lowfixed
    6.2.3User Cannot Revoke Their Own Terms Acceptance

    The only mutating choice on `TermsAcceptance` is `RevokeAcceptance`, and it is controlled by `operator`. The user can query the record, but cannot change or revoke it.

    Mediumfixed
    6.2.5Operator-Supplied acceptedAt Timestamp Is Unconstrained

    `acceptedAt` is a template field provided at creation time, but the `ensure` block does not validate it and no creation helper sets it from ledger time.

    Mediumfixed
    6.2.6Wallet Address Validation Is Mostly Length-Based

    `validateWalletAddress` checks only minimal shape constraints. EVM requires `0x` plus total length 42, but does not verify hexadecimal characters.

    Lowfixed
    6.2.8LinkWallet Does Not Verify Wallet Ownership

    `LinkWallet` checks formatting and wallet-count limits, but never proves that the user controls the wallet being attached.

    Lowacknowledged
    6.2.10termsHash Checks Length but Not Hex Content

    `TermsAcceptance` only checks `Text.length termsHash == 64`. That enforces size, not SHA-256 hex encoding.

    Lowfixed
    6.2.11LinkAuthKey Allows Duplicate Authentication Keys

    `LinkAuthKey` prepends a new `(authKey, encryptedKey)` pair but does not check whether the same key is already present.

    Lowfixed
    6.2.12Redeem Does Not Enforce a Transaction-State Transition

    `Redeem` checks wallet linkage and one-time redemption, but it does not validate the current `status` and does not change `status` after redemption.

    Lowfixed
    6.2.13ArchiveTransaction Allows Unilateral Record Deletion

    `ArchiveTransaction` is operator-controlled and unconditional. Because the user is not a stakeholder on `TransactionCommitment`, this lets the operator remove active transaction records without a user-side check or notice in the template…

    Lowacknowledged
    6.2.15Statistics Counters Are Not Consistently Monotonic

    `newTotalTransactions` must be greater than or equal to the current value, but `newTotalVolumeUSD` is only checked for non-negativity and `newUniqueTokens` is not checked against the previous value.

    Lowfixed
    6.2.16Referrer Can Be Rewritten or Removed Without Constraint

    `SetReferrer` accepts `Optional Party` and only checks that the referrer is not the same as `userParty`. The current code permits unlimited changes and explicit removal via `None`.

    Lowacknowledged
    6.2.17UserStatistics Is Not Derived From Transaction Records

    `UpdateStatistics` accepts aggregate values and user-preference fields directly. It does not read or reference `TransactionCommitment`, so the statistics record is not mechanically tied to source transactions.

    Lowfixed
    6.2.19ipAddress Is Stored Directly On-Ledger

    `TermsAcceptance` stores `ipAddress : Optional Text` directly in the contract payload, which means the value becomes part of immutable ledger history once created.

    Lowfixed
    6.2.20Terms Versions Have No On-Ledger Lifecycle Management

    `termsVersion` is any non-empty string, and there is no registry, deprecation flow, or active-version check. The transaction workflow also does not verify that a user accepted the currently active version.

    Lowfixed

Methodology

Review process

  1. Scoping and threat modelling

    The commit hash is frozen and the attack surface is mapped: asset flows, trust assumptions, privileged roles and the external systems the code depends on.

  2. Automated analysis

    Static analysers sweep the full codebase to surface known weakness patterns, unreachable states and deviations from established conventions.

  3. Manual code review

    Independent engineers read the code line by line, concentrating on business logic, access control, arithmetic and the handling of external calls.

  4. Adversarial testing

    Property-based fuzzing and invariant tests attack the assumptions the protocol relies on, targeting states that ordinary unit tests never reach.

  5. Reporting

    Every finding is documented with a severity rating, its impact, the steps to reproduce it and a concrete remediation the team can act on.

  6. Remediation verification

    Submitted fixes are re-reviewed against the original finding, and the final report records the resolved state of each one.

Standards and references

FAQ

2 separate reviews, the first in March 2026 and the most recent in March 2026. Each one covers its own scope and commit, and is listed individually on this page.

33 findings across all 2 reviews: 4 high, 13 medium and 16 low. 29 of 33 were resolved or mitigated before the final reports.

Each report covers the code as it stood at the commit it names, the most recent in March 2026. Any code changed after that point is outside the reviewed scope.