Skip to content

Fix panics in reply parsing + validate route continuity in set_route#23

Open
Syzygys wants to merge 1 commit into
InjectiveLabs:masterfrom
Syzygys:fix/reply-parse-and-route-continuity
Open

Fix panics in reply parsing + validate route continuity in set_route#23
Syzygys wants to merge 1 commit into
InjectiveLabs:masterfrom
Syzygys:fix/reply-parse-and-route-continuity

Conversation

@Syzygys

@Syzygys Syzygys commented Jul 2, 2026

Copy link
Copy Markdown

What

  1. parse_market_order_response() used two unwrap()s after already constructing the correct ContractError variants — changed its return type from StdResult to Result<_, ContractError> so those errors are actually returned via ? instead of discarded via panic. Also handles an empty msg_responses list explicitly instead of unwrapping None.
  2. verify_route_exists() only checked the first and last market in a route. A route with a broken middle hop would pass set_route and only fail later at swap time with a generic exchange-module rejection. Added an explicit continuity check between consecutive markets so a bad route is rejected immediately with a specific error.

Why

Found while reviewing the contract for a security bounty pass. Neither issue is exploitable beyond a failed/reverted transaction (CosmWasm traps roll back the whole tx, and set_route is admin-only), so this is a robustness/error-message improvement, not a security report.

Testing

cargo check -p swap-contract --lib and cargo clippy -p swap-contract --lib both pass clean. Could not run the full cargo test suite locally — injective-test-tube's build script requires a go toolchain (cgo) that isn't available in my environment; CI should cover it.

Summary by CodeRabbit

  • Bug Fixes
    • Improved route validation so invalid multi-hop swap routes are rejected earlier if any adjacent steps are incompatible.
    • Made swap reply handling more robust by returning clear errors when reply data is missing or malformed, reducing unexpected failures.

parse_market_order_response() used two unwrap()s after already constructing
the correct ContractError variants (SubMsgFailure, ReplyParseFailure) -
change its return type from StdResult to Result<_, ContractError> so those
errors can actually be returned with '?' instead of discarded via panic.
Also handle an empty msg_responses list explicitly instead of unwrapping
Option::None.

fix(admin): validate route continuity in set_route

verify_route_exists() only checked that the first market contains the
source denom and the last market contains the target denom. A multi-hop
route with a broken middle hop (market[i] and market[i+1] sharing no
denom) would pass set_route and only fail later at swap execution time
with a generic exchange-module rejection. Add an explicit continuity
check between each consecutive pair of markets so a bad route is rejected
immediately, with a specific error message, at configuration time.
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f7f9b493-b6a8-46e3-82c8-40a77c14eb33

📥 Commits

Reviewing files that changed from the base of the PR and between 772192d and f8c481b.

📒 Files selected for processing (2)
  • contracts/swap/src/admin.rs
  • contracts/swap/src/swap.rs

📝 Walkthrough

Walkthrough

This PR adds continuity validation for multi-hop swap routes in verify_route_exists, ensuring consecutive markets share a denom, and rewrites parse_market_order_response to return Result<_, ContractError> instead of panicking via unwrap() on missing or malformed reply data.

Changes

Swap Contract Robustness Improvements

Layer / File(s) Summary
Route continuity validation
contracts/swap/src/admin.rs
verify_route_exists now checks each consecutive pair of markets in a route shares at least one denom, failing with ContractError::CustomError if the route is discontinuous.
Panic-free reply parsing
contracts/swap/src/swap.rs
parse_market_order_response signature changed from StdResult<MsgCreateSpotMarketOrderResponse> to Result<MsgCreateSpotMarketOrderResponse, ContractError>, replacing unwraps with explicit error handling for empty msg_responses and decode failures.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
    participant Admin as set_route (admin.rs)
    participant Verify as verify_route_exists
    participant Contract as ContractError

    Admin->>Verify: validate route (source_denom, target_denom, markets)
    Verify->>Verify: build (quote_denom, base_denom) list
    Verify->>Verify: check first/last denom match
    loop each consecutive market pair
        Verify->>Verify: check shared denom
        alt no shared denom
            Verify->>Contract: return CustomError (route not continuous)
        end
    end
    Verify-->>Admin: route valid
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes both main changes: reply parsing panic fixes and route continuity validation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant