Skip to content

Migrate existing IDL presets off local format_arg_value (charset-safety gap for array/struct args) #417

Description

@prasanna-anchorage

Background

While reviewing #375 (which adds core::arg_rendering::format_arg_value — a shared, charset-safe, type-aware arg renderer used by the new Marginfi preset), I checked how the 17 existing IDL-based presets currently render instruction args. None of them use a shared helper — each has its own local, copy-pasted format_arg_value:

// e.g. kamino_vault, meteora_dlmm, onre_app, kamino_farms, kamino_limit, meteora_damm_v2
fn format_arg_value(value: &serde_json::Value) -> String {
    match value {
        serde_json::Value::String(s) => s.clone(),
        other => other.to_string(),
    }
}

// e.g. jupiter_perps, kamino_borrow, drift, jupiter_earn, squads_multisig,
// exponent_finance, neutral_trade, jupiter_borrow, orca_whirlpool
fn format_arg_value(value: &serde_json::Value) -> String {
    match value {
        serde_json::Value::String(s) => s.clone(),
        serde_json::Value::Number(n) => n.to_string(),
        serde_json::Value::Bool(b) => b.to_string(),
        serde_json::Value::Null => "null".to_string(),
        other => other.to_string(),
    }
}

Presets: kamino_vault, jupiter_perps, kamino_borrow, meteora_dlmm, drift, onre_app, jupiter_earn, kamino_farms, squads_multisig, kamino_limit, exponent_finance, meteora_damm_v2, neutral_trade, metadao_conditional_vault, jupiter_borrow, orca_whirlpool, metadao_futarchy.

The problem

For any arg whose serde_json::Value is an Array or Object (byte arrays, structs, enum payloads, nested IDL types), the fallback arm calls other.to_string() / value.to_string(), which is serde_json::Value's Display impl — i.e. it serializes the value as literal JSON, quotes and all (e.g. ["a","b"], {"side":"buy"}).

That's a charset-safety violation risk: SignablePayload::validate_charset rejects " and \ in rendered field text. Any preset among the 17 above that decodes an instruction with an array- or struct-typed arg would emit a fallback string containing ", which the crate's own charset validation is specifically designed to catch and reject — meaning either (a) it's never been hit because none of the fuzzed/tested transactions for these presets exercise an array/struct arg, or (b) it's silently failing charset validation somewhere already. Either way it's a live gap, not a hypothetical one, since it doesn't depend on any future IDL — it's live in main today for these 17 presets.

Suggested fix

Migrate these presets off their local format_arg_value onto the shared, charset-safe, type-aware version added in core::arg_rendering by #375 (plus the find_idl_instruction/arg_types_for helpers proposed as a follow-up there). This fixes the charset-safety gap and gets type-driven byte-array rendering (no more mis-rendering an array of small numbers as a JSON blob) in one pass, rather than fixing each preset's local copy separately.

Scope note

Deliberately kept out of #375 itself — that PR's own description says "existing presets keep their current renderers untouched," and this touches ~17 files rather than the one new preset. Tracking here so it doesn't get lost.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions