Skip to content

Commit ad3ff13

Browse files
authored
Use functions from blockifier to calculate used gas (#1607)
<!-- Reference any GitHub issues resolved by this PR --> Closes #1445 ## Introduced changes <!-- A brief description of the changes --> - `calculate_tx_gas_usage` function is used to calculate onchain gas usage ## Checklist <!-- Make sure all of these are complete --> - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md`
1 parent dc2bc13 commit ad3ff13

File tree

3 files changed

+69
-67
lines changed

3 files changed

+69
-67
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Forge
11+
12+
#### Changed
13+
14+
- Gas estimation is now aligned with the Starknet v0.13
15+
1016
## [0.16.0] - 2024-01-26
1117

1218
### Forge

crates/forge-runner/src/gas.rs

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use std::collections::HashMap;
22

33
use crate::test_case_summary::{Single, TestCaseSummary};
4-
use blockifier::fee::eth_gas_constants;
54
use blockifier::fee::fee_utils::calculate_tx_l1_gas_usage;
6-
use blockifier::fee::gas_usage::get_message_segment_length;
5+
use blockifier::fee::gas_usage::calculate_tx_gas_usage;
76
use blockifier::fee::os_resources::OS_RESOURCES;
87
use blockifier::fee::os_usage::get_additional_os_resources;
98
use blockifier::state::cached_state::{CachedState, StateChangesCount};
@@ -33,12 +32,14 @@ pub fn calculate_used_gas(
3332
// which we don't want to include in gas cost
3433
state_changes.compiled_class_hash_updates.clear();
3534

36-
let l1_gas_usage = get_l1_gas_usage(
35+
let l1_gas_usage = calculate_tx_gas_usage(
3736
&resources.l2_to_l1_payloads_length,
3837
StateChangesCount::from(&state_changes),
38+
None,
3939
);
4040

4141
let resource_mapping = used_resources_to_resource_mapping(&total_vm_usage, l1_gas_usage);
42+
4243
calculate_tx_l1_gas_usage(&resource_mapping, block_context)
4344
.expect("Calculating gas failed, some resources were not included.")
4445
}
@@ -77,35 +78,6 @@ fn get_total_vm_usage(resources: &ExecutionResources) -> VmExecutionResources {
7778
total_vm_usage.filter_unused_builtins()
7879
}
7980

80-
fn get_l1_gas_usage(
81-
l2_to_l1_payloads_length: &[usize],
82-
state_changes_count: StateChangesCount,
83-
) -> usize {
84-
let message_segment_length = get_message_segment_length(l2_to_l1_payloads_length, None);
85-
let onchain_data_segment_length = get_onchain_data_segment_length(state_changes_count);
86-
87-
message_segment_length * eth_gas_constants::SHARP_GAS_PER_MEMORY_WORD
88-
+ onchain_data_segment_length * eth_gas_constants::SHARP_GAS_PER_MEMORY_WORD
89-
}
90-
91-
// TODO::copied from blockifier, because it became private
92-
fn get_onchain_data_segment_length(state_changes_count: StateChangesCount) -> usize {
93-
// For each newly modified contract:
94-
// contract address (1 word).
95-
// + 1 word with the following info: A flag indicating whether the class hash was updated, the
96-
// number of entry updates, and the new nonce.
97-
let mut onchain_data_segment_length = state_changes_count.n_modified_contracts * 2;
98-
// For each class updated (through a deploy or a class replacement).
99-
onchain_data_segment_length +=
100-
state_changes_count.n_class_hash_updates * constants::CLASS_UPDATE_SIZE;
101-
// For each modified storage cell: key, new value.
102-
onchain_data_segment_length += state_changes_count.n_storage_updates * 2;
103-
// For each compiled class updated (through declare): class_hash, compiled_class_hash
104-
onchain_data_segment_length += state_changes_count.n_compiled_class_hash_updates * 2;
105-
106-
onchain_data_segment_length
107-
}
108-
10981
pub fn check_available_gas(
11082
available_gas: &Option<usize>,
11183
summary: TestCaseSummary<Single>,

crates/forge/tests/integration/gas.rs

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use test_utils::runner::Contract;
44
use test_utils::running_tests::run_test_case;
55
use test_utils::{assert_gas, assert_passed, test_case};
66

7-
// gas values comes from https://book.starknet.io/ch03-01-02-fee-mechanism.html#computation
7+
// all calculations are based on formula from
8+
// https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/fee-mechanism/#overall_fee
9+
810
#[test]
911
fn declare_cost_is_omitted() {
1012
let test = test_case!(
@@ -32,7 +34,6 @@ fn declare_cost_is_omitted() {
3234
assert_gas!(result, "declare_cost_is_omitted", 1);
3335
}
3436

35-
// FIXME(#1596): Code (steps) was added but the cost did not change
3637
#[test]
3738
fn deploy_syscall_cost() {
3839
let test = test_case!(
@@ -59,10 +60,39 @@ fn deploy_syscall_cost() {
5960
let result = run_test_case(&test);
6061

6162
assert_passed!(result);
62-
// 1224 = 2 * cost per 32-byte word (contract_address and contract modification info)
63-
// 612 = updated class_hash (through deploy)
6463
// 6 = gas cost from steps
65-
assert_gas!(result, "deploy_syscall_cost", 1224 + 612 + 6);
64+
// 1101 = gas cost of onchain data (deploy cost)
65+
assert_gas!(result, "deploy_syscall_cost", 6 + 1101);
66+
}
67+
68+
#[test]
69+
fn snforge_std_deploy_cost() {
70+
let test = test_case!(
71+
indoc!(
72+
r"
73+
use snforge_std::{ declare, ContractClassTrait };
74+
75+
#[test]
76+
fn deploy_cost() {
77+
let contract = declare('GasChecker');
78+
let address = contract.deploy(@array![]).unwrap();
79+
assert(address != 0.try_into().unwrap(), 'wrong deployed addr');
80+
}
81+
"
82+
),
83+
Contract::from_code_path(
84+
"GasChecker".to_string(),
85+
Path::new("tests/data/contracts/gas_checker.cairo"),
86+
)
87+
.unwrap()
88+
);
89+
90+
let result = run_test_case(&test);
91+
92+
assert_passed!(result);
93+
// 2 = gas cost from steps
94+
// 1101 = gas cost of onchain data (deploy cost)
95+
assert_gas!(result, "deploy_cost", 2 + 1101);
6696
}
6797

6898
#[test]
@@ -114,9 +144,9 @@ fn contract_keccak_cost() {
114144
let result = run_test_case(&test);
115145

116146
assert_passed!(result);
117-
// 1836 = 3 * cost per 32-byte word (deploy)
147+
// 1101 = cost of deploy (see snforge_std_deploy_cost test)
118148
// 11 = cost of single keccak builtin
119-
assert_gas!(result, "contract_keccak_cost", 1836 + 11);
149+
assert_gas!(result, "contract_keccak_cost", 1101 + 11);
120150
}
121151

122152
#[test]
@@ -172,9 +202,9 @@ fn contract_range_check_cost() {
172202
let result = run_test_case(&test);
173203

174204
assert_passed!(result);
175-
// 1836 = 3 * cost per 32-byte word (deploy)
205+
// 1101 = cost of deploy (see snforge_std_deploy_cost test)
176206
// 2 = cost of 22 range check builtins
177-
assert_gas!(result, "contract_range_check_cost", 1836 + 2);
207+
assert_gas!(result, "contract_range_check_cost", 1101 + 2);
178208
}
179209

180210
#[test]
@@ -228,9 +258,9 @@ fn contract_bitwise_cost() {
228258
let result = run_test_case(&test);
229259

230260
assert_passed!(result);
231-
// 1836 = 3 * cost per 32-byte word (deploy)
261+
// 1101 = cost of deploy (see snforge_std_deploy_cost test)
232262
// 2 = cost of 6 bitwise builtins
233-
assert_gas!(result, "contract_bitwise_cost", 1836 + 2);
263+
assert_gas!(result, "contract_bitwise_cost", 1101 + 2);
234264
}
235265

236266
#[test]
@@ -284,9 +314,9 @@ fn contract_pedersen_cost() {
284314
let result = run_test_case(&test);
285315

286316
assert_passed!(result);
287-
// 1836 = 3 * cost per 32-byte word (deploy)
317+
// 1101 = cost of deploy (see snforge_std_deploy_cost test)
288318
// 2 = cost of 12 pedersen builtins
289-
assert_gas!(result, "contract_pedersen_cost", 1836 + 2);
319+
assert_gas!(result, "contract_pedersen_cost", 1101 + 2);
290320
}
291321

292322
#[test]
@@ -340,9 +370,9 @@ fn contract_poseidon_cost() {
340370
let result = run_test_case(&test);
341371

342372
assert_passed!(result);
343-
// 1836 = 3 * cost per 32-byte word (deploy)
373+
// 1101 = cost of deploy (see snforge_std_deploy_cost test)
344374
// 2 = cost of 12 poseidon builtins
345-
assert_gas!(result, "contract_poseidon_cost", 1836 + 2);
375+
assert_gas!(result, "contract_poseidon_cost", 1101 + 2);
346376
}
347377

348378
#[test]
@@ -397,9 +427,9 @@ fn contract_ec_op_cost() {
397427
let result = run_test_case(&test);
398428

399429
assert_passed!(result);
400-
// 1836 = 3 * cost per 32-byte word (deploy)
430+
// 1101 = cost of deploy (see snforge_std_deploy_cost test)
401431
// 6 = cost of single ec_op builtin
402-
assert_gas!(result, "contract_ec_op_cost", 1836 + 6);
432+
assert_gas!(result, "contract_ec_op_cost", 1101 + 6);
403433
}
404434

405435
#[test]
@@ -434,10 +464,9 @@ fn storage_write_cost() {
434464
let result = run_test_case(&test);
435465

436466
assert_passed!(result);
437-
// 1836 = 3 * cost per 32-byte word (deploy)
438-
// 1224 = 2 * cost per 32-byte word (storage write)
439467
// 3 = gas cost of steps
440-
assert_gas!(result, "storage_write_cost", 1836 + 1224 + 3);
468+
// 2203 = gas cost of onchain data
469+
assert_gas!(result, "storage_write_cost", 3 + 2203);
441470
}
442471

443472
#[test]
@@ -465,10 +494,9 @@ fn storage_write_from_test_cost() {
465494
let result = run_test_case(&test);
466495

467496
assert_passed!(result);
468-
// 1224 = 2 * cost per 32-byte word (modified contract)
469-
// 1224 = 2 * cost per 32-byte word (storage write)
470497
// 1 = gas cost of steps
471-
assert_gas!(result, "storage_write_from_test_cost", 1224 + 1224 + 1);
498+
// 1652 = gas cost of onchain data
499+
assert_gas!(result, "storage_write_from_test_cost", 1 + 1652);
472500
}
473501

474502
#[test]
@@ -504,10 +532,9 @@ fn multiple_storage_writes_cost() {
504532
let result = run_test_case(&test);
505533

506534
assert_passed!(result);
507-
// 1836 = 3 * cost per 32-byte word (deploy)
508-
// 1224 = 2 * cost per 32-byte word (storage write)
509535
// 3 = gas cost of steps
510-
assert_gas!(result, "multiple_storage_writes_cost", 1836 + 1224 + 3);
536+
// 2203 = gas cost of onchain data
537+
assert_gas!(result, "multiple_storage_writes_cost", 3 + 2203);
511538
}
512539

513540
#[test]
@@ -542,10 +569,9 @@ fn l1_message_cost() {
542569
let result = run_test_case(&test);
543570

544571
assert_passed!(result);
545-
// 1836 = 3 * cost per 32-byte word (deploy)
546-
// 2448 = 4 * cost per 32-byte word (l2_l1_message, header is of length 3 and payload size is 1)
547572
// 3 = gas cost of steps
548-
assert_gas!(result, "l1_message_cost", 1836 + 2448 + 3);
573+
// 27865 = gas cost of onchain data
574+
assert_gas!(result, "l1_message_cost", 3 + 27865);
549575
}
550576

551577
#[test]
@@ -562,9 +588,9 @@ fn l1_message_from_test_cost() {
562588
let result = run_test_case(&test);
563589

564590
assert_passed!(result);
565-
// 2448 = 4 * cost per 32-byte word (l2_l1_message, header is of length 3 and payload size is 1)
566591
// 1 = gas cost of steps
567-
assert_gas!(result, "l1_message_from_test_cost", 2448 + 1);
592+
// 26764 = gas cost of onchain data
593+
assert_gas!(result, "l1_message_from_test_cost", 1 + 26764);
568594
}
569595

570596
#[test]
@@ -611,9 +637,7 @@ fn l1_message_cost_for_proxy() {
611637
let result = run_test_case(&test);
612638

613639
assert_passed!(result);
614-
// 1836 = 3 * cost per 32-byte word (deploy)
615-
// 1836 = 3 * cost per 32-byte word (deploy)
616-
// 2448 = 4 * cost per 32-byte word (l2_l1_message, header is of length 3 and payload size is 1)
617640
// 8 = gas cost of steps
618-
assert_gas!(result, "l1_message_cost_for_proxy", 1836 + 1836 + 2448 + 8);
641+
// 29206 = gas cost of onchain data
642+
assert_gas!(result, "l1_message_cost_for_proxy", 8 + 29206);
619643
}

0 commit comments

Comments
 (0)