<p>There are multiple ways to do that.</p>
<p><strong>Option 1:</strong></p>
<p>If you have <em>&quot;script-wide&quot;</em> constants, like your mentioned example of an auction house fee, I suggest parameterizing your contract like it is done in <a href="https://github.com/input-output-hk/plutus-pioneer-program/blob/main/code/week03/src/Week03/Parameterized.hs" rel="nofollow noreferrer">Lecture #3</a> instead of storing that value in each output's datum.</p>
<p><strong>Option 2:</strong></p>
<p>If you really want to ensure some or all of the datum fields are recreated when it is consumed you can do that too. By default for any spending transaction from a script, Plutus expects you to provide the datum value/file whose hash matches the one stored on-chain for the UTxO you're trying to spend in your transaction.</p>
<p>Your validator can check for an output recreated at its own address with a certain value and datum. If the datum shall be the exact same as previously you can simply check if the hash of the newly created output equals the one you're consuming.</p>
<p>Otherwise, you can also provide the datum (not the hash) of the newly created output in the transaction and validate it within the script. You can do that via the CLI by using:</p>
<pre><code>--tx-out ADDRESS VALUE
[--tx-out-datum-embed-file FILE | --tx-out-datum-embed-value JSON VALUE]
</code></pre>
<p>or using <a href="https://github.com/Emurgo/cardano-serialization-lib" rel="nofollow noreferrer">CSL</a>:</p>
<pre><code>[...]
TransactionOutputBuilder.new()
    .with_address(yourScriptAddress)
    .with_data_hash(hashOfYourNewDatum) // does not include the datum value
    .next()
    .with_value(Value.new(someOutputValueOrMinADA))
    .build()

// Adding transaction datum values
// Must at least include a datum value for every script output that is being 
// spent + optionally any additional datums necessary for the script validation
const datums = PlutusList.new();
datums.add(datumBuilder(1));
datums.add(datumBuilder(2));

const transactionWitnessSet = TransactionWitnessSet.new();
transactionWitnessSet.set_plutus_data(datums);
[...]

export const datumBuilder(n: number): PlutusData {
    const fields = PlutusList.new();
      fields.add(PlutusData.new_integer(BigInt.from_str(`${n}`)));
      return PlutusData.new_constr_plutus_data(
          ConstrPlutusData.new(
            BigNum.from_str('0'),
            fields
          )
        );
}

</code></pre>
<p>Once, you've added the datum value of the newly created script output to the transaction you can retrieve it in your Plutus code like similarly to any other datum:</p>
<pre><code>[...]
where
    -- returns new outputs of this script
    ownOutputs :: [TxOut]
    ownOutputs = getContinuingOutputs ctx

    -- returns Datum value for a tx output if it is provided
    outputDatum :: TxOut -&gt; Maybe Datum
    outputDatum o = txOutDatumHash o &gt;&gt;= flip findDatum info

</code></pre>
<p>Related answers to that topic:</p>
<ul>
<li><a href="https://forum.cardano.org/t/on-datums-and-or-metadata-in-transactions/81924" rel="nofollow noreferrer">Post 1</a></li>
</ul>

CC BY-SA 4.0
2022-07-23T08:40:47.717Z
2022-07-23T08:40:47.717Z
Will
<p>I am trying to figure out how to write a script where you can make sure the datum value doesn't change each time an output gets consumed. For example, in the auction script in the pioneer program each step along the way someone wants to consume a previous output to up the bid. Suppose you wanted to store some meta deta in the datum and have it carried on the block chain, like a secondary beneficiary, imagine an auction house fee that gets set when the action is created.</p>
<p>Each end point supplies the the datum to be set as the output of the transaction. The endpoint code runs off chain. So it seems that there is no way to set a static datum value, especially for any script which allows the public to access, like an auction.</p>
<p>Is my understanding correct and this is just a limitation of the cardano smart contract?</p>
<p>Thank you in advance</p>

CC BY-SA 4.0
2022-01-14T07:02:01.120Z
I have a very similar question that could be answered by answering your question. I would be keen to see an answer to your question.
FTM
CC BY-SA 4.0
2022-01-14T14:11:51.127Z
In the on-chain validator script, you can inspect the transaction outputs through the `ScriptContext`. An output has a datum hash field available. You can then assert that the hash is equal to the hash of the input datum. Ref: https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/Plutus-V1-Ledger-Contexts.html#t:TxOut
Jaanus Varus
<plutus><plutustx><datum>
How can I secure a Datum value in a smart contract?
# How can I secure a Datum value in a smart contract?

(Asked by: username_0 on 2021-11-27)

I am trying to figure out how to write a script where you can make sure the datum value doesn't change each time an output gets consumed. For example, in the auction script in the pioneer program each step along the way someone wants to consume a previous output to up the bid. Suppose you wanted to store some meta deta in the datum and have it carried on the block chain, like a secondary beneficiary, imagine an auction house fee that gets set when the action is created.

Each end point supplies the the datum to be set as the output of the transaction. The endpoint code runs off chain. So it seems that there is no way to set a static datum value, especially for any script which allows the public to access, like an auction.

Is my understanding correct and this is just a limitation of the cardano smart contract?

Thank you in advance

**Tags:** plutus, plutustx, datum
> **Comments:**
> **username_1**: I have a very similar question that could be answered by answering your question. I would be keen to see an answer to your question.  
> **username_2**: In the on-chain validator script, you can inspect the transaction outputs through the `ScriptContext`. An output has a datum hash field available. You can then assert that the hash is equal to the hash of the input datum. Ref: https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/Plutus-V1-Ledger-Contexts.html#t:TxOut  

---

## 1 answers

### Answer by username_3 on 2022-07-23. Score: 3

There are multiple ways to do that.
Option 1:
If you have "script-wide" constants, like your mentioned example of an auction house fee, I suggest parameterizing your contract like it is done in Lecture #3 instead of storing that value in each output's datum.
Option 2:
If you really want to ensure some or all of the datum fields are recreated when it is consumed you can do that too. By default for any spending transaction from a script, Plutus expects you to provide the datum value/file whose hash matches the one stored on-chain for the UTxO you're trying to spend in your transaction.
Your validator can check for an output recreated at its own address with a certain value and datum. If the datum shall be the exact same as previously you can simply check if the hash of the newly created output equals the one you're consuming.
Otherwise, you can also provide the datum (not the hash) of the newly created output in the transaction and validate it within the script. You can do that via the CLI by using:
--tx-out ADDRESS VALUE
[--tx-out-datum-embed-file FILE | --tx-out-datum-embed-value JSON VALUE]

or using CSL:
[...]
TransactionOutputBuilder.new()
    .with_address(yourScriptAddress)
    .with_data_hash(hashOfYourNewDatum) // does not include the datum value
    .next()
    .with_value(Value.new(someOutputValueOrMinADA))
    .build()

// Adding transaction datum values
// Must at least include a datum value for every script output that is being 
// spent + optionally any additional datums necessary for the script validation
const datums = PlutusList.new();
datums.add(datumBuilder(1));
datums.add(datumBuilder(2));

const transactionWitnessSet = TransactionWitnessSet.new();
transactionWitnessSet.set_plutus_data(datums);
[...]

export const datumBuilder(n: number): PlutusData {
    const fields = PlutusList.new();
      fields.add(PlutusData.new_integer(BigInt.from_str(`${n}`)));
      return PlutusData.new_constr_plutus_data(
          ConstrPlutusData.new(
            BigNum.from_str('0'),
            fields
          )
        );
}


Once, you've added the datum value of the newly created script output to the transaction you can retrieve it in your Plutus code like similarly to any other datum:
[...]
where
    -- returns new outputs of this script
    ownOutputs :: [TxOut]
    ownOutputs = getContinuingOutputs ctx

    -- returns Datum value for a tx output if it is provided
    outputDatum :: TxOut -> Maybe Datum
    outputDatum o = txOutDatumHash o >>= flip findDatum info


Related answers to that topic:

Post 1


---

