Skip to main content

near_parameters/
cost.rs

1use crate::parameter::Parameter;
2use crate::parameter_table::FeeComponent;
3use enum_map::{EnumMap, enum_map};
4use near_account_id::AccountType;
5use near_primitives_core::account::{AccessKey, GasKeyInfo};
6use near_primitives_core::errors::IntegerOverflowError;
7use near_primitives_core::trie_key::access_key_key_len;
8use near_primitives_core::types::{Balance, Compute, Gas, NonceIndex};
9use near_schema_checker_lib::ProtocolSchema;
10use num_rational::Rational32;
11
12/// Costs associated with an object that can only be sent over the network (and executed
13/// by the receiver).
14/// NOTE: `send_sir` or `send_not_sir` fees are usually burned when the item is being created.
15/// And `execution` fee is burned when the item is being executed.
16#[derive(Debug, Clone, Hash, PartialEq, Eq)]
17pub struct Fee {
18    /// Fee for sending an object from the sender to itself, guaranteeing that it does not leave
19    /// the shard.
20    pub send_sir: FeeComponent,
21    /// Fee for sending an object potentially across the shards.
22    pub send_not_sir: FeeComponent,
23    /// Fee for executing the object.
24    pub execution: FeeComponent,
25}
26
27impl Fee {
28    pub fn new(send_sir: u64, send_not_sir: u64, execution: u64) -> Self {
29        Self {
30            send_sir: FeeComponent::Gas(Gas::from_gas(send_sir)),
31            send_not_sir: FeeComponent::Gas(Gas::from_gas(send_not_sir)),
32            execution: FeeComponent::Gas(Gas::from_gas(execution)),
33        }
34    }
35
36    #[inline]
37    pub fn send_fee(&self, sir: bool) -> ParameterCost {
38        if sir { self.send_sir.cost() } else { self.send_not_sir.cost() }
39    }
40
41    pub fn exec_fee(&self) -> ParameterCost {
42        self.execution.cost()
43    }
44
45    /// The minimum gas fee to send and execute.
46    pub fn min_send_and_exec_fee(&self) -> Gas {
47        std::cmp::min(self.send_sir.gas(), self.send_not_sir.gas())
48            .checked_add(self.execution.gas())
49            .unwrap()
50    }
51
52    fn test_value(value: u64, factor: u64) -> Self {
53        Self::test_value_detailed(value, value, value, factor)
54    }
55
56    fn test_value_detailed(
57        send_sir_cost: u64,
58        send_not_sir_cost: u64,
59        execution_cost: u64,
60        factor: u64,
61    ) -> Self {
62        Self {
63            send_sir: FeeComponent::GasAndCompute {
64                gas: Gas::from_gas(send_sir_cost),
65                compute: send_sir_cost * factor,
66            },
67            send_not_sir: FeeComponent::GasAndCompute {
68                gas: Gas::from_gas(send_not_sir_cost),
69                compute: send_not_sir_cost * factor,
70            },
71            execution: FeeComponent::GasAndCompute {
72                gas: Gas::from_gas(execution_cost),
73                compute: execution_cost * factor,
74            },
75        }
76    }
77}
78#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
79pub struct ParameterCost {
80    pub gas: Gas,
81    pub compute: Compute,
82}
83
84impl ParameterCost {
85    pub const ZERO: ParameterCost = ParameterCost { gas: Gas::ZERO, compute: 0 };
86
87    pub fn new(gas: Gas, compute: Compute) -> Self {
88        Self { gas, compute }
89    }
90
91    pub fn checked_add(self, rhs: Self) -> Option<Self> {
92        let gas = self.gas.checked_add(rhs.gas)?;
93        let compute = self.compute.checked_add(rhs.compute)?;
94        Some(Self { gas, compute })
95    }
96
97    pub fn checked_add_result(self, rhs: Self) -> Result<Self, IntegerOverflowError> {
98        self.checked_add(rhs).ok_or(IntegerOverflowError)
99    }
100
101    pub fn checked_sub(self, rhs: Self) -> Option<Self> {
102        let gas = self.gas.checked_sub(rhs.gas)?;
103        let compute = self.compute.checked_sub(rhs.compute)?;
104        Some(Self { gas, compute })
105    }
106
107    pub fn checked_mul(self, rhs: u64) -> Option<Self> {
108        let gas = self.gas.checked_mul(rhs)?;
109        let compute = self.compute.checked_mul(rhs)?;
110        Some(Self { gas, compute })
111    }
112}
113
114#[derive(Debug, Clone, Hash, PartialEq, Eq)]
115pub struct ExtCostsConfig {
116    pub costs: EnumMap<ExtCosts, ParameterCost>,
117}
118
119// We multiply the actual computed costs by the fixed factor to ensure we
120// have certain reserve for further gas price variation.
121const SAFETY_MULTIPLIER: u64 = 3;
122
123impl ExtCostsConfig {
124    pub fn gas_cost(&self, param: ExtCosts) -> Gas {
125        self.costs[param].gas
126    }
127
128    pub fn compute_cost(&self, param: ExtCosts) -> Compute {
129        self.costs[param].compute
130    }
131
132    /// Convenience constructor to use in tests where the exact gas cost does
133    /// not need to correspond to a specific protocol version.
134    pub fn test_with_undercharging_factor(factor: u64) -> ExtCostsConfig {
135        let costs = enum_map! {
136            ExtCosts::base => SAFETY_MULTIPLIER * 88256037,
137            ExtCosts::contract_loading_base => SAFETY_MULTIPLIER * 11815321,
138            ExtCosts::contract_loading_bytes => SAFETY_MULTIPLIER * 72250,
139            ExtCosts::read_memory_base => SAFETY_MULTIPLIER * 869954400,
140            ExtCosts::read_memory_byte => SAFETY_MULTIPLIER * 1267111,
141            ExtCosts::write_memory_base => SAFETY_MULTIPLIER * 934598287,
142            ExtCosts::write_memory_byte => SAFETY_MULTIPLIER * 907924,
143            ExtCosts::read_register_base => SAFETY_MULTIPLIER * 839055062,
144            ExtCosts::read_register_byte => SAFETY_MULTIPLIER * 32854,
145            ExtCosts::write_register_base => SAFETY_MULTIPLIER * 955174162,
146            ExtCosts::write_register_byte => SAFETY_MULTIPLIER * 1267188,
147            ExtCosts::utf8_decoding_base => SAFETY_MULTIPLIER * 1037259687,
148            ExtCosts::utf8_decoding_byte => SAFETY_MULTIPLIER * 97193493,
149            ExtCosts::utf16_decoding_base => SAFETY_MULTIPLIER * 1181104350,
150            ExtCosts::utf16_decoding_byte => SAFETY_MULTIPLIER * 54525831,
151            ExtCosts::sha256_base => SAFETY_MULTIPLIER * 1513656750,
152            ExtCosts::sha256_byte => SAFETY_MULTIPLIER * 8039117,
153            ExtCosts::keccak256_base => SAFETY_MULTIPLIER * 1959830425,
154            ExtCosts::keccak256_byte => SAFETY_MULTIPLIER * 7157035,
155            ExtCosts::keccak512_base => SAFETY_MULTIPLIER * 1937129412,
156            ExtCosts::keccak512_byte => SAFETY_MULTIPLIER * 12216567,
157            ExtCosts::ripemd160_base => SAFETY_MULTIPLIER * 284558362,
158            ExtCosts::ed25519_verify_base => SAFETY_MULTIPLIER * 1513656750,
159            ExtCosts::ed25519_verify_byte => SAFETY_MULTIPLIER * 7157035,
160            ExtCosts::ripemd160_block => SAFETY_MULTIPLIER * 226702528,
161            ExtCosts::ecrecover_base => SAFETY_MULTIPLIER * 1121789875000,
162            ExtCosts::p256_verify_base => SAFETY_MULTIPLIER * 433_333_333_333,
163            ExtCosts::p256_verify_byte => SAFETY_MULTIPLIER * 4_333_333,
164            ExtCosts::log_base => SAFETY_MULTIPLIER * 1181104350,
165            ExtCosts::log_byte => SAFETY_MULTIPLIER * 4399597,
166            ExtCosts::storage_write_base => SAFETY_MULTIPLIER * 21398912000,
167            ExtCosts::storage_write_key_byte => SAFETY_MULTIPLIER * 23494289,
168            ExtCosts::storage_write_value_byte => SAFETY_MULTIPLIER * 10339513,
169            ExtCosts::storage_write_evicted_byte => SAFETY_MULTIPLIER * 10705769,
170            ExtCosts::storage_read_base => SAFETY_MULTIPLIER * 18785615250,
171            ExtCosts::storage_read_key_byte => SAFETY_MULTIPLIER * 10317511,
172            ExtCosts::storage_read_value_byte => SAFETY_MULTIPLIER * 1870335,
173            ExtCosts::storage_large_read_overhead_base => 0,
174            ExtCosts::storage_large_read_overhead_byte => 0,
175            ExtCosts::storage_remove_base => SAFETY_MULTIPLIER * 17824343500,
176            ExtCosts::storage_remove_key_byte => SAFETY_MULTIPLIER * 12740128,
177            ExtCosts::storage_remove_ret_value_byte => SAFETY_MULTIPLIER * 3843852,
178            ExtCosts::storage_has_key_base => SAFETY_MULTIPLIER * 18013298875,
179            ExtCosts::storage_has_key_byte => SAFETY_MULTIPLIER * 10263615,
180            // Here it should be `SAFETY_MULTIPLIER * 0` for consistency, but then
181            // clippy complains with "this operation will always return zero" warning
182            ExtCosts::storage_iter_create_prefix_base => 0,
183            ExtCosts::storage_iter_create_prefix_byte => 0,
184            ExtCosts::storage_iter_create_range_base => 0,
185            ExtCosts::storage_iter_create_from_byte => 0,
186            ExtCosts::storage_iter_create_to_byte => 0,
187            ExtCosts::storage_iter_next_base => 0,
188            ExtCosts::storage_iter_next_key_byte => 0,
189            ExtCosts::storage_iter_next_value_byte => 0,
190            ExtCosts::touching_trie_node => SAFETY_MULTIPLIER * 5367318642,
191            ExtCosts::read_cached_trie_node => SAFETY_MULTIPLIER * 760_000_000,
192            ExtCosts::promise_and_base => SAFETY_MULTIPLIER * 488337800,
193            ExtCosts::promise_and_per_promise => SAFETY_MULTIPLIER * 1817392,
194            ExtCosts::promise_return => SAFETY_MULTIPLIER * 186717462,
195            ExtCosts::validator_stake_base => SAFETY_MULTIPLIER * 303944908800,
196            ExtCosts::validator_total_stake_base => SAFETY_MULTIPLIER * 303944908800,
197            ExtCosts::alt_bn128_g1_multiexp_base => 713_000_000_000,
198            ExtCosts::alt_bn128_g1_multiexp_element => 320_000_000_000,
199            ExtCosts::alt_bn128_pairing_check_base => 9_686_000_000_000,
200            ExtCosts::alt_bn128_pairing_check_element => 5_102_000_000_000,
201            ExtCosts::alt_bn128_g1_sum_base => 3_000_000_000,
202            ExtCosts::alt_bn128_g1_sum_element => 5_000_000_000,
203            ExtCosts::bls12381_p1_sum_base => SAFETY_MULTIPLIER * 5_500_000_000,
204            ExtCosts::bls12381_p1_sum_element => SAFETY_MULTIPLIER * 2_000_000_000,
205            ExtCosts::bls12381_p2_sum_base => SAFETY_MULTIPLIER * 6_200_000_000,
206            ExtCosts::bls12381_p2_sum_element => SAFETY_MULTIPLIER * 5_000_000_000,
207            ExtCosts::bls12381_g1_multiexp_base => SAFETY_MULTIPLIER * 5_500_000_000,
208            ExtCosts::bls12381_g1_multiexp_element => SAFETY_MULTIPLIER * 310_000_000_000,
209            ExtCosts::bls12381_g2_multiexp_base => SAFETY_MULTIPLIER * 6_200_000_000,
210            ExtCosts::bls12381_g2_multiexp_element => SAFETY_MULTIPLIER * 665_000_000_000,
211            ExtCosts::bls12381_map_fp_to_g1_base => SAFETY_MULTIPLIER * 500_000_000,
212            ExtCosts::bls12381_map_fp_to_g1_element => SAFETY_MULTIPLIER * 84_000_000_000,
213            ExtCosts::bls12381_map_fp2_to_g2_base => SAFETY_MULTIPLIER * 500_000_000,
214            ExtCosts::bls12381_map_fp2_to_g2_element => SAFETY_MULTIPLIER * 300_000_000_000,
215            ExtCosts::bls12381_pairing_base => SAFETY_MULTIPLIER * 710_000_000_000,
216            ExtCosts::bls12381_pairing_element => SAFETY_MULTIPLIER * 710_000_000_000,
217            ExtCosts::bls12381_p1_decompress_base => SAFETY_MULTIPLIER * 500_000_000,
218            ExtCosts::bls12381_p1_decompress_element => SAFETY_MULTIPLIER * 27_000_000_000,
219            ExtCosts::bls12381_p2_decompress_base => SAFETY_MULTIPLIER * 500_000_000,
220            ExtCosts::bls12381_p2_decompress_element => SAFETY_MULTIPLIER * 55_000_000_000,
221            // TODO(yield/resume): replicate fees here after estimation
222            ExtCosts::yield_create_base => 300_000_000_000_000,
223            ExtCosts::yield_create_byte => 300_000_000_000_000,
224            ExtCosts::yield_create_with_id_base => 300_000_000_000_000,
225            ExtCosts::yield_resume_base => 300_000_000_000_000,
226            ExtCosts::yield_resume_byte => 300_000_000_000_000,
227        }
228        .map(|_, value| ParameterCost { gas: Gas::from_gas(value), compute: value * factor });
229        ExtCostsConfig { costs }
230    }
231
232    /// `test_with_undercharging_factor` with a factor of 1.
233    pub fn test() -> ExtCostsConfig {
234        Self::test_with_undercharging_factor(1)
235    }
236}
237
238/// Strongly-typed representation of the fees for counting.
239///
240/// Do not change the enum discriminants here, they are used for borsh
241/// (de-)serialization.
242#[derive(
243    Copy,
244    Clone,
245    Hash,
246    PartialEq,
247    Eq,
248    Debug,
249    PartialOrd,
250    Ord,
251    strum::Display,
252    strum::EnumIter,
253    enum_map::Enum,
254    ProtocolSchema,
255)]
256#[allow(non_camel_case_types)]
257pub enum ExtCosts {
258    base = 0,
259    contract_loading_base = 1,
260    contract_loading_bytes = 2,
261    read_memory_base = 3,
262    read_memory_byte = 4,
263    write_memory_base = 5,
264    write_memory_byte = 6,
265    read_register_base = 7,
266    read_register_byte = 8,
267    write_register_base = 9,
268    write_register_byte = 10,
269    utf8_decoding_base = 11,
270    utf8_decoding_byte = 12,
271    utf16_decoding_base = 13,
272    utf16_decoding_byte = 14,
273    sha256_base = 15,
274    sha256_byte = 16,
275    keccak256_base = 17,
276    keccak256_byte = 18,
277    keccak512_base = 19,
278    keccak512_byte = 20,
279    ripemd160_base = 21,
280    ripemd160_block = 22,
281    ecrecover_base = 23,
282    log_base = 24,
283    log_byte = 25,
284    storage_write_base = 26,
285    storage_write_key_byte = 27,
286    storage_write_value_byte = 28,
287    storage_write_evicted_byte = 29,
288    storage_read_base = 30,
289    storage_read_key_byte = 31,
290    storage_read_value_byte = 32,
291    storage_remove_base = 33,
292    storage_remove_key_byte = 34,
293    storage_remove_ret_value_byte = 35,
294    storage_has_key_base = 36,
295    storage_has_key_byte = 37,
296    storage_iter_create_prefix_base = 38,
297    storage_iter_create_prefix_byte = 39,
298    storage_iter_create_range_base = 40,
299    storage_iter_create_from_byte = 41,
300    storage_iter_create_to_byte = 42,
301    storage_iter_next_base = 43,
302    storage_iter_next_key_byte = 44,
303    storage_iter_next_value_byte = 45,
304    touching_trie_node = 46,
305    read_cached_trie_node = 47,
306    promise_and_base = 48,
307    promise_and_per_promise = 49,
308    promise_return = 50,
309    validator_stake_base = 51,
310    validator_total_stake_base = 52,
311    alt_bn128_g1_multiexp_base = 53,
312    alt_bn128_g1_multiexp_element = 54,
313    alt_bn128_pairing_check_base = 55,
314    alt_bn128_pairing_check_element = 56,
315    alt_bn128_g1_sum_base = 57,
316    alt_bn128_g1_sum_element = 58,
317    ed25519_verify_base = 59,
318    ed25519_verify_byte = 60,
319    yield_create_base = 61,
320    yield_create_byte = 62,
321    yield_resume_base = 63,
322    yield_resume_byte = 64,
323    bls12381_p1_sum_base = 65,
324    bls12381_p1_sum_element = 66,
325    bls12381_p2_sum_base = 67,
326    bls12381_p2_sum_element = 68,
327    bls12381_g1_multiexp_base = 69,
328    bls12381_g1_multiexp_element = 70,
329    bls12381_g2_multiexp_base = 71,
330    bls12381_g2_multiexp_element = 72,
331    bls12381_map_fp_to_g1_base = 73,
332    bls12381_map_fp_to_g1_element = 74,
333    bls12381_map_fp2_to_g2_base = 75,
334    bls12381_map_fp2_to_g2_element = 76,
335    bls12381_pairing_base = 77,
336    bls12381_pairing_element = 78,
337    bls12381_p1_decompress_base = 79,
338    bls12381_p1_decompress_element = 80,
339    bls12381_p2_decompress_base = 81,
340    bls12381_p2_decompress_element = 82,
341    storage_large_read_overhead_base = 83,
342    storage_large_read_overhead_byte = 84,
343    p256_verify_base = 85,
344    p256_verify_byte = 86,
345    yield_create_with_id_base = 87,
346}
347
348// Type of an action, used in fees logic.
349#[derive(
350    Copy,
351    Clone,
352    Hash,
353    PartialEq,
354    Eq,
355    Debug,
356    PartialOrd,
357    Ord,
358    strum::Display,
359    strum::EnumIter,
360    enum_map::Enum,
361    ProtocolSchema,
362)]
363#[allow(non_camel_case_types)]
364pub enum ActionCosts {
365    create_account = 0,
366    delete_account = 1,
367    deploy_contract_base = 2,
368    deploy_contract_byte = 3,
369    function_call_base = 4,
370    function_call_byte = 5,
371    transfer = 6,
372    stake = 7,
373    add_full_access_key = 8,
374    add_function_call_key_base = 9,
375    add_function_call_key_byte = 10,
376    delete_key = 11,
377    new_action_receipt = 12,
378    new_data_receipt_base = 13,
379    new_data_receipt_byte = 14,
380    delegate = 15,
381    deploy_global_contract_base = 16,
382    deploy_global_contract_byte = 17,
383    use_global_contract_base = 18,
384    use_global_contract_byte = 19,
385    deterministic_state_init_base = 20,
386    deterministic_state_init_byte = 21,
387    deterministic_state_init_entry = 22,
388    gas_key_transfer_base = 23,
389    gas_key_byte = 24,
390    gas_key_nonce_write_base = 25,
391}
392
393impl ExtCosts {
394    pub fn gas(self, config: &ExtCostsConfig) -> Gas {
395        config.gas_cost(self)
396    }
397
398    pub fn compute(self, config: &ExtCostsConfig) -> Compute {
399        config.compute_cost(self)
400    }
401
402    pub fn param(&self) -> Parameter {
403        match self {
404            ExtCosts::base => Parameter::WasmBase,
405            ExtCosts::contract_loading_base => Parameter::WasmContractLoadingBase,
406            ExtCosts::contract_loading_bytes => Parameter::WasmContractLoadingBytes,
407            ExtCosts::read_memory_base => Parameter::WasmReadMemoryBase,
408            ExtCosts::read_memory_byte => Parameter::WasmReadMemoryByte,
409            ExtCosts::write_memory_base => Parameter::WasmWriteMemoryBase,
410            ExtCosts::write_memory_byte => Parameter::WasmWriteMemoryByte,
411            ExtCosts::read_register_base => Parameter::WasmReadRegisterBase,
412            ExtCosts::read_register_byte => Parameter::WasmReadRegisterByte,
413            ExtCosts::write_register_base => Parameter::WasmWriteRegisterBase,
414            ExtCosts::write_register_byte => Parameter::WasmWriteRegisterByte,
415            ExtCosts::utf8_decoding_base => Parameter::WasmUtf8DecodingBase,
416            ExtCosts::utf8_decoding_byte => Parameter::WasmUtf8DecodingByte,
417            ExtCosts::utf16_decoding_base => Parameter::WasmUtf16DecodingBase,
418            ExtCosts::utf16_decoding_byte => Parameter::WasmUtf16DecodingByte,
419            ExtCosts::sha256_base => Parameter::WasmSha256Base,
420            ExtCosts::sha256_byte => Parameter::WasmSha256Byte,
421            ExtCosts::keccak256_base => Parameter::WasmKeccak256Base,
422            ExtCosts::keccak256_byte => Parameter::WasmKeccak256Byte,
423            ExtCosts::keccak512_base => Parameter::WasmKeccak512Base,
424            ExtCosts::keccak512_byte => Parameter::WasmKeccak512Byte,
425            ExtCosts::ripemd160_base => Parameter::WasmRipemd160Base,
426            ExtCosts::ripemd160_block => Parameter::WasmRipemd160Block,
427            ExtCosts::ecrecover_base => Parameter::WasmEcrecoverBase,
428            ExtCosts::ed25519_verify_base => Parameter::WasmEd25519VerifyBase,
429            ExtCosts::ed25519_verify_byte => Parameter::WasmEd25519VerifyByte,
430            ExtCosts::p256_verify_base => Parameter::WasmP256VerifyBase,
431            ExtCosts::p256_verify_byte => Parameter::WasmP256VerifyByte,
432            ExtCosts::log_base => Parameter::WasmLogBase,
433            ExtCosts::log_byte => Parameter::WasmLogByte,
434            ExtCosts::storage_write_base => Parameter::WasmStorageWriteBase,
435            ExtCosts::storage_write_key_byte => Parameter::WasmStorageWriteKeyByte,
436            ExtCosts::storage_write_value_byte => Parameter::WasmStorageWriteValueByte,
437            ExtCosts::storage_write_evicted_byte => Parameter::WasmStorageWriteEvictedByte,
438            ExtCosts::storage_read_base => Parameter::WasmStorageReadBase,
439            ExtCosts::storage_read_key_byte => Parameter::WasmStorageReadKeyByte,
440            ExtCosts::storage_read_value_byte => Parameter::WasmStorageReadValueByte,
441            ExtCosts::storage_large_read_overhead_base => {
442                Parameter::WasmStorageLargeReadOverheadBase
443            }
444            ExtCosts::storage_large_read_overhead_byte => {
445                Parameter::WasmStorageLargeReadOverheadByte
446            }
447            ExtCosts::storage_remove_base => Parameter::WasmStorageRemoveBase,
448            ExtCosts::storage_remove_key_byte => Parameter::WasmStorageRemoveKeyByte,
449            ExtCosts::storage_remove_ret_value_byte => Parameter::WasmStorageRemoveRetValueByte,
450            ExtCosts::storage_has_key_base => Parameter::WasmStorageHasKeyBase,
451            ExtCosts::storage_has_key_byte => Parameter::WasmStorageHasKeyByte,
452            ExtCosts::storage_iter_create_prefix_base => Parameter::WasmStorageIterCreatePrefixBase,
453            ExtCosts::storage_iter_create_prefix_byte => Parameter::WasmStorageIterCreatePrefixByte,
454            ExtCosts::storage_iter_create_range_base => Parameter::WasmStorageIterCreateRangeBase,
455            ExtCosts::storage_iter_create_from_byte => Parameter::WasmStorageIterCreateFromByte,
456            ExtCosts::storage_iter_create_to_byte => Parameter::WasmStorageIterCreateToByte,
457            ExtCosts::storage_iter_next_base => Parameter::WasmStorageIterNextBase,
458            ExtCosts::storage_iter_next_key_byte => Parameter::WasmStorageIterNextKeyByte,
459            ExtCosts::storage_iter_next_value_byte => Parameter::WasmStorageIterNextValueByte,
460            ExtCosts::touching_trie_node => Parameter::WasmTouchingTrieNode,
461            ExtCosts::read_cached_trie_node => Parameter::WasmReadCachedTrieNode,
462            ExtCosts::promise_and_base => Parameter::WasmPromiseAndBase,
463            ExtCosts::promise_and_per_promise => Parameter::WasmPromiseAndPerPromise,
464            ExtCosts::promise_return => Parameter::WasmPromiseReturn,
465            ExtCosts::validator_stake_base => Parameter::WasmValidatorStakeBase,
466            ExtCosts::validator_total_stake_base => Parameter::WasmValidatorTotalStakeBase,
467            ExtCosts::alt_bn128_g1_multiexp_base => Parameter::WasmAltBn128G1MultiexpBase,
468            ExtCosts::alt_bn128_g1_multiexp_element => Parameter::WasmAltBn128G1MultiexpElement,
469            ExtCosts::alt_bn128_pairing_check_base => Parameter::WasmAltBn128PairingCheckBase,
470            ExtCosts::alt_bn128_pairing_check_element => Parameter::WasmAltBn128PairingCheckElement,
471            ExtCosts::alt_bn128_g1_sum_base => Parameter::WasmAltBn128G1SumBase,
472            ExtCosts::alt_bn128_g1_sum_element => Parameter::WasmAltBn128G1SumElement,
473            ExtCosts::yield_create_base => Parameter::WasmYieldCreateBase,
474            ExtCosts::yield_create_byte => Parameter::WasmYieldCreateByte,
475            ExtCosts::yield_create_with_id_base => Parameter::WasmYieldCreateWithIdBase,
476            ExtCosts::yield_resume_base => Parameter::WasmYieldResumeBase,
477            ExtCosts::yield_resume_byte => Parameter::WasmYieldResumeByte,
478            ExtCosts::bls12381_p1_sum_base => Parameter::WasmBls12381P1SumBase,
479            ExtCosts::bls12381_p1_sum_element => Parameter::WasmBls12381P1SumElement,
480            ExtCosts::bls12381_p2_sum_base => Parameter::WasmBls12381P2SumBase,
481            ExtCosts::bls12381_p2_sum_element => Parameter::WasmBls12381P2SumElement,
482            ExtCosts::bls12381_g1_multiexp_base => Parameter::WasmBls12381G1MultiexpBase,
483            ExtCosts::bls12381_g1_multiexp_element => Parameter::WasmBls12381G1MultiexpElement,
484            ExtCosts::bls12381_g2_multiexp_base => Parameter::WasmBls12381G2MultiexpBase,
485            ExtCosts::bls12381_g2_multiexp_element => Parameter::WasmBls12381G2MultiexpElement,
486            ExtCosts::bls12381_map_fp_to_g1_base => Parameter::WasmBls12381MapFpToG1Base,
487            ExtCosts::bls12381_map_fp_to_g1_element => Parameter::WasmBls12381MapFpToG1Element,
488            ExtCosts::bls12381_map_fp2_to_g2_base => Parameter::WasmBls12381MapFp2ToG2Base,
489            ExtCosts::bls12381_map_fp2_to_g2_element => Parameter::WasmBls12381MapFp2ToG2Element,
490            ExtCosts::bls12381_pairing_base => Parameter::WasmBls12381PairingBase,
491            ExtCosts::bls12381_pairing_element => Parameter::WasmBls12381PairingElement,
492            ExtCosts::bls12381_p1_decompress_base => Parameter::WasmBls12381P1DecompressBase,
493            ExtCosts::bls12381_p1_decompress_element => Parameter::WasmBls12381P1DecompressElement,
494            ExtCosts::bls12381_p2_decompress_base => Parameter::WasmBls12381P2DecompressBase,
495            ExtCosts::bls12381_p2_decompress_element => Parameter::WasmBls12381P2DecompressElement,
496        }
497    }
498}
499
500/// Signature scheme of a transaction (or delegate-action) signer, used as the
501/// key for per-scheme verification-cost lookups. Mirrors the schemes in
502/// `near_crypto::KeyType`; kept here (rather than reusing `KeyType`) so that
503/// `near-parameters` need not depend on `near-crypto`. Convert with the
504/// `KeyType -> SignatureKind` match at the runtime call site.
505///
506/// To price a future scheme (more ML-DSA bits, hash-based schemes, ...): add
507/// the `KeyType`, add a variant here, and add a `<scheme>_verification_cost`
508/// runtime parameter; the compiler then forces wiring the new entry into the
509/// cost map in `parameter_table.rs`.
510#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, enum_map::Enum)]
511pub enum SignatureKind {
512    Ed25519,
513    Secp256k1,
514    MlDsa65,
515}
516
517#[derive(Debug, Clone, Hash, PartialEq, Eq)]
518pub struct RuntimeFeesConfig {
519    /// Gas fees for sending and executing actions.
520    pub action_fees: EnumMap<ActionCosts, Fee>,
521
522    /// Describes fees for storage.
523    pub storage_usage_config: StorageUsageConfig,
524
525    /// Fraction of the burnt gas to reward to the contract account for execution.
526    pub burnt_gas_reward: Rational32,
527
528    /// Pessimistic gas price inflation ratio.
529    pub pessimistic_gas_price_inflation_ratio: Rational32,
530
531    /// Relative cost for gas refunds as a ratio of the refunded amount.
532    ///
533    /// The actual penalty is
534    /// `max(gross_refund * gas_refund_penalty, min_gas_refund_penalty)`
535    ///
536    /// Added with [NEP-536](https://github.com/near/NEPs/pull/536)
537    pub gas_refund_penalty: Rational32,
538    /// Minimum cost for gas refunds.
539    ///
540    /// The actual penalty is
541    /// `max(gross_refund * gas_refund_penalty, min_gas_refund_penalty)`
542    ///
543    /// Added with [NEP-536](https://github.com/near/NEPs/pull/536)
544    pub min_gas_refund_penalty: Gas,
545
546    /// Compute cost charged when applying a `GlobalContractDistribution`
547    /// receipt on the receiver shard (covers precompilation overhead).
548    pub deploy_global_contract_execution_base: Compute,
549    /// Per-byte compute cost charged when applying a
550    /// `GlobalContractDistribution` receipt, scaled by deployed code size.
551    pub deploy_global_contract_execution_per_byte: Compute,
552
553    /// Gas and compute cost charged at transaction conversion for each
554    /// signature the transaction triggers verification of, keyed by signature
555    /// scheme: the signer's own signature, plus each `Delegate` action's inner
556    /// signer. This is the *extra* verification cost of a scheme relative to
557    /// the classical schemes (whose verification is part of
558    /// `action_receipt_creation`). ed25519/secp256k1 stay 0 for backwards
559    /// compatibility; only ML-DSA-65 carries a charge. The signer pays it as
560    /// burnt gas when buying the transaction; receipts created from within
561    /// contracts are unaffected (no signing there). All 0 before
562    /// `PostQuantumSignatures`.
563    pub signature_verification_costs: EnumMap<SignatureKind, ParameterCost>,
564}
565
566/// Describes cost of storage per block
567#[derive(Debug, Clone, Hash, PartialEq, Eq)]
568pub struct StorageUsageConfig {
569    /// Amount of yN per byte required to have on the account. See
570    /// <https://nomicon.io/Economics/Economics.html#state-stake> for details.
571    pub storage_amount_per_byte: Balance,
572    /// Number of bytes for an account record, including rounding up for account id.
573    pub num_bytes_account: u64,
574    /// Additional number of bytes for a k/v record
575    pub num_extra_bytes_record: u64,
576    /// Amount of yN burned per byte of deployed Global Contract code.
577    pub global_contract_storage_amount_per_byte: Balance,
578}
579
580impl RuntimeFeesConfig {
581    /// Access action fee by `ActionCosts`.
582    pub fn fee(&self, cost: ActionCosts) -> &Fee {
583        &self.action_fees[cost]
584    }
585
586    /// Convenience constructor to use in tests where the exact gas cost does
587    /// not need to correspond to a specific protocol version.
588    pub fn test_with_undercharging_factor(factor: u64) -> Self {
589        // Once `ProtocolFeature::AccountCostIncrease` is enabled the test config has to keep the invariant
590        // `min_gas_purchase_price * create_account.exec >= account_creation_charge` satisfied,
591        // so the `create_account` fee is aligned with the real mainnet protocol values. With the
592        // feature disabled we keep the historical `Fee::test_value(3_850_000_000_000)` so
593        // pre-feature test expectations are unchanged.
594        let create_account_fee =
595            if near_primitives_core::version::ProtocolFeature::AccountCostIncrease
596                .enabled(near_primitives_core::version::PROTOCOL_VERSION)
597            {
598                Fee::test_value_detailed(
599                    500_000_000_000,
600                    500_000_000_000,
601                    7_200_000_000_000,
602                    factor,
603                )
604            } else {
605                Fee::test_value(3_850_000_000_000, factor)
606            };
607        Self {
608            storage_usage_config: StorageUsageConfig::test(),
609            burnt_gas_reward: Rational32::new(3, 10),
610            pessimistic_gas_price_inflation_ratio: Rational32::new(103, 100),
611            gas_refund_penalty: Rational32::new(5, 100),
612            min_gas_refund_penalty: Gas::from_teragas(1),
613            action_fees: enum_map::enum_map! {
614                ActionCosts::create_account => create_account_fee.clone(),
615                ActionCosts::delete_account => Fee::test_value(147489000000, factor),
616                ActionCosts::deploy_contract_base => Fee::test_value(184765750000, factor),
617                ActionCosts::deploy_contract_byte => Fee::test_value(6812999, factor),
618                ActionCosts::function_call_base => Fee::test_value(2319861500000, factor),
619                ActionCosts::function_call_byte => Fee::test_value(2235934, factor),
620                ActionCosts::transfer => Fee::test_value(115123062500, factor),
621                ActionCosts::stake => Fee::new(141715687500, 141715687500, 102217625000),
622                ActionCosts::add_full_access_key => Fee::test_value(101765125000, factor),
623                ActionCosts::add_function_call_key_base => Fee::test_value(102217625000, factor),
624                ActionCosts::add_function_call_key_byte => Fee::test_value(1925331, factor),
625                ActionCosts::delete_key => Fee::test_value(94946625000, factor),
626                ActionCosts::new_action_receipt => Fee::test_value(108059500000, factor),
627                ActionCosts::new_data_receipt_base => Fee::test_value(4697339419375, factor),
628                ActionCosts::new_data_receipt_byte => Fee::test_value(59357464, factor),
629                ActionCosts::delegate => Fee::test_value(200_000_000_000, factor),
630                ActionCosts::deploy_global_contract_base => Fee::test_value(184_765_750_000, factor),
631                ActionCosts::deploy_global_contract_byte => Fee::new(6_812_999, 6_812_999, 70_000_000),
632                ActionCosts::use_global_contract_base => Fee::test_value(184_765_750_000, factor),
633                ActionCosts::use_global_contract_byte => Fee::new(6_812_999, 47_683_715, 64_572_944),
634                ActionCosts::deterministic_state_init_base => Fee::new(3_850_000_000_000, 3_850_000_000_000, 4_080_000_000_000),
635                ActionCosts::deterministic_state_init_byte => Fee::new(72_000_000, 72_000_000, 70_000_000),
636                ActionCosts::deterministic_state_init_entry => Fee::new(0, 0, 200_000_000_000),
637                ActionCosts::gas_key_transfer_base => Fee::new(115_123_062_500, 115_123_062_500, 235_676_644_250),
638                ActionCosts::gas_key_byte => Fee::new(59_357_464, 59_357_464, 101_435_400),
639                ActionCosts::gas_key_nonce_write_base => Fee::new(0, 0, 64_196_736_000),
640            },
641            deploy_global_contract_execution_base: 0,
642            deploy_global_contract_execution_per_byte: 0,
643            signature_verification_costs: enum_map::enum_map! { _ => ParameterCost::ZERO },
644        }
645    }
646
647    /// `test_with_undercharging_factor` with a factor of 1.
648    pub fn test() -> RuntimeFeesConfig {
649        Self::test_with_undercharging_factor(1)
650    }
651
652    pub fn free() -> Self {
653        Self {
654            action_fees: enum_map::enum_map! {
655                _ => Fee::new(0, 0, 0)
656            },
657            storage_usage_config: StorageUsageConfig::free(),
658            burnt_gas_reward: Rational32::from_integer(0),
659            pessimistic_gas_price_inflation_ratio: Rational32::from_integer(0),
660            gas_refund_penalty: Rational32::from_integer(0),
661            min_gas_refund_penalty: Gas::ZERO,
662            deploy_global_contract_execution_base: 0,
663            deploy_global_contract_execution_per_byte: 0,
664            signature_verification_costs: enum_map::enum_map! { _ => ParameterCost::ZERO },
665        }
666    }
667
668    /// The minimum amount of gas required to create and execute a new receipt with a function call
669    /// action.
670    /// This amount is used to determine how many receipts can be created, send and executed for
671    /// some amount of prepaid gas using function calls.
672    pub fn min_receipt_with_function_call_gas(&self) -> Gas {
673        self.fee(ActionCosts::new_action_receipt)
674            .min_send_and_exec_fee()
675            .checked_add(self.fee(ActionCosts::function_call_base).min_send_and_exec_fee())
676            .unwrap()
677    }
678
679    /// Given a left over gas amount to be refunded, returns how much should be
680    /// subtracted as a penalty introduced with NEP-536.
681    ///
682    /// Must return a value smaller or equal to the `gas_refund` parameter.
683    pub fn gas_penalty_for_gas_refund(&self, gas_refund: Gas) -> Gas {
684        let relative_cost = Gas::from_gas(
685            (u128::from(gas_refund.as_gas()) * *self.gas_refund_penalty.numer() as u128
686                / *self.gas_refund_penalty.denom() as u128)
687                .try_into()
688                .unwrap(),
689        );
690
691        let penalty = std::cmp::max(relative_cost, self.min_gas_refund_penalty);
692        std::cmp::min(penalty, gas_refund)
693    }
694}
695
696impl StorageUsageConfig {
697    pub fn test() -> Self {
698        Self {
699            num_bytes_account: 100,
700            num_extra_bytes_record: 40,
701            storage_amount_per_byte: Balance::from_yoctonear(909 * 100_000_000_000_000_000),
702            global_contract_storage_amount_per_byte: Balance::from_yoctonear(
703                100_000_000_000_000_000_000,
704            ),
705        }
706    }
707
708    pub(crate) fn free() -> StorageUsageConfig {
709        Self {
710            num_bytes_account: 0,
711            num_extra_bytes_record: 0,
712            storage_amount_per_byte: Balance::ZERO,
713            global_contract_storage_amount_per_byte: Balance::ZERO,
714        }
715    }
716}
717
718/// Helper functions for computing Transfer fees.
719/// In case of implicit account creation they include extra fees for the CreateAccount and
720/// AddFullAccessKey (for NEAR-implicit account only) actions that are implicit.
721/// We can assume that no overflow will happen here.
722pub fn transfer_exec_fee(
723    cfg: &RuntimeFeesConfig,
724    eth_implicit_accounts_enabled: bool,
725    receiver_account_type: AccountType,
726) -> ParameterCost {
727    let transfer_fee = cfg.fee(ActionCosts::transfer).exec_fee();
728    match (eth_implicit_accounts_enabled, receiver_account_type) {
729        // Regular transfer to a named account.
730        (_, AccountType::NamedAccount) => transfer_fee,
731        // No account will be created, just a regular transfer.
732        (false, AccountType::EthImplicitAccount) => transfer_fee,
733        // Extra fee for the CreateAccount.
734        (true, AccountType::EthImplicitAccount) => {
735            transfer_fee.checked_add(cfg.fee(ActionCosts::create_account).exec_fee()).unwrap()
736        }
737        // Extra fees for the CreateAccount and AddFullAccessKey.
738        (_, AccountType::NearImplicitAccount) => transfer_fee
739            .checked_add(cfg.fee(ActionCosts::create_account).exec_fee())
740            .unwrap()
741            .checked_add(cfg.fee(ActionCosts::add_full_access_key).exec_fee())
742            .unwrap(),
743        // Extra fees for the implied CreateAccount action.
744        (_, AccountType::NearDeterministicAccount) => {
745            transfer_fee.checked_add(cfg.fee(ActionCosts::create_account).exec_fee()).unwrap()
746        }
747    }
748}
749
750pub fn transfer_send_fee(
751    cfg: &RuntimeFeesConfig,
752    sender_is_receiver: bool,
753    eth_implicit_accounts_enabled: bool,
754    receiver_account_type: AccountType,
755) -> ParameterCost {
756    let transfer_fee = cfg.fee(ActionCosts::transfer).send_fee(sender_is_receiver);
757    match (eth_implicit_accounts_enabled, receiver_account_type) {
758        // Regular transfer to a named account.
759        (_, AccountType::NamedAccount) => transfer_fee,
760        // No account will be created, just a regular transfer.
761        (false, AccountType::EthImplicitAccount) => transfer_fee,
762        // Extra fee for the CreateAccount.
763        (true, AccountType::EthImplicitAccount) => transfer_fee
764            .checked_add(cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver))
765            .unwrap(),
766        // Extra fees for the CreateAccount and AddFullAccessKey.
767        (_, AccountType::NearImplicitAccount) => transfer_fee
768            .checked_add(cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver))
769            .unwrap()
770            .checked_add(cfg.fee(ActionCosts::add_full_access_key).send_fee(sender_is_receiver))
771            .unwrap(),
772        // Extra fees for the implied  CreateAccount action.
773        (_, AccountType::NearDeterministicAccount) => transfer_fee
774            .checked_add(cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver))
775            .unwrap(),
776    }
777}
778
779/// Gas fee split into base and per-byte components, so callers can attribute
780/// them to separate `ActionCosts` in the gas profile.
781pub struct GasKeyTransferFee {
782    pub base: ParameterCost,
783    pub per_byte: ParameterCost,
784}
785
786impl GasKeyTransferFee {
787    pub fn total(&self) -> ParameterCost {
788        self.base.checked_add(self.per_byte).unwrap()
789    }
790}
791
792/// Send fee for TransferToGasKey / WithdrawFromGasKey actions.
793/// Based on the public key length (what the sender sees).
794pub fn gas_key_transfer_send_fee(
795    cfg: &RuntimeFeesConfig,
796    sender_is_receiver: bool,
797    public_key_len: usize,
798) -> GasKeyTransferFee {
799    let base = cfg.fee(ActionCosts::gas_key_transfer_base).send_fee(sender_is_receiver);
800    let per_byte = cfg
801        .fee(ActionCosts::gas_key_byte)
802        .send_fee(sender_is_receiver)
803        .checked_mul(public_key_len as u64)
804        .unwrap();
805    GasKeyTransferFee { base, per_byte }
806}
807
808/// Exec fee for TransferToGasKey / WithdrawFromGasKey actions.
809/// Based on the access key trie key length + estimated value length (what the
810/// receiver needs to read/write in the trie).
811pub fn gas_key_transfer_exec_fee(
812    cfg: &RuntimeFeesConfig,
813    account_id_len: usize,
814    public_key_len: usize,
815) -> GasKeyTransferFee {
816    let base = cfg.fee(ActionCosts::gas_key_transfer_base).exec_fee();
817    let trie_key_len = access_key_key_len(account_id_len, public_key_len);
818    let estimated_value_len = AccessKey::min_gas_key_borsh_len();
819    let per_byte = cfg
820        .fee(ActionCosts::gas_key_byte)
821        .exec_fee()
822        .checked_mul((trie_key_len + estimated_value_len) as u64)
823        .unwrap();
824    GasKeyTransferFee { base, per_byte }
825}
826
827/// Additional costs for adding an access key with GasKeyFunctionCall or
828/// GasKeyFullAccess permissions, split into base (`gas_key_nonce_write_base`)
829/// and per-byte (`gas_key_byte`) components.
830pub struct GasKeyAddFee {
831    pub base: ParameterCost,
832    pub per_byte: ParameterCost,
833}
834
835impl GasKeyAddFee {
836    pub fn total(&self) -> ParameterCost {
837        self.base.checked_add(self.per_byte).unwrap()
838    }
839}
840
841/// Additional send fee for gas_key_byte when adding a gas key (AddKey with
842/// GasKeyFullAccess or GasKeyFunctionCall permission). Covers the serialized
843/// GasKeyInfo bytes.
844pub fn gas_key_add_key_send_fee(
845    cfg: &RuntimeFeesConfig,
846    sender_is_receiver: bool,
847) -> ParameterCost {
848    cfg.fee(ActionCosts::gas_key_byte)
849        .send_fee(sender_is_receiver)
850        .checked_mul(GasKeyInfo::borsh_len() as u64)
851        .unwrap()
852}
853
854/// Exec fee when adding a gas key with `num_nonces` nonces, split into base
855/// and per-byte components. Each nonce writes a trie entry of
856/// (access_key_key_len + NonceIndex) key bytes and NONCE_VALUE_LEN value bytes.
857pub fn gas_key_add_key_exec_fee(
858    cfg: &RuntimeFeesConfig,
859    account_id_len: usize,
860    public_key_len: usize,
861    num_nonces: NonceIndex,
862) -> GasKeyAddFee {
863    let num_nonces = num_nonces as u64;
864    let base =
865        cfg.fee(ActionCosts::gas_key_nonce_write_base).exec_fee().checked_mul(num_nonces).unwrap();
866    let nonce_key_len =
867        access_key_key_len(account_id_len, public_key_len) + std::mem::size_of::<NonceIndex>();
868    let per_byte = cfg
869        .fee(ActionCosts::gas_key_byte)
870        .exec_fee()
871        .checked_mul((nonce_key_len + AccessKey::NONCE_VALUE_LEN) as u64)
872        .unwrap()
873        .checked_mul(num_nonces)
874        .unwrap();
875    GasKeyAddFee { base, per_byte }
876}