The PswapNote helpers reproduce the swap note logic off-chain so that a client can predict the notes that a consumption will create. execute combines the caller-supplied account_fill_asset and note_fill_asset into a single payback asset and forwards it to create_payback_note, which places that asset into the payback note verbatim. Neither step relates the faucet of the fill assets to the requested faucet recorded in note storage, which is read only to build the remainder note. FungibleAsset::add rejects two fills whose faucets disagree with each other, but it never compares either fill against the requested faucet, and the branch that handles a single fill asset does not call it at all.
The note script cannot reproduce that behavior. On-chain, only the fill amounts are taken from the note arguments while the payback faucet is loaded from note storage, as in pswap.masm, and the note arguments carry bare amounts with no faucet, so a consumer cannot steer the on-chain faucet. A caller that supplies a fill asset from a faucet other than the requested one therefore obtains a predicted payback note whose assets commitment, and consequently whose note details commitment and note identifier, differ from the note the transaction actually creates. Nothing surfaces the discrepancy, because expected-output-note checking compares only note recipients, which are unchanged. The effect is confined to off-chain prediction and client-side accounting for the caller that supplied the incorrect faucet; the remaining outputs and the on-chain result are unaffected.
Consider validating that every provided fill asset uses the faucet returned by requested_faucet_id before the fills are combined, or deriving the payback asset from that faucet and the computed fill amount, so that the off-chain helper follows the same storage-driven semantics as the note script.
Copied verbatim from finding L-31 (low severity) of the OpenZeppelin smart contract diff audit (NFTs). The audit was performed against commit 8411bf093bde25285708faac152b6d7269009617.
The
PswapNotehelpers reproduce the swap note logic off-chain so that a client can predict the notes that a consumption will create.executecombines the caller-suppliedaccount_fill_assetandnote_fill_assetinto a single payback asset and forwards it tocreate_payback_note, which places that asset into the payback note verbatim. Neither step relates the faucet of the fill assets to the requested faucet recorded in note storage, which is read only to build the remainder note.FungibleAsset::addrejects two fills whose faucets disagree with each other, but it never compares either fill against the requested faucet, and the branch that handles a single fill asset does not call it at all.The note script cannot reproduce that behavior. On-chain, only the fill amounts are taken from the note arguments while the payback faucet is loaded from note storage, as in
pswap.masm, and the note arguments carry bare amounts with no faucet, so a consumer cannot steer the on-chain faucet. A caller that supplies a fill asset from a faucet other than the requested one therefore obtains a predicted payback note whose assets commitment, and consequently whose note details commitment and note identifier, differ from the note the transaction actually creates. Nothing surfaces the discrepancy, because expected-output-note checking compares only note recipients, which are unchanged. The effect is confined to off-chain prediction and client-side accounting for the caller that supplied the incorrect faucet; the remaining outputs and the on-chain result are unaffected.Consider validating that every provided fill asset uses the faucet returned by
requested_faucet_idbefore the fills are combined, or deriving the payback asset from that faucet and the computed fill amount, so that the off-chain helper follows the same storage-driven semantics as the note script.Copied verbatim from finding L-31 (low severity) of the OpenZeppelin smart contract diff audit (NFTs). The audit was performed against commit
8411bf093bde25285708faac152b6d7269009617.