whisky_pallas/utils/
fee.rs1use pallas::ledger::primitives::Fragment;
2use whisky_common::{Protocol, WError};
3
4use crate::wrapper::transaction_body::Transaction;
5
6pub fn calculate_fee(
7 transaction: Transaction,
8 script_size: usize,
9 protocol_params: Protocol,
10) -> Result<u64, WError> {
11 let witness_set = &transaction.inner.transaction_witness_set;
12 let fee = protocol_params.min_fee_b
13 + transaction
14 .inner
15 .encode_fragment()
16 .map_err(|_| {
17 WError::new(
18 "Calculating Fee - ",
19 "Error while serializing TransactionBody",
20 )
21 })?
22 .len() as u64
23 * protocol_params.min_fee_a;
24 let script_ref_fee = calculate_script_ref_fee(
25 script_size,
26 protocol_params.min_fee_ref_script_cost_per_byte,
27 );
28 let Some(redeemers) = &witness_set.redeemer else {
29 return Ok(fee + script_ref_fee);
30 };
31 let script_fee = match redeemers.clone().unwrap() {
32 pallas::ledger::primitives::conway::Redeemers::List(redeemers) => {
33 let mut script_fee: f64 = 0.0;
34 for redeemer in redeemers {
35 let mem_units = redeemer.ex_units.mem;
36 let step_units = redeemer.ex_units.steps;
37 script_fee += mem_units as f64 * protocol_params.price_mem;
38 script_fee += step_units as f64 * protocol_params.price_step;
39 }
40 script_fee.ceil() as u64
41 }
42 pallas::ledger::primitives::conway::Redeemers::Map(btree_map) => {
43 let mut script_fee: f64 = 0.0;
44 for (_, redeemer) in btree_map {
45 let mem_units = redeemer.ex_units.mem;
46 let step_units = redeemer.ex_units.steps;
47 script_fee += mem_units as f64 * protocol_params.price_mem;
48 script_fee += step_units as f64 * protocol_params.price_step;
49 }
50 script_fee.ceil() as u64
51 }
52 };
53 Ok(fee + script_fee + script_ref_fee)
54}
55
56fn calculate_script_ref_fee(script_size: usize, min_fee_ref_script_cost_per_byte: u64) -> u64 {
57 let mut script_fee: f64 = 0.0;
58 const TIER_SIZE: u64 = 25600;
59 const TIER_MULTIPLIER: f64 = 1.2;
60
61 let mut current_multiplier: f64 = 1.0;
62 let mut remaining_size = script_size as u64;
63 while remaining_size >= TIER_SIZE {
64 script_fee +=
65 TIER_SIZE as f64 * current_multiplier * min_fee_ref_script_cost_per_byte as f64;
66 remaining_size -= TIER_SIZE;
67 current_multiplier *= TIER_MULTIPLIER;
68 }
69 if remaining_size > 0 {
70 script_fee +=
71 remaining_size as f64 * current_multiplier * min_fee_ref_script_cost_per_byte as f64;
72 }
73 script_fee.ceil() as u64
74}