Min-ada-value calculation

Why is it so difficult to explain the min-ada-value calculation?

I’m looking at two documents:

https://cardano-ledger.readthedocs.io/en/latest/explanations/min-utxo-mary.html

Both documents end with sample calculations that look like this:
One policyID, no asset names
6 + FLOOR (((1 * 12) + 0 + (1 * 28) + 7) / 8) = 11

No explanation what 6 and 7 are and it’s no quite clear what 3 other components inside FLOOR are. The expectation is that an app developer will deduct how to calculate the length of the native token portion for any given UTxO.

Am I missing more clear explanation somewhere?
If not, can somebody show the calculation for this case:
a policy A with no token name + a policy B with a token name ‘43484f43’ + a policy B with a token name ‘524245525259’

Maybe more cases will help me to deduce the calculation algorithm.

Thanks!

Things are much clearer in the morning. The constant 6 is still a mystery to me. The constant 7 makes sense as we rounding UP. The rest of the formula components are actually well described in that second document at Min-Ada-Value Requirement — Cardano Ledger 1.0.0 documentation

Case closed.

I suspect the k1 constant of 6 is the byte size of the utxo header necessary to bundle native tokens …

However I found no explanation in documentation, code, or even the formal spec to back up my theory. It could also be arbitrary :wink:

It’s 6 words, 48 bytes. Yes, let’s file it under A(rbitrary). I can live with that.

I’ve written a series of shell scripts to mint tokens, he’s the excerpt that calcultates min-ada-value:

# CONSTANTS
utxoEntrySizeWithoutVal=27
coinSize=2
adaOnlyUTxOSize=$((utxoEntrySizeWithoutVal+coinSize))
pidSize=28
numPIDs=1
numAssets=1
minUTxOValue=1000000
#########

assetName="$1"
sumAssetNameLengths=${#assetName}

quot(){
    local a=$1
    local b=$2
    echo $((a/b))
}

roundUpBytesToWords(){
    local b="$1"
    quot $((b+7)) 8
}

size=$(( 6 + \
	$(roundUpBytesToWords \
		$(( \
			$numAssets \
			* 12 \
			+ $sumAssetNameLengths \
			+ $numPIDs \
			* $pidSize \
		)) \
	) \
))
minimum_ada_value=$(echo -ne "$minUTxOValue\n \
	$(( \
		$(quot $minUTxOValue $adaOnlyUTxOSize) \
		* ($utxoEntrySizeWithoutVal+$size) \
	))" \
	| sort -n \
	| tail -1)
echo "Minimum Ada Value: $minimum_ada_value"

Note: this assumes every policy Id would have 28 bytes

Thank you for posting this. Could you please point to the doc that says to use coinSize=2? The docs I read are saying that it will change to 2 in some future implementation. I guess the future has arrived.

In my implementation i’m not using neither coinSize nor minUTxOValue. Once you know the size of the token bundle, the min amount is (utxoEntrySizeWithoutVal + bundle size) * utxoCostPerWord. The utxoCostPerWord is a protocol parameter.

By the way, doing this in a shell script is not super convenient. Consider this UTxO, where you would need to iterate over the assets to estimate the formula variables:

e38cae2c4e5f554c2d045bedaeb1c9684d6e0ddfd3ab533ce167b78076e7d7dd 1 1655136 lovelace + 10000000 57fca08abbaddee36da742a839f7d83a7e1d2419f1507fcbf3916522.43484f43 + 5000000000 57fca08abbaddee36da742a839f7d83a7e1d2419f1507fcbf3916522.4d494e54 + 1000000000 57fca08abbaddee36da742a839f7d83a7e1d2419f1507fcbf3916522.524245525259 + 2000000000 57fca08abbaddee36da742a839f7d83a7e1d2419f1507fcbf3916522.534245525259 + 15000000 57fca08abbaddee36da742a839f7d83a7e1d2419f1507fcbf3916522.56414e494c + TxOutDatumNone

The combination of node.js and cardanocli-js works very well for me.

Use whatever language you please as this part is always calculated off chain anyway. My minFeeAdaCalc function is in C++ currently. Note: It does not need to be exact. The operative keyword here is “minimum” so whatever function you roll could include a fudge factor then you just refund the unspent back to the input address as an additional output :wink: