# What's wrong with my calculation of fees and burn here?

I am trying to calculate the cost of a transaction, post-hoc, from the response to calling the entrypoint. This is for the purposes of a testing tool I am building that I need accurate costs for.

As an example, I have the following information about the call I have just made from a call response:

res:  {
operation_hash: 'op36m7td8UXUvCCUpZ72Xy3XLbU6pFf1VLF5y7cE6Rmb5qe7LNs',
storage_size: 24698,
consumed_gas: 15045.615,
paid_storage_size_diff: 96,
events: [],
}

I found a guide for calcuating cost from fees and burn. It includes this formula which seems fairly straightforward:

total_cost = burn + fees + amount of tez

burn = storage_difference * MINIMAL_FEE_PER_STORAGE_BYTE_MUTEZ

fees >= MINIMAL_FEE_MUTEZ +
MINIMAL_FEE_PER_BYTE_MUTEZ * size +
MINIMAL_FEE_PER_GAS_MUTEZ * gas

in practice:

fees in mutez >= 100 +
1 * size +
0.1 * gas

However, when I calculate the cost with the following formula:

function get_cost(
storage_difference: number = res.paid_storage_size_diff,
gas_use: number = res.consumed_gas,
bytes_size: number = res.storage_size,
) : BigNumber {
const fees = bytes_size + (gas_used*0.1)
const burn = storage_difference*1000
return new BigNumber(fees + burn)
}

Plugging in the response output from above, I get a cost of 114292.6447 mutez (the decimal places are another issue, as I believe mutez should be an integer. I guess I'm just meant to round them?)

However, I know from looking at the actual delta that true cost of calling this entrypoint in mockup mode is only 26028 mutez.

Please help me to understand what is wrong with my approach, and how (if) I can calculate the cost from the information I have.

Help greatly appreciated

## EDIT

Thanks to @Groxan I now have the following formula:

function get_cost(
storage_difference: number = res.paid_storage_size_diff,
gas_used: number = res.consumed_gas,
bytes_size: number = res.storage_size,
) : BigNumber {
const fees = 100 + bytes_size + (gas_used*0.1)
const burn = storage_difference*250
return new BigNumber(fees + burn).integerValue(BigNumber.ROUND_UP)
}

This is much closer, but it is still giving me an answer that is a bit over twice the observable cost. This function predicts the cost should have been 50203 mutez. (vs the observed 26028)

Is there a different calculation or set of constants in use for the mockup mode?

Any ideas? Thanks all

You need to multiply paid_storage_size_diff by 250, instead of 1000, because according to the current procotol constants cost per byte is 0.000250 tez. Also, don't forget to add +100 in the fees calculation, according to the formula you mentioned above ;) And yes, mutez must be an integer, so just round it up.

• Thanks this was a great help and I've made some changes accordingly (see my updated question). I'm still off the mark by a factor of 2 and a bit. Any thoughts?
– Grum
Mar 1, 2023 at 0:01
• @Grum it seems you use storage_size as bytes_size, which is wrong, because bytes_size is a length of the forged operation bytes - bytes that you post to the /inject RPC endpoint Mar 1, 2023 at 12:16
• Thanks - this sounds like it will be the problem as I am using storage_size as bytes_size, but I admit I don't have enough context to understand what to do next - but this gives me a good clue to research from
– Grum
Mar 2, 2023 at 0:31

What bytes_size value are you using ? you don't show it in your example, that would help figuring it out. Note that it is the size of the transaction in bytes.

• I am using storage_size from the response for the bytes_size. @Groxan has helpfully pointed out that this is wrong. Unfortunately I have poor fundamentals and do not understand what value I should be using instead (I do not understand @Groxan's comment about /inject etc at this point). Can I get the value I need from the response somehow?
– Grum
Mar 2, 2023 at 0:44
• Code example below. Mar 2, 2023 at 15:25

Here is how to compute operation size (with Taquito):

import { LocalForger } from "@taquito/local-forging";
import { InMemorySigner } from '@taquito/signer'
import { OperationContents, OperationContentsTransaction, OpKind } from '@taquito/rpc';

async function compute_op_size() {
const transaction: OperationContentsTransaction = {
"kind": OpKind.TRANSACTION,
"source": "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb",
"fee": "388",
"counter": "72035",
"gas_limit": "1304",
"storage_limit": "0",
"amount": "0",
"destination": "KT1Vrag7PFbjAmbmCJ9sAzYKxYkzvsqrUNEv",
"parameters": {
"entrypoint": "default",
"value": {
"int": "4"
}
}
};

const local_forge = new LocalForger();
const opContents: OperationContents[] = [transaction];

const forge_param = {
branch: "BLk3XprVitY86JimhijByZXcctLvsfkBmH16juNayRJbs3uHYbc",
contents: opContents
}

const op_bytes: string = await local_forge.forge(forge_param);

const signer = new InMemorySigner("edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq")
const op_sign = await signer.sign(op_bytes)
console.log(`opSize: \${op_sign.sbytes.length / 2}`)
}

compute_op_size()

It prints 157 when executed.

• Thanks for this answer, but it seems that one of the inputs required to find the operation size in the example above is the transaction fee (In OperationContentsTransaction), which is the value I am trying to find. Also, I am trying to get the fee as part of testing, and I guess it is not possible to get a meaningful block hash in mockup mode (?)
– Grum
Apr 27, 2023 at 3:37
• The point here is that 388 and BLk3XprVitY86JimhijByZXcctLvsfkBmH16juNayRJbs3uHYbc values are FAKE values just used to estimate the size in bytes of the transaction ... you can even keep theses values in your test if you want Apr 28, 2023 at 5:53