use num_rational::Rational;
use serde::{Deserialize, Serialize};
pub type Gas = u64;
#[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
pub struct Fee {
pub send_sir: Gas,
pub send_not_sir: Gas,
pub execution: Gas,
}
impl Fee {
#[inline]
pub fn send_fee(&self, sir: bool) -> Gas {
if sir {
self.send_sir
} else {
self.send_not_sir
}
}
pub fn exec_fee(&self) -> Gas {
self.execution
}
fn min_send_and_exec_fee(&self) -> Gas {
std::cmp::min(self.send_sir, self.send_not_sir) + self.execution
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
pub struct RuntimeFeesConfig {
pub action_receipt_creation_config: Fee,
pub data_receipt_creation_config: DataReceiptCreationConfig,
pub action_creation_config: ActionCreationConfig,
pub storage_usage_config: StorageUsageConfig,
pub burnt_gas_reward: Rational,
pub pessimistic_gas_price_inflation_ratio: Rational,
}
#[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
pub struct DataReceiptCreationConfig {
pub base_cost: Fee,
pub cost_per_byte: Fee,
}
#[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
pub struct ActionCreationConfig {
pub create_account_cost: Fee,
pub deploy_contract_cost: Fee,
pub deploy_contract_cost_per_byte: Fee,
pub function_call_cost: Fee,
pub function_call_cost_per_byte: Fee,
pub transfer_cost: Fee,
pub stake_cost: Fee,
pub add_key_cost: AccessKeyCreationConfig,
pub delete_key_cost: Fee,
pub delete_account_cost: Fee,
}
#[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
pub struct AccessKeyCreationConfig {
pub full_access_cost: Fee,
pub function_call_cost: Fee,
pub function_call_cost_per_byte: Fee,
}
#[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
pub struct StorageUsageConfig {
pub num_bytes_account: u64,
pub num_extra_bytes_record: u64,
}
impl Default for RuntimeFeesConfig {
fn default() -> Self {
#[allow(clippy::unreadable_literal)]
Self {
action_receipt_creation_config: Fee {
send_sir: 108059500000,
send_not_sir: 108059500000,
execution: 108059500000,
},
data_receipt_creation_config: DataReceiptCreationConfig {
base_cost: Fee {
send_sir: 4697339419375,
send_not_sir: 4697339419375,
execution: 4697339419375,
},
cost_per_byte: Fee {
send_sir: 59357464,
send_not_sir: 59357464,
execution: 59357464,
},
},
action_creation_config: ActionCreationConfig {
create_account_cost: Fee {
send_sir: 99607375000,
send_not_sir: 99607375000,
execution: 99607375000,
},
deploy_contract_cost: Fee {
send_sir: 184765750000,
send_not_sir: 184765750000,
execution: 184765750000,
},
deploy_contract_cost_per_byte: Fee {
send_sir: 6812999,
send_not_sir: 6812999,
execution: 6812999,
},
function_call_cost: Fee {
send_sir: 2319861500000,
send_not_sir: 2319861500000,
execution: 2319861500000,
},
function_call_cost_per_byte: Fee {
send_sir: 2235934,
send_not_sir: 2235934,
execution: 2235934,
},
transfer_cost: Fee {
send_sir: 115123062500,
send_not_sir: 115123062500,
execution: 115123062500,
},
stake_cost: Fee {
send_sir: 141715687500,
send_not_sir: 141715687500,
execution: 102217625000,
},
add_key_cost: AccessKeyCreationConfig {
full_access_cost: Fee {
send_sir: 101765125000,
send_not_sir: 101765125000,
execution: 101765125000,
},
function_call_cost: Fee {
send_sir: 102217625000,
send_not_sir: 102217625000,
execution: 102217625000,
},
function_call_cost_per_byte: Fee {
send_sir: 1925331,
send_not_sir: 1925331,
execution: 1925331,
},
},
delete_key_cost: Fee {
send_sir: 94946625000,
send_not_sir: 94946625000,
execution: 94946625000,
},
delete_account_cost: Fee {
send_sir: 147489000000,
send_not_sir: 147489000000,
execution: 147489000000,
},
},
storage_usage_config: StorageUsageConfig {
num_bytes_account: 100,
num_extra_bytes_record: 40,
},
burnt_gas_reward: Rational::new(3, 10),
pessimistic_gas_price_inflation_ratio: Rational::new(103, 100),
}
}
}
impl RuntimeFeesConfig {
pub fn free() -> Self {
let free = Fee { send_sir: 0, send_not_sir: 0, execution: 0 };
RuntimeFeesConfig {
action_receipt_creation_config: free.clone(),
data_receipt_creation_config: DataReceiptCreationConfig {
base_cost: free.clone(),
cost_per_byte: free.clone(),
},
action_creation_config: ActionCreationConfig {
create_account_cost: free.clone(),
deploy_contract_cost: free.clone(),
deploy_contract_cost_per_byte: free.clone(),
function_call_cost: free.clone(),
function_call_cost_per_byte: free.clone(),
transfer_cost: free.clone(),
stake_cost: free.clone(),
add_key_cost: AccessKeyCreationConfig {
full_access_cost: free.clone(),
function_call_cost: free.clone(),
function_call_cost_per_byte: free.clone(),
},
delete_key_cost: free.clone(),
delete_account_cost: free,
},
storage_usage_config: StorageUsageConfig {
num_bytes_account: 0,
num_extra_bytes_record: 0,
},
burnt_gas_reward: Rational::from_integer(0),
pessimistic_gas_price_inflation_ratio: Rational::from_integer(0),
}
}
pub fn min_receipt_with_function_call_gas(&self) -> Gas {
self.action_receipt_creation_config.min_send_and_exec_fee()
+ self.action_creation_config.function_call_cost.min_send_and_exec_fee()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_data_roundtrip_is_more_expensive() {
let transaction_costs = RuntimeFeesConfig::default();
assert!(
transaction_costs.data_receipt_creation_config.base_cost.min_send_and_exec_fee()
>= transaction_costs.min_receipt_with_function_call_gas(),
"The data receipt cost can't be larger than the cost of a receipt with a function call"
);
}
}