# Manual Calculation of Transaction Size and Fee

I realize that the CLI has commands for calculating a minimum fee based on a transaction size, but I'm wanting to do a calculation manually. The documentation states that the formula for calculating the transaction minimum fee is `a * size(tx) + b` where `a` & `b` are protocol parameters, and `size(tx)` is the transaction size in bytes.

Is there a way to calculate the transaction size if I know the number of consumed and output UTxOs? Also, are `a` and `b` in the genesis file?

there are two options that do come to my mind to calculate a transaction size:

## starting from the fees

since we know that the fees are calulated as `a * size(tx) + b == fees` using some simple algebra we can see that `size(tx) == (fees - b) / a`

this should be the most reliable way, but you need the fees in order to calculate the size, so it shouldn't fit you request

## use the CBOR size

when builing a transaction using either `cardano-cli transaction build` or `cardano-cli transaction build-raw` you need to specify an `--out-file` which turns out to be a `.json` file with the following chema:

``````{
"type": "Tx AlonzoEra",
"description": "",
"cborHex": "<some hex value>"
}
``````

ultimately the `cborHex` value is what goes on-chain that value is an hexadecimal string and represents the bytes of the CBOR message

since we know that each byte can have a value from `0` to `255` the hex representation must take 2 hexadecimal digits per byte

this way you could calculate the tx size in bytes as half the length of the cborHex string

in nodejs

``````"<some hex value>".length / 2
``````

however, this approach returns usually a value smaller by ~400/~500 bytes in contrast to the first approach, so I might be missing some data

#### P.S. `cardano-serialization-library`

using the `cardano-serialization-library` it should be enough to use the `Transaction.to_bytes()` method and get the length

e.g.

``````myTx.to_bytes().length
``````

Here is my bash script

``````fee=\$(cardano-cli transaction calculate-min-fee \
--tx-body-file tx.tmp \
--tx-in-count 1 \
--tx-out-count 1 \
--mainnet \
--witness-count 1 \
--byron-witness-count 0 \
--protocol-params-file protocol.json | awk '{ print \$1 }') >> \$log
``````

In your case, it depends how many TX_in and TX_outs you will have.

• tx.tmp will create it by : cardano-cli transaction build-raw \ --fee 200000 \ --tx-in \${tx_in} \ --tx-out \${in_addr}+\${utxo_balance} \ --invalid-hereafter \$(( \${currentSlot} + 2000)) \ --out-file tx.tmp >> \$log Jan 26, 2022 at 6:25

The `a` and `b` fees parameters are protocol parameters, so you should probably check the current epoch, even they are unlikely to change suddenly.

``````\$ curl -s  -H "project_id: \$BLOCKFROST_PROJECT_ID" https://cardano-mainnet.blockfrost.io/api/v0/epochs/latest/parameters | jq '. | .min_fee_a, .min_fee_b'
44
155381
``````

Then, all your need to do to calculate your fees is:

``````a × size (in bytes) + b
``````

Read more on docs.cardano.org.

• To get the exact size in bytes, you're going to want to build the transaction and include a dummy value for the fee even though you don't know it yet. Then you can get the exact number of bytes the transaction will take instead of doing estimates based on UTxO counts and such. Then, just calculate as @Marek showed and re-build the Tx a second time with the exact fees. Aug 30, 2021 at 20:04
• Thanks, you've both been helpful. I guess I probably also wasn't perfectly clear. I'm trying to figure out how to get the `size(tx)` value. I was wandering if I could do it without the CLI? I'm assuming its not the size of the ASCII characters in bytes but formatted differently. I couldn't find the exact info in the docs (although I'm sure its there somewhere). Aug 30, 2021 at 23:18
• Thanks Marek, I forgot to check the protocol parameters file. I was looking in the genesis files but of course it can change! Aug 31, 2021 at 2:41
• @nalyd88 The only way to get the size of the transaction without using cardano-cli is to build the cbor for everything yourself. I do this with my firehose project, but it's quite involved. Even cardano-cli doesn't give you exactly the minfee value. It just does a best guess estimate and pads it a bit. Things like stake vs enterprise output addresses can change the size of cbor and affect fees. Sep 22, 2021 at 12:55

The correct formula for non-smart contract transactions is indeed still `a*size(tx) + b`, with `a=44` and `b=155381`.

`size(tx)` is calculated as the number of bytes of the CBOR encoding of the transaction, which can differ per era. For example Babbage introduced a new way of encoding transaction outputs, which results in slightly larger transactions. The old way of encoding transaction outputs is however still permitted because it is a bit smaller, so `size(tx)` can differ depending on what tool/wallet created the transaction.

#### cardano-cli

Getting exactly the same result as cardano-cli is sadly not straightforward because it has a few quirks:

• the `isValid` byte is omitted when calculating `size(tx)` (which IOG claims is to stay consistent with the Mary era)
• if the fee is being calculated during tx building, then for each regular input, collateral input, required native script signature, and plutus script signature, a dummy pub key and signature is added (96 bytes + encoding overhead). This is usually an overestimation because many of the required signatures will be the same.

You can quite easily calculate the max number of potential signatures, but the CBOR encoding overhead is difficult to estimate manually (I don't recommend you even try without an appropriate library/framework):

``````size(tx) = size(tx_without_signatures)
+ num_signatures*(96 + cbor_overhead_per_signature)
If the estimated number of signatures equals the actual number of signatures, and you used the actual on-chain size of the transaction as `size(tx)`, you will probably just be off by 1 byte, i.e. `44` lovelace difference wrt. the cardano-cli result.
Disclaimer: this is how cardano-cli works internally as far as I'm currently aware, but this is subject to change (e.g. a more accurate estimation of the number of signatures is marked as `TODO` in the IOG codebase).