Skip to content

PSwap Contract#2636

Draft
VAIBHAVJINDAL3012 wants to merge 1 commit into0xMiden:nextfrom
inicio-labs:pswap-note
Draft

PSwap Contract#2636
VAIBHAVJINDAL3012 wants to merge 1 commit into0xMiden:nextfrom
inicio-labs:pswap-note

Conversation

@VAIBHAVJINDAL3012
Copy link

  • Add PSWAP (partially-fillable swap) note to miden-standards — a new note script that enables partial
    fills, creator reclaim, and inflight cross-swaps for decentralized asset exchange

    • MASM script (pswap.masm) uses 18-item KEY+VALUE storage layout, proportional price calculation with
      1e5 precision factor, and an early-return optimization for full fills to avoid integer truncation
    • Rust library (PswapNote) provides note creation, output note construction (P2ID payback + optional
      remainder), storage parsing, and calculate_offered_for_requested convenience method
    • 12 integration tests covering full fill, private fill, partial fill, inflight cross-swap, creator
      reclaim, invalid input rejection, multiple fill amounts, non-exact ratios, fuzz cases, and chained
      partial fills

    Test plan

    • cargo build -p miden-standards — MASM compiles into standards library
    • cargo test -p miden-standards pswap — 4 unit tests (script loading, tag construction, output
      calculation, storage parsing)
    • cargo test -p miden-testing pswap — 12 integration tests (full/partial/private fills, cross-swaps,
      reclaim, fuzz, chained fills)

/// - Note can be partially or fully filled by consumers
/// - Unfilled portions create remainder notes
/// - Creator receives requested assets via P2ID notes
pub struct PswapNote;
Copy link
Contributor

@PhilippGackstatter PhilippGackstatter Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're adding this as a completely new note, it would be great if we could immediately set it up with the structure we want to end up with, i.e. the one described in #2283.

So roughly:

pub struct PswapNoteStorage {
    requested_key: Word,
    requested_value: Word,
    swapp_tag: NoteTag,
    p2id_tag: NoteTag,
    swap_count: u64,
    creator_account_id: AccountId,
}

impl PswapNoteStorage {
    pub fn into_recipient(self, serial_num: Word) -> NoteRecipient {
        todo!()
    }
}

impl From<PswapNoteStorage> for NoteStorage {
    fn from(pswap_storage: PswapNoteStorage) -> Self {
        todo!()
    }
}

#[derive(Debug, Clone, bon::Builder)]
#[builder(finish_fn(vis = "", name = build_internal))]
pub struct PswapNote {
    sender: AccountId,

    storage: PswapNoteStorage,

    serial_number: Word,

    #[builder(default = NoteType::Private)]
    note_type: NoteType,

    #[builder(default)]
    assets: NoteAssets,

    #[builder(default)]
    attachment: NoteAttachment,
}

impl PswapNote {
    pub fn execute(
        &self,
        consumer_account_id: AccountId,
        input_amount: u64,
        inflight_amount: u64,
    ) -> Result<(Note, Option<PswapNote>), NoteError> {
        todo!("what create_output_notes does now")
    }
}

This would result in a more natural API, i.e. execute takes &self instead of create_output_notes taking an arbitrary &Note.

What do you think?

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.

2 participants