Skip to content

Commit c53efcd

Browse files
committed
Add well-funded multi-asset property test for calcMinFeeRecursive
1 parent 5ab0b5e commit c53efcd

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

cardano-api/test/cardano-api-test/Test/Cardano/Api/Experimental.hs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ tests =
8585
[ testProperty
8686
"well-funded transaction always succeeds"
8787
prop_calcMinFeeRecursive_well_funded_succeeds
88+
, testProperty
89+
"well-funded multi-asset transaction always succeeds"
90+
prop_calcMinFeeRecursive_well_funded_multi_asset
8891
, testProperty
8992
"fee calculation is idempotent"
9093
prop_calcMinFeeRecursive_fee_fixpoint
@@ -612,6 +615,44 @@ genFundedSimpleTx era = do
612615
& Exp.setTxFee 0
613616
return (Exp.makeUnsignedTx era txBodyContent, utxo, changeAddr)
614617

618+
-- | Like 'genFundedSimpleTx' but the UTxO and output both carry native tokens.
619+
-- The output sends all tokens; the surplus ADA goes to the change output.
620+
-- This exercises Case 2's multi-asset handling on the success path.
621+
genFundedMultiAssetTx
622+
:: Exp.Era era
623+
-> Gen
624+
( Exp.UnsignedTx (Exp.LedgerEra era)
625+
, L.UTxO (Exp.LedgerEra era)
626+
, L.Addr
627+
)
628+
genFundedMultiAssetTx era = do
629+
let sbe = convert era
630+
txIn <- genTxIn
631+
addr <- Api.toShelleyAddr <$> genAddressInEra sbe
632+
changeAddr <- Api.toShelleyAddr <$> genAddressInEra sbe
633+
sendCoin <- L.Coin <$> Gen.integral (Range.linear 2_000_000 5_000_000)
634+
surplus <- L.Coin <$> Gen.integral (Range.linear 2_000_000 17_000_000)
635+
tokenQty <- Gen.integral (Range.linear 1 1_000_000)
636+
let fundingCoin = sendCoin + surplus
637+
policyId = L.PolicyID $ L.ScriptHash "1c14ee8e58fbcbd48dc7367c95a63fd1d937ba989820015db16ac7e5"
638+
multiAsset = L.MultiAsset $ Map.singleton policyId (Map.singleton (Mary.AssetName "testtoken") tokenQty)
639+
ledgerTxIn = Api.toShelleyTxIn txIn
640+
fundingTxOut =
641+
Exp.obtainCommonConstraints era $
642+
L.mkBasicTxOut addr (L.MaryValue fundingCoin multiAsset)
643+
utxo = L.UTxO $ Map.singleton ledgerTxIn fundingTxOut
644+
sendTxOut =
645+
Exp.obtainCommonConstraints era $
646+
Exp.TxOut $
647+
Exp.obtainCommonConstraints era $
648+
Ledger.mkBasicTxOut addr (L.MaryValue sendCoin multiAsset)
649+
txBodyContent =
650+
Exp.defaultTxBodyContent
651+
& Exp.setTxIns [(txIn, Exp.AnyKeyWitnessPlaceholder)]
652+
& Exp.setTxOuts [sendTxOut]
653+
& Exp.setTxFee 0
654+
return (Exp.makeUnsignedTx era txBodyContent, utxo, changeAddr)
655+
615656
-- | Generates a simple lovelace-only transaction where the single output
616657
-- (5-10 ADA) greatly exceeds the UTxO funding (0.5-2 ADA).
617658
genUnderfundedTx
@@ -667,6 +708,27 @@ prop_calcMinFeeRecursive_well_funded_succeeds = H.property $ do
667708
(resultLedgerTx ^. L.bodyTxL)
668709
balance H.=== mempty
669710

711+
-- | Like 'prop_calcMinFeeRecursive_well_funded_succeeds' but the UTxO and
712+
-- output carry native tokens. Verifies that surplus tokens are correctly
713+
-- distributed to the change output and the result is fully balanced.
714+
prop_calcMinFeeRecursive_well_funded_multi_asset :: Property
715+
prop_calcMinFeeRecursive_well_funded_multi_asset = H.property $ do
716+
(unsignedTx, utxo, changeAddr) <- H.forAll $ genFundedMultiAssetTx Exp.ConwayEra
717+
case Exp.calcMinFeeRecursive changeAddr unsignedTx utxo exampleProtocolParams mempty mempty mempty 0 of
718+
Left err -> H.annotateShow err >> H.failure
719+
Right (Exp.UnsignedTx resultLedgerTx) -> do
720+
let resultFee = resultLedgerTx ^. L.bodyTxL . L.feeTxBodyL
721+
H.assert $ resultFee > L.Coin 0
722+
let balance =
723+
UnexportedLedger.evalBalanceTxBody
724+
exampleProtocolParams
725+
(const Nothing)
726+
(const Nothing)
727+
(const False)
728+
utxo
729+
(resultLedgerTx ^. L.bodyTxL)
730+
balance H.=== mempty
731+
670732
-- | 'calcMinFeeRecursive' is idempotent: applying it to its own result
671733
-- yields the same 'UnsignedTx'. This confirms the fee has reached a
672734
-- fixed point and that any surplus was already distributed to outputs.

0 commit comments

Comments
 (0)