diff --git a/ledger/babbage/rules.go b/ledger/babbage/rules.go index bb1d9c7a..16c32bc1 100644 --- a/ledger/babbage/rules.go +++ b/ledger/babbage/rules.go @@ -184,11 +184,19 @@ func UtxoValidateCollateralEqBalance( } collBalance += utxo.Output.Amount() } - // Subtract collateral return amount + + // Skip validation if no valid collateral UTxOs were found + // This avoids subtracting from zero and prevents uint underflow + if collBalance == 0 { + return nil + } + + // Subtract collateral return amount with underflow protection collReturn := tx.CollateralReturn() - if collReturn != nil { + if collReturn != nil && collBalance >= collReturn.Amount() { collBalance -= collReturn.Amount() } + if totalCollateral == collBalance { return nil } diff --git a/ledger/babbage/rules_test.go b/ledger/babbage/rules_test.go index 2e262075..6606ab18 100644 --- a/ledger/babbage/rules_test.go +++ b/ledger/babbage/rules_test.go @@ -1449,6 +1449,27 @@ func TestUtxoValidateCollateralEqBalance(t *testing.T) { } }, ) + // no valid collateral UTxO, should skip and not underflow + t.Run("no valid collateral UTxO, should skip and not underflow", func(t *testing.T) { + // Ledger state with NO matching UTxO + missingUtxoLedgerState := test.MockLedgerState{ + MockUtxos: []common.Utxo{}, // empty + } + testTx.Body.TxCollateralReturn = &babbage.BabbageTransactionOutput{ + OutputAmount: mary.MaryTransactionOutputValue{ + Amount: testCollateralReturnAmountBad, + }, + } + err := babbage.UtxoValidateCollateralEqBalance( + testTx, + testSlot, + missingUtxoLedgerState, + testProtocolParams, + ) + if err != nil { + t.Errorf("Should skip collateral return validation if collBalance == 0. Got error: %v", err) + } + }) } func TestUtxoValidateTooManyCollateralInputs(t *testing.T) {