user4677: 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

user5085: 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


4677: <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>
 5085: <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>
