Skip to content

fix(standards): stop mint policies from rewriting the output note - #3760

Merged
mmagician merged 7 commits into
nextfrom
fix-revert-mint-request
Sep 8, 2026
Merged

mmagician merged 7 commits into
nextfrom
fix-revert-mint-request

Conversation

@onurinanc

Copy link
Copy Markdown
Collaborator

Summary

  • Assert in execute_mint_policy that the mint policy returns the caller-supplied tag, note_type, and RECIPIENT unchanged.
  • Keep ASSET_VALUE adjustable, so a fungible faucet still mints the policy-adjusted amount.
  • Document the mint policy interface contract on MintPolicy.
  • Cover both new assertions with custom-policy tests on the non-fungible faucet.

Closes #3759.

@partylikeits1983 partylikeits1983 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good to me! Approving modulo the slight refactor of the execute_mint_policy procedure.

Comment on lines +365 to +385
# assert the policy returned the note metadata unchanged
push.0.0 dup.7 dup.7
# => [new_tag, new_note_type, 0, 0, NEW_ASSET_VALUE, new_tag, new_note_type, NEW_RECIPIENT]

padw loc_loadw_le.MINT_NOTE_METADATA_PTR
# => [NOTE_METADATA, NEW_NOTE_METADATA, NEW_ASSET_VALUE, new_tag, new_note_type, NEW_RECIPIENT]

assert_eqw.err=ERR_MINT_POLICY_MODIFIED_NOTE_METADATA
# => [NEW_ASSET_VALUE, tag, note_type, NEW_RECIPIENT]

# assert the policy returned the RECIPIENT unchanged
repeat.4
dup.9
end
# => [NEW_RECIPIENT, NEW_ASSET_VALUE, tag, note_type, NEW_RECIPIENT]

padw loc_loadw_le.MINT_RECIPIENT_PTR
# => [RECIPIENT, NEW_RECIPIENT, NEW_ASSET_VALUE, tag, note_type, NEW_RECIPIENT]

assert_eqw.err=ERR_MINT_POLICY_MODIFIED_RECIPIENT
# => [NEW_ASSET_VALUE, tag, note_type, RECIPIENT]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since execute_mint_policy is already kind of large, I'd put this logic into a separate procedure, simply for readability.

@mmagician mmagician left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not sure the underlying issue #3759 is a problem in the first place.

At the end of the day, minting of assets only affects the faucet owner/operator (not users directly; they are the beneficiary of a mint, if anything), and the owner is responsible for choosing the mint policy - so I don't see how this could be exploited or lead to a problem in any way?

@onurinanc

onurinanc commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

@mmagician

Agreed, there is no exploit here, but the concern here is a potential mistake for a written policy. (It is also an informational issue: "N-16")

Nothing enforces the policy's stack contract at the dyncall boundary. Think about an allowlist policy written similar to this:

pub proc check_policy
    # => [ASSET_VALUE, tag, note_type, RECIPIENT, pad(6)]

    # get RECIPIENT to the top for the allowlist lookup, and forget to put it back
    # ...
    # assertz.err=ERR_RECIPIENT_NOT_ALLOWLISTED
    
    # => [RECIPIENT, ASSET_VALUE, tag, note_type, pad(6)]
end

The policy works as expected, it does reject a non-allowlisted recipient, but the stack comes back rotated. Nothing catches this, the transaction succeeds and token_supply increases, but the note that can never be consumed.

The non-fungible faucets already have this guard such as: "ERR_NFT_MINT_POLICY_MODIFIED_ASSET_VALUE"

With this PR, we are sure that the stack is not rewritten also for fungible faucets.

@mmagician mmagician left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't know if we'll ever be able to guard against all types of misconfigured policies @onurinanc, but I suppose it doesn't hurt.

@mmagician
mmagician added this pull request to the merge queue Sep 8, 2026
Merged via the queue into next with commit 05ba0f0 Sep 8, 2026
19 checks passed
@mmagician
mmagician deleted the fix-revert-mint-request branch September 8, 2026 07:22
mmagician pushed a commit that referenced this pull request Sep 9, 2026
Renaming the section to v0.17.0-rc.3 moved four entries under an
already-published heading: #3760, #3811, #3824 and #3825 all merged on
2026-09-08, three days after rc.3 was cut, and none of them are in the
tag's changelog. Two are [BREAKING] and one fixes an AccountInterface
panic, so attributing them to a version that does not contain them
misleads anyone pinned to rc.3.

Move them to rc.4, keeping their original subsections. The rc.3 section
now lists only work that shipped in rc.3.

Note it still lists four of those entries twice (#3729, #3754, #3753,
#3580). That duplication is already on next, which carries each of them
twice, so it is left for a separate pass rather than fixed here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KNLFFu1vkaRFyybnKAYfw
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.

Mint Policy Interface Allows Overriding Note Tag, Type, and Recipient Without Documented Rationale

3 participants