fix(plutus): base collateral on whole tx fee#3540
Merged
Merged
Conversation
The ledger requires collateral to cover `collateralPercentage` of the whole transaction fee, not just the Plutus script execution cost. Add pessimistic `base_fee` estimate (fee for tx of max size by default) to the script cost when computing `min_collateral`, and use ceiling to match the ledger's rounding. Replace the arbitrary 1M lovelace buffer in `collateral` with a min UTxO value derived from protocol parameters, so the return collateral output stays above the min UTxO limit.
`test_minting_with_limited_collateral` hardcoded the funded collateral UTxO amount to 2M lovelace, which only matched the old `compute_cost` output. Use `minting_cost.collateral` so the return collateral txout is balanced against the real UTxO value. Base the limited total collateral on the actual tx fee instead of `min_collateral`, which now includes the pessimistic base fee and could exceed the required collateral, making the tx valid.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR aligns Plutus collateral computation with ledger rules by basing min_collateral on the whole transaction fee (script fee + estimated non-script “base” fee) and matching the ledger’s ceiling rounding. It also replaces the previous fixed 1 ADA buffer with a min-UTxO-derived buffer that tracks utxoCostPerByte, and updates one negative minting test to derive collateral amounts from the computed cost values.
Changes:
- Update
plutus_common.compute_cost()to:- include a
base_feeestimate in collateral computation, - use
math.ceilfor collateral rounding, - derive the return-collateral buffer from
utxoCostPerByte(instead of a fixed 1_000_000).
- include a
- Fix
test_minting_with_limited_collateralto useminting_cost.collateraland derive an insufficienttotal_collateral_amountfrom the actual tx fee used in the test.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
cardano_node_tests/tests/plutus_common.py |
Adjusts collateral/min-collateral calculation to match ledger semantics (whole-fee basis + ceiling rounding) and makes the return-collateral buffer depend on utxoCostPerByte. |
cardano_node_tests/tests/tests_plutus_v2/test_mint_negative_raw.py |
Updates a negative minting test to use computed collateral and to construct a reliably insufficient total collateral based on the tx fee. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fix collateral computation in
plutus_common.compute_cost()so it matcheswhat the ledger actually requires.
Base collateral on the whole transaction fee
The ledger requires collateral to cover
collateralPercentageof the wholetransaction fee, not just the Plutus script execution cost (see
validateInsufficientCollateralin cardano-ledger:balance ∗ 100 ≥ txfee ∗ collateralPercent). The previous computation usedonly the script cost, so the computed
min_collateralunderestimated the realrequirement.
Since the exact fee is unknown before the transaction is built, a new
base_feeparameter provides a pessimistic estimate of the non-script part ofthe fee, defaulting to the fee for a transaction of maximum size
(
txFeeFixed + txFeePerByte * maxTxSize). Overestimating is harmless:collateral is not spent for valid scripts, and any excess over the total
collateral comes back in the return collateral output.
Rounding now uses ceiling, matching the ledger (
rationalToCoinViaCeilinginvalidateInsufficientCollateralandcalcReturnAndTotalCollateralincardano-api).
The
collateral_fraction_offsetmultiplier is applied only to the script partof the fee, so tests that use a large offset to inflate collateral for a cheap
script (e.g.
test_collateralswith offset 250 000) don't multiply thesize-based fee estimate as well.
Derive the collateral buffer from min UTxO value
The return collateral txout must itself satisfy the min UTxO value:
(160 + serialized txout size) * utxoCostPerByte(seebabbageMinUTxOValuein cardano-ledger). Replace the arbitrary 1M lovelace buffer with the min UTxO
value for a 67-byte ada-only txout (payment + staking credentials) derived
from protocol parameters, so the buffer tracks
utxoCostPerByteif theparameter changes.
Test fix
test_minting_with_limited_collateralhardcoded the funded collateral UTxOamount to 2M lovelace, which only matched the old
compute_cost()output.It now uses
minting_cost.collateral, and the deliberately insufficienttotal collateral is derived from the actual transaction fee (half of it)
instead of
min_collateral, which now includes the pessimistic base fee andcould exceed the required collateral, making the transaction unexpectedly
valid.