Skip to content

fix(lang): only capture a policy's ref where its script runs#333

Merged
scarmuega merged 1 commit into
mainfrom
fix/policy-ref-capture-only-on-script-execution
Jun 7, 2026
Merged

fix(lang): only capture a policy's ref where its script runs#333
scarmuega merged 1 commit into
mainfrom
fix/policy-ref-capture-only-on-script-execution

Conversation

@scarmuega

Copy link
Copy Markdown
Contributor

Follow-up to #332.

Bug

#332 captured a ref-backed policy's ref UTxO whenever the policy appeared in an address position, gated on is_address_expr(). That flag is set for both an input's from and an output's to. So:

policy Vault { hash: 0x.., ref: 0x..#0 }

tx send(quantity: Int) {
    input funding { from: SomeParty, min_amount: Ada(quantity) }
    output { to: Vault, amount: Ada(quantity) }   // <-- wrongly added Vault's ref as a reference input
}

Sending funds to a script address does not run the script (it runs later, when those funds are spent), so no reference input should be attached. The over-capture bloats the tx and can make it unresolvable if that UTxO is gone.

Fix

Capture is now driven solely by the explicit capture_policy_ref signal, set only at the sites where the policy's script actually executes in this tx:

  • input fromenter_address_expr().capturing_policy_refs()
  • mint / burn amount → already sets it

Symbol::PolicyDef no longer captures on is_address_expr(); the BuildScriptAddress lowering stays keyed on it. Output to keeps its address lowering but no longer captures.

Net rule: capture iff the policy's script runs in this transaction — input from, mint, burn.

Test

New send_to_policy example tx outputs to a ref-backed policy without spending from it; asserts references is empty. Existing ref-backed from/mint/burn checks still expect 1. cargo test -p tx3-lang: 167 passed, 0 failed — no snapshot regressions (no committed example used a ref-backed policy as an output recipient).

🤖 Generated with Claude Code

PR #332 captured a ref-backed policy's `ref` UTxO whenever the policy
appeared in an address position, keyed on `is_address_expr()`. But that
flag is also set for an output's `to`, so sending funds *to* a script
address wrongly pulled the policy's reference script into the
transaction — the script does not run when receiving, only when spending.

Drive the capture solely off the explicit `capture_policy_ref` signal,
set at the script-executing sites: an input's `from` and mint/burn
amounts. Output `to` keeps its address lowering but no longer captures.

Add a `send_to_policy` example tx that outputs to a ref-backed policy
without spending from it, asserting it contributes no reference input.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@scarmuega scarmuega force-pushed the fix/policy-ref-capture-only-on-script-execution branch from 38a2eea to d351217 Compare June 7, 2026 15:34
@scarmuega scarmuega merged commit b19f287 into main Jun 7, 2026
6 checks passed
@scarmuega scarmuega deleted the fix/policy-ref-capture-only-on-script-execution branch June 7, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant