near_parameters/
cost.rs

1use crate::parameter::Parameter;
2use enum_map::{EnumMap, enum_map};
3use near_account_id::AccountType;
4use near_primitives_core::types::{Balance, Compute, Gas};
5use near_schema_checker_lib::ProtocolSchema;
6use num_rational::Rational32;
7
8/// Costs associated with an object that can only be sent over the network (and executed
9/// by the receiver).
10/// NOTE: `send_sir` or `send_not_sir` fees are usually burned when the item is being created.
11/// And `execution` fee is burned when the item is being executed.
12#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Hash, PartialEq, Eq)]
13#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
14pub struct Fee {
15    /// Fee for sending an object from the sender to itself, guaranteeing that it does not leave
16    /// the shard.
17    pub send_sir: Gas,
18    /// Fee for sending an object potentially across the shards.
19    pub send_not_sir: Gas,
20    /// Fee for executing the object.
21    pub execution: Gas,
22}
23
24impl Fee {
25    pub fn new(send_sir: u64, send_not_sir: u64, execution: u64) -> Self {
26        Self {
27            send_sir: Gas::from_gas(send_sir),
28            send_not_sir: Gas::from_gas(send_not_sir),
29            execution: Gas::from_gas(execution),
30        }
31    }
32
33    #[inline]
34    pub fn send_fee(&self, sir: bool) -> Gas {
35        if sir { self.send_sir } else { self.send_not_sir }
36    }
37
38    pub fn exec_fee(&self) -> Gas {
39        self.execution
40    }
41
42    /// The minimum fee to send and execute.
43    pub fn min_send_and_exec_fee(&self) -> Gas {
44        std::cmp::min(self.send_sir, self.send_not_sir).checked_add(self.execution).unwrap()
45    }
46
47    fn test_value(value: u64) -> Self {
48        Self {
49            send_sir: Gas::from_gas(value),
50            send_not_sir: Gas::from_gas(value),
51            execution: Gas::from_gas(value),
52        }
53    }
54}
55
56#[derive(Debug, Clone, Hash, PartialEq, Eq)]
57pub struct ParameterCost {
58    pub gas: Gas,
59    pub compute: Compute,
60}
61
62#[derive(Debug, Clone, Hash, PartialEq, Eq)]
63pub struct ExtCostsConfig {
64    pub costs: EnumMap<ExtCosts, ParameterCost>,
65}
66
67// We multiply the actual computed costs by the fixed factor to ensure we
68// have certain reserve for further gas price variation.
69const SAFETY_MULTIPLIER: u64 = 3;
70
71impl ExtCostsConfig {
72    pub fn gas_cost(&self, param: ExtCosts) -> Gas {
73        self.costs[param].gas
74    }
75
76    pub fn compute_cost(&self, param: ExtCosts) -> Compute {
77        self.costs[param].compute
78    }
79
80    /// Convenience constructor to use in tests where the exact gas cost does
81    /// not need to correspond to a specific protocol version.
82    pub fn test_with_undercharging_factor(factor: u64) -> ExtCostsConfig {
83        let costs = enum_map! {
84            ExtCosts::base => SAFETY_MULTIPLIER * 88256037,
85            ExtCosts::contract_loading_base => SAFETY_MULTIPLIER * 11815321,
86            ExtCosts::contract_loading_bytes => SAFETY_MULTIPLIER * 72250,
87            ExtCosts::read_memory_base => SAFETY_MULTIPLIER * 869954400,
88            ExtCosts::read_memory_byte => SAFETY_MULTIPLIER * 1267111,
89            ExtCosts::write_memory_base => SAFETY_MULTIPLIER * 934598287,
90            ExtCosts::write_memory_byte => SAFETY_MULTIPLIER * 907924,
91            ExtCosts::read_register_base => SAFETY_MULTIPLIER * 839055062,
92            ExtCosts::read_register_byte => SAFETY_MULTIPLIER * 32854,
93            ExtCosts::write_register_base => SAFETY_MULTIPLIER * 955174162,
94            ExtCosts::write_register_byte => SAFETY_MULTIPLIER * 1267188,
95            ExtCosts::utf8_decoding_base => SAFETY_MULTIPLIER * 1037259687,
96            ExtCosts::utf8_decoding_byte => SAFETY_MULTIPLIER * 97193493,
97            ExtCosts::utf16_decoding_base => SAFETY_MULTIPLIER * 1181104350,
98            ExtCosts::utf16_decoding_byte => SAFETY_MULTIPLIER * 54525831,
99            ExtCosts::sha256_base => SAFETY_MULTIPLIER * 1513656750,
100            ExtCosts::sha256_byte => SAFETY_MULTIPLIER * 8039117,
101            ExtCosts::keccak256_base => SAFETY_MULTIPLIER * 1959830425,
102            ExtCosts::keccak256_byte => SAFETY_MULTIPLIER * 7157035,
103            ExtCosts::keccak512_base => SAFETY_MULTIPLIER * 1937129412,
104            ExtCosts::keccak512_byte => SAFETY_MULTIPLIER * 12216567,
105            ExtCosts::ripemd160_base => SAFETY_MULTIPLIER * 284558362,
106            ExtCosts::ed25519_verify_base => SAFETY_MULTIPLIER * 1513656750,
107            ExtCosts::ed25519_verify_byte => SAFETY_MULTIPLIER * 7157035,
108            ExtCosts::ripemd160_block => SAFETY_MULTIPLIER * 226702528,
109            ExtCosts::ecrecover_base => SAFETY_MULTIPLIER * 1121789875000,
110            ExtCosts::log_base => SAFETY_MULTIPLIER * 1181104350,
111            ExtCosts::log_byte => SAFETY_MULTIPLIER * 4399597,
112            ExtCosts::storage_write_base => SAFETY_MULTIPLIER * 21398912000,
113            ExtCosts::storage_write_key_byte => SAFETY_MULTIPLIER * 23494289,
114            ExtCosts::storage_write_value_byte => SAFETY_MULTIPLIER * 10339513,
115            ExtCosts::storage_write_evicted_byte => SAFETY_MULTIPLIER * 10705769,
116            ExtCosts::storage_read_base => SAFETY_MULTIPLIER * 18785615250,
117            ExtCosts::storage_read_key_byte => SAFETY_MULTIPLIER * 10317511,
118            ExtCosts::storage_read_value_byte => SAFETY_MULTIPLIER * 1870335,
119            ExtCosts::storage_large_read_overhead_base => 0,
120            ExtCosts::storage_large_read_overhead_byte => 0,
121            ExtCosts::storage_remove_base => SAFETY_MULTIPLIER * 17824343500,
122            ExtCosts::storage_remove_key_byte => SAFETY_MULTIPLIER * 12740128,
123            ExtCosts::storage_remove_ret_value_byte => SAFETY_MULTIPLIER * 3843852,
124            ExtCosts::storage_has_key_base => SAFETY_MULTIPLIER * 18013298875,
125            ExtCosts::storage_has_key_byte => SAFETY_MULTIPLIER * 10263615,
126            // Here it should be `SAFETY_MULTIPLIER * 0` for consistency, but then
127            // clippy complains with "this operation will always return zero" warning
128            ExtCosts::storage_iter_create_prefix_base => 0,
129            ExtCosts::storage_iter_create_prefix_byte => 0,
130            ExtCosts::storage_iter_create_range_base => 0,
131            ExtCosts::storage_iter_create_from_byte => 0,
132            ExtCosts::storage_iter_create_to_byte => 0,
133            ExtCosts::storage_iter_next_base => 0,
134            ExtCosts::storage_iter_next_key_byte => 0,
135            ExtCosts::storage_iter_next_value_byte => 0,
136            ExtCosts::touching_trie_node => SAFETY_MULTIPLIER * 5367318642,
137            ExtCosts::read_cached_trie_node => SAFETY_MULTIPLIER * 760_000_000,
138            ExtCosts::promise_and_base => SAFETY_MULTIPLIER * 488337800,
139            ExtCosts::promise_and_per_promise => SAFETY_MULTIPLIER * 1817392,
140            ExtCosts::promise_return => SAFETY_MULTIPLIER * 186717462,
141            ExtCosts::validator_stake_base => SAFETY_MULTIPLIER * 303944908800,
142            ExtCosts::validator_total_stake_base => SAFETY_MULTIPLIER * 303944908800,
143            ExtCosts::alt_bn128_g1_multiexp_base => 713_000_000_000,
144            ExtCosts::alt_bn128_g1_multiexp_element => 320_000_000_000,
145            ExtCosts::alt_bn128_pairing_check_base => 9_686_000_000_000,
146            ExtCosts::alt_bn128_pairing_check_element => 5_102_000_000_000,
147            ExtCosts::alt_bn128_g1_sum_base => 3_000_000_000,
148            ExtCosts::alt_bn128_g1_sum_element => 5_000_000_000,
149            ExtCosts::bls12381_p1_sum_base => SAFETY_MULTIPLIER * 5_500_000_000,
150            ExtCosts::bls12381_p1_sum_element => SAFETY_MULTIPLIER * 2_000_000_000,
151            ExtCosts::bls12381_p2_sum_base => SAFETY_MULTIPLIER * 6_200_000_000,
152            ExtCosts::bls12381_p2_sum_element => SAFETY_MULTIPLIER * 5_000_000_000,
153            ExtCosts::bls12381_g1_multiexp_base => SAFETY_MULTIPLIER * 5_500_000_000,
154            ExtCosts::bls12381_g1_multiexp_element => SAFETY_MULTIPLIER * 310_000_000_000,
155            ExtCosts::bls12381_g2_multiexp_base => SAFETY_MULTIPLIER * 6_200_000_000,
156            ExtCosts::bls12381_g2_multiexp_element => SAFETY_MULTIPLIER * 665_000_000_000,
157            ExtCosts::bls12381_map_fp_to_g1_base => SAFETY_MULTIPLIER * 500_000_000,
158            ExtCosts::bls12381_map_fp_to_g1_element => SAFETY_MULTIPLIER * 84_000_000_000,
159            ExtCosts::bls12381_map_fp2_to_g2_base => SAFETY_MULTIPLIER * 500_000_000,
160            ExtCosts::bls12381_map_fp2_to_g2_element => SAFETY_MULTIPLIER * 300_000_000_000,
161            ExtCosts::bls12381_pairing_base => SAFETY_MULTIPLIER * 710_000_000_000,
162            ExtCosts::bls12381_pairing_element => SAFETY_MULTIPLIER * 710_000_000_000,
163            ExtCosts::bls12381_p1_decompress_base => SAFETY_MULTIPLIER * 500_000_000,
164            ExtCosts::bls12381_p1_decompress_element => SAFETY_MULTIPLIER * 27_000_000_000,
165            ExtCosts::bls12381_p2_decompress_base => SAFETY_MULTIPLIER * 500_000_000,
166            ExtCosts::bls12381_p2_decompress_element => SAFETY_MULTIPLIER * 55_000_000_000,
167            // TODO(yield/resume): replicate fees here after estimation
168            ExtCosts::yield_create_base => 300_000_000_000_000,
169            ExtCosts::yield_create_byte => 300_000_000_000_000,
170            ExtCosts::yield_resume_base => 300_000_000_000_000,
171            ExtCosts::yield_resume_byte => 300_000_000_000_000,
172        }
173        .map(|_, value| ParameterCost { gas: Gas::from_gas(value), compute: value * factor });
174        ExtCostsConfig { costs }
175    }
176
177    /// `test_with_undercharging_factor` with a factor of 1.
178    pub fn test() -> ExtCostsConfig {
179        Self::test_with_undercharging_factor(1)
180    }
181}
182
183/// Strongly-typed representation of the fees for counting.
184///
185/// Do not change the enum discriminants here, they are used for borsh
186/// (de-)serialization.
187#[derive(
188    Copy,
189    Clone,
190    Hash,
191    PartialEq,
192    Eq,
193    Debug,
194    PartialOrd,
195    Ord,
196    strum::Display,
197    strum::EnumIter,
198    enum_map::Enum,
199    ProtocolSchema,
200)]
201#[allow(non_camel_case_types)]
202pub enum ExtCosts {
203    base = 0,
204    contract_loading_base = 1,
205    contract_loading_bytes = 2,
206    read_memory_base = 3,
207    read_memory_byte = 4,
208    write_memory_base = 5,
209    write_memory_byte = 6,
210    read_register_base = 7,
211    read_register_byte = 8,
212    write_register_base = 9,
213    write_register_byte = 10,
214    utf8_decoding_base = 11,
215    utf8_decoding_byte = 12,
216    utf16_decoding_base = 13,
217    utf16_decoding_byte = 14,
218    sha256_base = 15,
219    sha256_byte = 16,
220    keccak256_base = 17,
221    keccak256_byte = 18,
222    keccak512_base = 19,
223    keccak512_byte = 20,
224    ripemd160_base = 21,
225    ripemd160_block = 22,
226    ecrecover_base = 23,
227    log_base = 24,
228    log_byte = 25,
229    storage_write_base = 26,
230    storage_write_key_byte = 27,
231    storage_write_value_byte = 28,
232    storage_write_evicted_byte = 29,
233    storage_read_base = 30,
234    storage_read_key_byte = 31,
235    storage_read_value_byte = 32,
236    storage_remove_base = 33,
237    storage_remove_key_byte = 34,
238    storage_remove_ret_value_byte = 35,
239    storage_has_key_base = 36,
240    storage_has_key_byte = 37,
241    storage_iter_create_prefix_base = 38,
242    storage_iter_create_prefix_byte = 39,
243    storage_iter_create_range_base = 40,
244    storage_iter_create_from_byte = 41,
245    storage_iter_create_to_byte = 42,
246    storage_iter_next_base = 43,
247    storage_iter_next_key_byte = 44,
248    storage_iter_next_value_byte = 45,
249    touching_trie_node = 46,
250    read_cached_trie_node = 47,
251    promise_and_base = 48,
252    promise_and_per_promise = 49,
253    promise_return = 50,
254    validator_stake_base = 51,
255    validator_total_stake_base = 52,
256    alt_bn128_g1_multiexp_base = 53,
257    alt_bn128_g1_multiexp_element = 54,
258    alt_bn128_pairing_check_base = 55,
259    alt_bn128_pairing_check_element = 56,
260    alt_bn128_g1_sum_base = 57,
261    alt_bn128_g1_sum_element = 58,
262    ed25519_verify_base = 59,
263    ed25519_verify_byte = 60,
264    yield_create_base = 61,
265    yield_create_byte = 62,
266    yield_resume_base = 63,
267    yield_resume_byte = 64,
268    bls12381_p1_sum_base = 65,
269    bls12381_p1_sum_element = 66,
270    bls12381_p2_sum_base = 67,
271    bls12381_p2_sum_element = 68,
272    bls12381_g1_multiexp_base = 69,
273    bls12381_g1_multiexp_element = 70,
274    bls12381_g2_multiexp_base = 71,
275    bls12381_g2_multiexp_element = 72,
276    bls12381_map_fp_to_g1_base = 73,
277    bls12381_map_fp_to_g1_element = 74,
278    bls12381_map_fp2_to_g2_base = 75,
279    bls12381_map_fp2_to_g2_element = 76,
280    bls12381_pairing_base = 77,
281    bls12381_pairing_element = 78,
282    bls12381_p1_decompress_base = 79,
283    bls12381_p1_decompress_element = 80,
284    bls12381_p2_decompress_base = 81,
285    bls12381_p2_decompress_element = 82,
286    storage_large_read_overhead_base = 83,
287    storage_large_read_overhead_byte = 84,
288}
289
290// Type of an action, used in fees logic.
291#[derive(
292    Copy,
293    Clone,
294    Hash,
295    PartialEq,
296    Eq,
297    Debug,
298    PartialOrd,
299    Ord,
300    strum::Display,
301    strum::EnumIter,
302    enum_map::Enum,
303    ProtocolSchema,
304)]
305#[allow(non_camel_case_types)]
306pub enum ActionCosts {
307    create_account = 0,
308    delete_account = 1,
309    deploy_contract_base = 2,
310    deploy_contract_byte = 3,
311    function_call_base = 4,
312    function_call_byte = 5,
313    transfer = 6,
314    stake = 7,
315    add_full_access_key = 8,
316    add_function_call_key_base = 9,
317    add_function_call_key_byte = 10,
318    delete_key = 11,
319    new_action_receipt = 12,
320    new_data_receipt_base = 13,
321    new_data_receipt_byte = 14,
322    delegate = 15,
323    deploy_global_contract_base = 16,
324    deploy_global_contract_byte = 17,
325    use_global_contract_base = 18,
326    use_global_contract_byte = 19,
327    deterministic_state_init_base = 20,
328    deterministic_state_init_byte = 21,
329    deterministic_state_init_entry = 22,
330}
331
332impl ExtCosts {
333    pub fn gas(self, config: &ExtCostsConfig) -> Gas {
334        config.gas_cost(self)
335    }
336
337    pub fn compute(self, config: &ExtCostsConfig) -> Compute {
338        config.compute_cost(self)
339    }
340
341    pub fn param(&self) -> Parameter {
342        match self {
343            ExtCosts::base => Parameter::WasmBase,
344            ExtCosts::contract_loading_base => Parameter::WasmContractLoadingBase,
345            ExtCosts::contract_loading_bytes => Parameter::WasmContractLoadingBytes,
346            ExtCosts::read_memory_base => Parameter::WasmReadMemoryBase,
347            ExtCosts::read_memory_byte => Parameter::WasmReadMemoryByte,
348            ExtCosts::write_memory_base => Parameter::WasmWriteMemoryBase,
349            ExtCosts::write_memory_byte => Parameter::WasmWriteMemoryByte,
350            ExtCosts::read_register_base => Parameter::WasmReadRegisterBase,
351            ExtCosts::read_register_byte => Parameter::WasmReadRegisterByte,
352            ExtCosts::write_register_base => Parameter::WasmWriteRegisterBase,
353            ExtCosts::write_register_byte => Parameter::WasmWriteRegisterByte,
354            ExtCosts::utf8_decoding_base => Parameter::WasmUtf8DecodingBase,
355            ExtCosts::utf8_decoding_byte => Parameter::WasmUtf8DecodingByte,
356            ExtCosts::utf16_decoding_base => Parameter::WasmUtf16DecodingBase,
357            ExtCosts::utf16_decoding_byte => Parameter::WasmUtf16DecodingByte,
358            ExtCosts::sha256_base => Parameter::WasmSha256Base,
359            ExtCosts::sha256_byte => Parameter::WasmSha256Byte,
360            ExtCosts::keccak256_base => Parameter::WasmKeccak256Base,
361            ExtCosts::keccak256_byte => Parameter::WasmKeccak256Byte,
362            ExtCosts::keccak512_base => Parameter::WasmKeccak512Base,
363            ExtCosts::keccak512_byte => Parameter::WasmKeccak512Byte,
364            ExtCosts::ripemd160_base => Parameter::WasmRipemd160Base,
365            ExtCosts::ripemd160_block => Parameter::WasmRipemd160Block,
366            ExtCosts::ecrecover_base => Parameter::WasmEcrecoverBase,
367            ExtCosts::ed25519_verify_base => Parameter::WasmEd25519VerifyBase,
368            ExtCosts::ed25519_verify_byte => Parameter::WasmEd25519VerifyByte,
369            ExtCosts::log_base => Parameter::WasmLogBase,
370            ExtCosts::log_byte => Parameter::WasmLogByte,
371            ExtCosts::storage_write_base => Parameter::WasmStorageWriteBase,
372            ExtCosts::storage_write_key_byte => Parameter::WasmStorageWriteKeyByte,
373            ExtCosts::storage_write_value_byte => Parameter::WasmStorageWriteValueByte,
374            ExtCosts::storage_write_evicted_byte => Parameter::WasmStorageWriteEvictedByte,
375            ExtCosts::storage_read_base => Parameter::WasmStorageReadBase,
376            ExtCosts::storage_read_key_byte => Parameter::WasmStorageReadKeyByte,
377            ExtCosts::storage_read_value_byte => Parameter::WasmStorageReadValueByte,
378            ExtCosts::storage_large_read_overhead_base => {
379                Parameter::WasmStorageLargeReadOverheadBase
380            }
381            ExtCosts::storage_large_read_overhead_byte => {
382                Parameter::WasmStorageLargeReadOverheadByte
383            }
384            ExtCosts::storage_remove_base => Parameter::WasmStorageRemoveBase,
385            ExtCosts::storage_remove_key_byte => Parameter::WasmStorageRemoveKeyByte,
386            ExtCosts::storage_remove_ret_value_byte => Parameter::WasmStorageRemoveRetValueByte,
387            ExtCosts::storage_has_key_base => Parameter::WasmStorageHasKeyBase,
388            ExtCosts::storage_has_key_byte => Parameter::WasmStorageHasKeyByte,
389            ExtCosts::storage_iter_create_prefix_base => Parameter::WasmStorageIterCreatePrefixBase,
390            ExtCosts::storage_iter_create_prefix_byte => Parameter::WasmStorageIterCreatePrefixByte,
391            ExtCosts::storage_iter_create_range_base => Parameter::WasmStorageIterCreateRangeBase,
392            ExtCosts::storage_iter_create_from_byte => Parameter::WasmStorageIterCreateFromByte,
393            ExtCosts::storage_iter_create_to_byte => Parameter::WasmStorageIterCreateToByte,
394            ExtCosts::storage_iter_next_base => Parameter::WasmStorageIterNextBase,
395            ExtCosts::storage_iter_next_key_byte => Parameter::WasmStorageIterNextKeyByte,
396            ExtCosts::storage_iter_next_value_byte => Parameter::WasmStorageIterNextValueByte,
397            ExtCosts::touching_trie_node => Parameter::WasmTouchingTrieNode,
398            ExtCosts::read_cached_trie_node => Parameter::WasmReadCachedTrieNode,
399            ExtCosts::promise_and_base => Parameter::WasmPromiseAndBase,
400            ExtCosts::promise_and_per_promise => Parameter::WasmPromiseAndPerPromise,
401            ExtCosts::promise_return => Parameter::WasmPromiseReturn,
402            ExtCosts::validator_stake_base => Parameter::WasmValidatorStakeBase,
403            ExtCosts::validator_total_stake_base => Parameter::WasmValidatorTotalStakeBase,
404            ExtCosts::alt_bn128_g1_multiexp_base => Parameter::WasmAltBn128G1MultiexpBase,
405            ExtCosts::alt_bn128_g1_multiexp_element => Parameter::WasmAltBn128G1MultiexpElement,
406            ExtCosts::alt_bn128_pairing_check_base => Parameter::WasmAltBn128PairingCheckBase,
407            ExtCosts::alt_bn128_pairing_check_element => Parameter::WasmAltBn128PairingCheckElement,
408            ExtCosts::alt_bn128_g1_sum_base => Parameter::WasmAltBn128G1SumBase,
409            ExtCosts::alt_bn128_g1_sum_element => Parameter::WasmAltBn128G1SumElement,
410            ExtCosts::yield_create_base => Parameter::WasmYieldCreateBase,
411            ExtCosts::yield_create_byte => Parameter::WasmYieldCreateByte,
412            ExtCosts::yield_resume_base => Parameter::WasmYieldResumeBase,
413            ExtCosts::yield_resume_byte => Parameter::WasmYieldResumeByte,
414            ExtCosts::bls12381_p1_sum_base => Parameter::WasmBls12381P1SumBase,
415            ExtCosts::bls12381_p1_sum_element => Parameter::WasmBls12381P1SumElement,
416            ExtCosts::bls12381_p2_sum_base => Parameter::WasmBls12381P2SumBase,
417            ExtCosts::bls12381_p2_sum_element => Parameter::WasmBls12381P2SumElement,
418            ExtCosts::bls12381_g1_multiexp_base => Parameter::WasmBls12381G1MultiexpBase,
419            ExtCosts::bls12381_g1_multiexp_element => Parameter::WasmBls12381G1MultiexpElement,
420            ExtCosts::bls12381_g2_multiexp_base => Parameter::WasmBls12381G2MultiexpBase,
421            ExtCosts::bls12381_g2_multiexp_element => Parameter::WasmBls12381G2MultiexpElement,
422            ExtCosts::bls12381_map_fp_to_g1_base => Parameter::WasmBls12381MapFpToG1Base,
423            ExtCosts::bls12381_map_fp_to_g1_element => Parameter::WasmBls12381MapFpToG1Element,
424            ExtCosts::bls12381_map_fp2_to_g2_base => Parameter::WasmBls12381MapFp2ToG2Base,
425            ExtCosts::bls12381_map_fp2_to_g2_element => Parameter::WasmBls12381MapFp2ToG2Element,
426            ExtCosts::bls12381_pairing_base => Parameter::WasmBls12381PairingBase,
427            ExtCosts::bls12381_pairing_element => Parameter::WasmBls12381PairingElement,
428            ExtCosts::bls12381_p1_decompress_base => Parameter::WasmBls12381P1DecompressBase,
429            ExtCosts::bls12381_p1_decompress_element => Parameter::WasmBls12381P1DecompressElement,
430            ExtCosts::bls12381_p2_decompress_base => Parameter::WasmBls12381P2DecompressBase,
431            ExtCosts::bls12381_p2_decompress_element => Parameter::WasmBls12381P2DecompressElement,
432        }
433    }
434}
435
436#[derive(Debug, Clone, Hash, PartialEq, Eq)]
437pub struct RuntimeFeesConfig {
438    /// Gas fees for sending and executing actions.
439    pub action_fees: EnumMap<ActionCosts, Fee>,
440
441    /// Describes fees for storage.
442    pub storage_usage_config: StorageUsageConfig,
443
444    /// Fraction of the burnt gas to reward to the contract account for execution.
445    pub burnt_gas_reward: Rational32,
446
447    /// Pessimistic gas price inflation ratio.
448    pub pessimistic_gas_price_inflation_ratio: Rational32,
449
450    /// Relative cost for gas refunds as a ratio of the refunded amount.
451    ///
452    /// The actual penalty is
453    /// `max(gross_refund * gas_refund_penalty, min_gas_refund_penalty)`
454    ///
455    /// Added with [NEP-536](https://github.com/near/NEPs/pull/536)
456    pub gas_refund_penalty: Rational32,
457    /// Minimum cost for gas refunds.
458    ///
459    /// The actual penalty is
460    /// `max(gross_refund * gas_refund_penalty, min_gas_refund_penalty)`
461    ///
462    /// Added with [NEP-536](https://github.com/near/NEPs/pull/536)
463    pub min_gas_refund_penalty: Gas,
464}
465
466/// Describes cost of storage per block
467#[derive(Debug, Clone, Hash, PartialEq, Eq)]
468pub struct StorageUsageConfig {
469    /// Amount of yN per byte required to have on the account. See
470    /// <https://nomicon.io/Economics/Economic#state-stake> for details.
471    pub storage_amount_per_byte: Balance,
472    /// Number of bytes for an account record, including rounding up for account id.
473    pub num_bytes_account: u64,
474    /// Additional number of bytes for a k/v record
475    pub num_extra_bytes_record: u64,
476    /// Amount of yN burned per byte of deployed Global Contract code.
477    pub global_contract_storage_amount_per_byte: Balance,
478}
479
480impl RuntimeFeesConfig {
481    /// Access action fee by `ActionCosts`.
482    pub fn fee(&self, cost: ActionCosts) -> &Fee {
483        &self.action_fees[cost]
484    }
485
486    pub fn test() -> Self {
487        Self {
488            storage_usage_config: StorageUsageConfig::test(),
489            burnt_gas_reward: Rational32::new(3, 10),
490            pessimistic_gas_price_inflation_ratio: Rational32::new(103, 100),
491            gas_refund_penalty: Rational32::new(5, 100),
492            min_gas_refund_penalty: Gas::from_teragas(1),
493            action_fees: enum_map::enum_map! {
494                ActionCosts::create_account => Fee::test_value(3_850_000_000_000),
495                ActionCosts::delete_account => Fee::test_value(147489000000),
496                ActionCosts::deploy_contract_base => Fee::test_value(184765750000),
497                ActionCosts::deploy_contract_byte => Fee::test_value(6812999),
498                ActionCosts::function_call_base => Fee::test_value(2319861500000),
499                ActionCosts::function_call_byte => Fee::test_value(2235934),
500                ActionCosts::transfer => Fee::test_value(115123062500),
501                ActionCosts::stake => Fee::new(141715687500, 141715687500, 102217625000),
502                ActionCosts::add_full_access_key => Fee::test_value(101765125000),
503                ActionCosts::add_function_call_key_base => Fee::test_value(102217625000),
504                ActionCosts::add_function_call_key_byte => Fee::test_value(1925331),
505                ActionCosts::delete_key => Fee::test_value(94946625000),
506                ActionCosts::new_action_receipt => Fee::test_value(108059500000),
507                ActionCosts::new_data_receipt_base => Fee::test_value(4697339419375),
508                ActionCosts::new_data_receipt_byte => Fee::test_value(59357464),
509                ActionCosts::delegate => Fee::test_value(200_000_000_000),
510                ActionCosts::deploy_global_contract_base => Fee::test_value(184_765_750_000),
511                ActionCosts::deploy_global_contract_byte => Fee::new(6_812_999, 6_812_999, 70_000_000),
512                ActionCosts::use_global_contract_base => Fee::test_value(184_765_750_000),
513                ActionCosts::use_global_contract_byte => Fee::new(6_812_999, 47_683_715, 64_572_944),
514                ActionCosts::deterministic_state_init_base => Fee::new(3_850_000_000_000, 3_850_000_000_000, 4_080_000_000_000),
515                ActionCosts::deterministic_state_init_byte => Fee::new(72_000_000, 72_000_000, 70_000_000),
516                ActionCosts::deterministic_state_init_entry => Fee::new(0, 0, 200_000_000_000),
517            },
518        }
519    }
520
521    pub fn free() -> Self {
522        Self {
523            action_fees: enum_map::enum_map! {
524                _ => Fee::new(0, 0, 0)
525            },
526            storage_usage_config: StorageUsageConfig::free(),
527            burnt_gas_reward: Rational32::from_integer(0),
528            pessimistic_gas_price_inflation_ratio: Rational32::from_integer(0),
529            gas_refund_penalty: Rational32::from_integer(0),
530            min_gas_refund_penalty: Gas::ZERO,
531        }
532    }
533
534    /// The minimum amount of gas required to create and execute a new receipt with a function call
535    /// action.
536    /// This amount is used to determine how many receipts can be created, send and executed for
537    /// some amount of prepaid gas using function calls.
538    pub fn min_receipt_with_function_call_gas(&self) -> Gas {
539        self.fee(ActionCosts::new_action_receipt)
540            .min_send_and_exec_fee()
541            .checked_add(self.fee(ActionCosts::function_call_base).min_send_and_exec_fee())
542            .unwrap()
543    }
544
545    /// Given a left over gas amount to be refunded, returns how much should be
546    /// subtracted as a penalty introduced with NEP-536.
547    ///
548    /// Must return a value smaller or equal to the `gas_refund` parameter.
549    pub fn gas_penalty_for_gas_refund(&self, gas_refund: Gas) -> Gas {
550        let relative_cost = Gas::from_gas(
551            (u128::from(gas_refund.as_gas()) * *self.gas_refund_penalty.numer() as u128
552                / *self.gas_refund_penalty.denom() as u128)
553                .try_into()
554                .unwrap(),
555        );
556
557        let penalty = std::cmp::max(relative_cost, self.min_gas_refund_penalty);
558        std::cmp::min(penalty, gas_refund)
559    }
560}
561
562impl StorageUsageConfig {
563    pub fn test() -> Self {
564        Self {
565            num_bytes_account: 100,
566            num_extra_bytes_record: 40,
567            storage_amount_per_byte: Balance::from_yoctonear(909 * 100_000_000_000_000_000),
568            global_contract_storage_amount_per_byte: Balance::from_yoctonear(
569                100_000_000_000_000_000_000,
570            ),
571        }
572    }
573
574    pub(crate) fn free() -> StorageUsageConfig {
575        Self {
576            num_bytes_account: 0,
577            num_extra_bytes_record: 0,
578            storage_amount_per_byte: Balance::ZERO,
579            global_contract_storage_amount_per_byte: Balance::ZERO,
580        }
581    }
582}
583
584/// Helper functions for computing Transfer fees.
585/// In case of implicit account creation they include extra fees for the CreateAccount and
586/// AddFullAccessKey (for NEAR-implicit account only) actions that are implicit.
587/// We can assume that no overflow will happen here.
588pub fn transfer_exec_fee(
589    cfg: &RuntimeFeesConfig,
590    implicit_account_creation_allowed: bool,
591    eth_implicit_accounts_enabled: bool,
592    receiver_account_type: AccountType,
593) -> Gas {
594    let transfer_fee = cfg.fee(ActionCosts::transfer).exec_fee();
595    match (implicit_account_creation_allowed, eth_implicit_accounts_enabled, receiver_account_type)
596    {
597        // Regular transfer to a named account.
598        (_, _, AccountType::NamedAccount) => transfer_fee,
599        // No account will be created, just a regular transfer.
600        (false, _, _) => transfer_fee,
601        // No account will be created, just a regular transfer.
602        (true, false, AccountType::EthImplicitAccount) => transfer_fee,
603        // Extra fee for the CreateAccount.
604        (true, true, AccountType::EthImplicitAccount) => {
605            transfer_fee.checked_add(cfg.fee(ActionCosts::create_account).exec_fee()).unwrap()
606        }
607        // Extra fees for the CreateAccount and AddFullAccessKey.
608        (true, _, AccountType::NearImplicitAccount) => transfer_fee
609            .checked_add(cfg.fee(ActionCosts::create_account).exec_fee())
610            .unwrap()
611            .checked_add(cfg.fee(ActionCosts::add_full_access_key).exec_fee())
612            .unwrap(),
613        // Extra fees for the implied CreateAccount action.
614        (true, _, AccountType::NearDeterministicAccount) => {
615            transfer_fee.checked_add(cfg.fee(ActionCosts::create_account).exec_fee()).unwrap()
616        }
617    }
618}
619
620pub fn transfer_send_fee(
621    cfg: &RuntimeFeesConfig,
622    sender_is_receiver: bool,
623    implicit_account_creation_allowed: bool,
624    eth_implicit_accounts_enabled: bool,
625    receiver_account_type: AccountType,
626) -> Gas {
627    let transfer_fee = cfg.fee(ActionCosts::transfer).send_fee(sender_is_receiver);
628    match (implicit_account_creation_allowed, eth_implicit_accounts_enabled, receiver_account_type)
629    {
630        // Regular transfer to a named account.
631        (_, _, AccountType::NamedAccount) => transfer_fee,
632        // No account will be created, just a regular transfer.
633        (false, _, _) => transfer_fee,
634        // No account will be created, just a regular transfer.
635        (true, false, AccountType::EthImplicitAccount) => transfer_fee,
636        // Extra fee for the CreateAccount.
637        (true, true, AccountType::EthImplicitAccount) => transfer_fee
638            .checked_add(cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver))
639            .unwrap(),
640        // Extra fees for the CreateAccount and AddFullAccessKey.
641        (true, _, AccountType::NearImplicitAccount) => transfer_fee
642            .checked_add(cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver))
643            .unwrap()
644            .checked_add(cfg.fee(ActionCosts::add_full_access_key).send_fee(sender_is_receiver))
645            .unwrap(),
646        // Extra fees for the implied  CreateAccount action.
647        (true, _, AccountType::NearDeterministicAccount) => transfer_fee
648            .checked_add(cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver))
649            .unwrap(),
650    }
651}