0

A beneficiary tries to withdraw the maximum amount from 2 utxo's of a smart contract in one transaction but that fails. If the beneficiary does it in two steps it succeeds. Why does the first one fail?

Detail :

-------------------------------------------------------------------------
ben         | addr_test1v⋯qarpt4  | = 1101556208 |
            | - 714d2e⋯dea7cb#0   | +    1021470 | [ "ben"×1 ] Token
            | - 714d2e⋯dea7cb#1   | + 1100534738 | 
-------------------------------------------------------------------------
tokencheck  | addr_test1w⋯hyha8n  | =   34000000 |
            | - 347def⋯58e2c7#0   | +   21000000 | {14e594⋯4816fa} Datum
            | - dca3bc⋯b80ae8#0   | +   13000000 | {14e594⋯4816fa} Datum

The beneficiary 'ben' tries to withdraw the maximum amount from smart contract 'tokencheck', and in that transaction also includes his token 'ben' (62656e), to fulfill a condition in the contract.

Ben tries to withdraw from both the utxo's of the contract (both have the same, correct datum) :

# total amount = 21000000 (contract) + 13000000 (contract) + 1021470 (ben token) - 966660 (fee) = 34054810

cardano-cli transaction build-raw
  --babbage-era
  --protocol-params-file protocol-parameters.json
  --tx-in "714d2e⋯dea7cb#0"                    # utxo with ben's token
  --tx-in "347def⋯58e2c7#0"                    # first utxo of contract
  --tx-in "dca3bc⋯b80ae8#0"                    # second utxo of contract
  --tx-in-datum-file datum.json
  --tx-in-redeemer-file redeemer.json
  --tx-in-script-file tokencheck.json
  --tx-in-collateral "714d2e⋯dea7cb#1"
  --required-signer ben.skey
  --tx-out "addr_test1v⋯qarpt4 + 34054810 + 1 2d99fb⋯63d3a1.62656e"
  --fee 966660
  --tx-in-execution-units '(3000000000,7000000)'
  --out-file tx_raw.json

This fails when submitting, with error message:

Command failed: transaction submit  Error: Error while submitting tx: ShelleyTxValidationError 
ShelleyBasedEraBabbage (ApplyTxError 
[UtxowFailure( 
  FromAlonzoUtxowFail 
    (MissingRedeemers [(Spending (TxIn (TxId {_unTxId = SafeHash "347def⋯58e2c7"}) (
        TxIx 0)),ScriptHash "5c2d3c⋯7d947b")])),
UtxowFailure (
  UtxoFailure (FromAlonzoUtxoFail (UtxosFailure (CollectErrors
    [NoRedeemer (Spending (TxIn (TxId {_unTxId = SafeHash "347def⋯58e2c7"}) (TxIx 0)))])))
    )
])

If Ben just withdraws using only ONE of the contract's utxo's, the transaction succeeds:

# total amount = 21000000 + 1021470 - 953284 = 21068186

cardano-cli transaction build-raw
  --babbage-era
  --protocol-params-file protocol-parameters.json
  --tx-in "714d2e⋯dea7cb#0"                    # utxo with ben's token
  --tx-in "347def⋯58e2c7#0"                    # one utxo of contract
  --tx-in-datum-file datum.json
  --tx-in-redeemer-file redeemer.json
  --tx-in-script-file tokencheck.json
  --tx-in-collateral "714d2e⋯dea7cb#1"
  --required-signer ben.skey
  --tx-out "addr_test1v⋯qarpt4 + 21068186 + 1 2d99fb⋯63d3a1.62656e"
  --fee 953284
  --tx-in-execution-units '(3000000000,7000000)'
  --out-file tx_raw.json

Transaction successfully submitted.

Question: why does the first transaction fail while the second succeeds?

Update

Here's the contract, it's written in Helios:

struct Datum {
    donor:        PubKeyHash
    beneficiary:  PubKeyHash
    policy:       MintingPolicyHash
}

func main(datum: Datum, ctx: ScriptContext) -> Bool {
    tx: Tx = ctx.tx;
    if (tx.is_signed_by(datum.donor)) {
        true
    } else { 
        if ( tx.value_sent_to(datum.beneficiary).get(AssetClass::new(datum.policy, #62656e)) == 1) { 
            true
        } else {
            print("computer says no"); false
        }
    }
}
3
  • Does contract only allows one input utxo that requires script to be consumed per transaction? Can you check or share the contract code too.
    – nabin
    Nov 22, 2022 at 9:46
  • Contract added to the text above. I don't think the problem is with the contract's code, because it would give a different error.
    – wmoco_6725
    Nov 22, 2022 at 13:00
  • Yeah i see. Could it be due to build-raw requiring tx-in-script-file, datum redeemer for each input. I think it can be repeated and order matters. You can try that but not sure if it automatically uses same script, datum, redeemer for two inputs.
    – nabin
    Nov 22, 2022 at 14:48

1 Answer 1

2

The solution is, as Nabin suggested, to repeat after each contract-utxo the datum/redeemer/script and execution units arguments as shown here:

cardano-cli transaction build-raw
  --babbage-era      
  --protocol-params-file protocol-parameters.json
  --tx-in "344b8c⋯a3325e#0"                     # utxo with ben's token
  --tx-in "9b7697⋯dbb2e4#0"                     # contract utxo #1
  --tx-in-datum-file datum.json
  --tx-in-redeemer-file redeemer.json  
  --tx-in-script-file tokencheck.json
  --tx-in-execution-units '(3000000000,7000000)'
  --tx-in "f44eee⋯db6906#0"                     # contract utxo #2
  --tx-in-datum-file datum.json
  --tx-in-redeemer-file redeemer.json  
  --tx-in-script-file tokencheck.json
  --tx-in-execution-units '(3000000000,7000000)'
  --tx-in-collateral "344b8c⋯a3325e#1"
  --required-signer ben.skey
  --tx-out "addr_test1v⋯qarpt4 + 33323655 + 1 2d99fb⋯63d3a1.62656e"  
  --fee 1697815
  --out-file tx_raw.json

Transaction successfully submitted.

1
  • Indeed: datum/redeemer and script need to be specified for each utxo separately Nov 30, 2022 at 16:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.