miden-lib 0.12.4

Standard library of the Miden protocol
Documentation
use.miden::active_note
use.miden::output_note
use.miden::contracts::wallets::basic->wallet

# CONSTANTS
# =================================================================================================

const.SWAP_NOTE_INPUTS_NUMBER=12

# ERRORS
# =================================================================================================

const.ERR_SWAP_WRONG_NUMBER_OF_INPUTS="SWAP script expects exactly 12 note inputs"

const.ERR_SWAP_WRONG_NUMBER_OF_ASSETS="SWAP script requires exactly 1 note asset"

#! Swap script: adds an asset from the note into consumers account and
#! creates a note consumable by note issuer containing requested ASSET.
#!
#! Requires that the account exposes:
#! - miden::contracts::wallets::basic::receive_asset procedure.
#! - miden::contracts::wallets::basic::move_asset_to_note procedure.
#!
#! Inputs:  [ARGS]
#! Outputs: []
#!
#! Note inputs are assumed to be as follows:
#! - REQUESTED_ASSET
#! - PAYBACK_NOTE_RECIPIENT
#! - payback_note_execution_hint
#! - payback_note_type
#! - payback_note_aux
#! - payback_note_tag
#!
#! Panics if:
#! - account does not expose miden::contracts::wallets::basic::receive_asset procedure.
#! - account does not expose miden::contracts::wallets::basic::move_asset_to_note procedure.
#! - account vault does not contain the requested asset.
#! - adding a fungible asset would result in amount overflow, i.e., the total amount would be
#!   greater than 2^63.
begin
    # dropping note args
    dropw
    # => []

    # --- create a payback note with the requested asset ----------------

    # store note inputs into memory starting at address 0
    push.0 exec.active_note::get_inputs
    # => [num_inputs, inputs_ptr]

    # make sure the number of inputs is 12
    eq.SWAP_NOTE_INPUTS_NUMBER assert.err=ERR_SWAP_WRONG_NUMBER_OF_INPUTS
    # => [inputs_ptr]

    # load REQUESTED_ASSET
    mem_loadw_be
    # => [REQUESTED_ASSET]

    # load PAYBACK_NOTE_RECIPIENT
    padw mem_loadw_be.4
    # => [PAYBACK_NOTE_RECIPIENT, REQUESTED_ASSET]

    # load payback P2ID details
    padw mem_loadw_be.8
    # => [tag, aux, note_type, execution_hint, PAYBACK_NOTE_RECIPIENT, REQUESTED_ASSET]

    # create payback P2ID note
    exec.output_note::create
    # => [note_idx, REQUESTED_ASSET]

    movdn.4
    # => [REQUESTED_ASSET, note_idx]

    # padding stack with 11 zeros
    repeat.11
        push.0
        movdn.5
    end
    # => [REQUESTED_ASSET, note_idx, pad(11)]

    # move asset to the note
    call.wallet::move_asset_to_note
    # => [REQUESTED_ASSET, note_idx, pad(11)]

    dropw drop push.0
    # => [pad(12)]

    # --- move assets from the SWAP note into the account -------------------------

    # store the number of note assets to memory starting at address 0
    push.0 exec.active_note::get_assets
    # => [num_assets, ptr, pad(12)]

    # make sure the number of assets is 1
    assert.err=ERR_SWAP_WRONG_NUMBER_OF_ASSETS
    # => [ptr, pad(12)]

    # load the ASSET
    mem_loadw_be
    # => [ASSET, pad(12)]

    # add the ASSET to the account
    call.wallet::receive_asset
    # => [pad(16)]

    # clearing the stack of padded 0s
    repeat.4
        dropw
    end
    # => []
end