arb_evm/multi_gas/
intrinsic.rs1use arb_primitives::multigas::{MultiGas, ResourceKind};
8
9const TX_GAS: u64 = 21_000;
10const TX_GAS_CREATE: u64 = 53_000;
11const TX_DATA_NONZERO: u64 = 16; const TX_DATA_ZERO: u64 = 4; const INIT_CODE_WORD: u64 = 2; const ACCESS_LIST_ADDRESS: u64 = 2_400; const ACCESS_LIST_KEY: u64 = 1_900; const AUTH_ACCOUNT: u64 = 25_000; #[derive(Debug, Clone, Copy)]
20pub struct IntrinsicInput {
21 pub is_create: bool,
22 pub zero_bytes: u64,
23 pub nonzero_bytes: u64,
24 pub init_code_words: u64,
25 pub access_list_addresses: u64,
26 pub access_list_keys: u64,
27 pub auth_list_len: u64,
28}
29
30pub fn intrinsic_multigas(input: IntrinsicInput) -> MultiGas {
34 let base = if input.is_create {
35 TX_GAS_CREATE
36 } else {
37 TX_GAS
38 };
39 let init_code = if input.is_create {
40 input.init_code_words * INIT_CODE_WORD
41 } else {
42 0
43 };
44 let calldata = input.nonzero_bytes * TX_DATA_NONZERO + input.zero_bytes * TX_DATA_ZERO;
45 let access = input.access_list_addresses * ACCESS_LIST_ADDRESS
46 + input.access_list_keys * ACCESS_LIST_KEY;
47 let auth = input.auth_list_len * AUTH_ACCOUNT;
48
49 MultiGas::from_pairs(&[
50 (ResourceKind::Computation, base + init_code),
51 (ResourceKind::L2Calldata, calldata),
52 (ResourceKind::StorageAccessRead, access),
53 (ResourceKind::StorageGrowth, auth),
54 ])
55}
56
57#[cfg(test)]
58mod tests {
59 use arb_primitives::multigas::ResourceKind::*;
60
61 use super::*;
62
63 fn input() -> IntrinsicInput {
64 IntrinsicInput {
65 is_create: false,
66 zero_bytes: 0,
67 nonzero_bytes: 0,
68 init_code_words: 0,
69 access_list_addresses: 0,
70 access_list_keys: 0,
71 auth_list_len: 0,
72 }
73 }
74
75 #[test]
76 fn bare_call() {
77 let mg = intrinsic_multigas(input());
78 assert_eq!(mg.get(Computation), 21_000);
79 assert_eq!(mg.single_gas(), 21_000);
80 }
81
82 #[test]
83 fn calldata_goes_to_l2_calldata() {
84 let mg = intrinsic_multigas(IntrinsicInput {
85 zero_bytes: 5,
86 nonzero_bytes: 10,
87 ..input()
88 });
89 assert_eq!(mg.get(Computation), 21_000);
90 assert_eq!(mg.get(L2Calldata), 10 * 16 + 5 * 4);
91 assert_eq!(mg.single_gas(), 21_000 + 180);
92 }
93
94 #[test]
95 fn creation_base_and_init_words() {
96 let mg = intrinsic_multigas(IntrinsicInput {
97 is_create: true,
98 init_code_words: 7,
99 ..input()
100 });
101 assert_eq!(mg.get(Computation), 53_000 + 7 * 2);
102 }
103
104 #[test]
105 fn access_list_is_storage_read() {
106 let mg = intrinsic_multigas(IntrinsicInput {
107 access_list_addresses: 2,
108 access_list_keys: 3,
109 ..input()
110 });
111 assert_eq!(mg.get(StorageAccessRead), 2 * 2_400 + 3 * 1_900);
112 }
113
114 #[test]
115 fn auth_list_is_storage_growth() {
116 let mg = intrinsic_multigas(IntrinsicInput {
117 auth_list_len: 2,
118 ..input()
119 });
120 assert_eq!(mg.get(StorageGrowth), 2 * 25_000);
121 }
122}