1use wasmer::wasmparser::Operator;
38
39pub fn wasm_opcode_gas_schedule(operator: &Operator) -> u64 {
42 match operator {
43 Operator::I32Const { .. } | Operator::I64Const { .. } => 0,
45
46 Operator::Drop => 2,
48 Operator::Select => 3,
49
50 Operator::Nop
52 | Operator::Unreachable
53 | Operator::Loop { .. }
54 | Operator::Else
55 | Operator::If { .. } => 0,
56 Operator::Br { .. }
57 | Operator::BrTable { .. }
58 | Operator::Return
59 | Operator::Call { .. }
60 | Operator::CallIndirect { .. } => 2,
61 Operator::BrIf { .. } => 3,
62
63 Operator::GlobalGet { .. }
65 | Operator::GlobalSet { .. }
66 | Operator::LocalGet { .. }
67 | Operator::LocalSet { .. } => 3,
68
69 Operator::RefIsNull
71 | Operator::RefFunc { .. }
72 | Operator::RefNull { .. }
73 | Operator::ReturnCall { .. }
74 | Operator::ReturnCallIndirect { .. } => 2,
75
76 Operator::CatchAll
78 | Operator::Throw { .. }
79 | Operator::Rethrow { .. }
80 | Operator::Delegate { .. } => 2,
81
82 Operator::ElemDrop { .. } | Operator::DataDrop { .. } => 1,
84 Operator::TableInit { .. } => 2,
85 Operator::MemoryCopy { .. }
86 | Operator::MemoryFill { .. }
87 | Operator::TableCopy { .. }
88 | Operator::TableFill { .. } => 3,
89
90 Operator::I32Load { .. }
92 | Operator::I64Load { .. }
93 | Operator::I32Store { .. }
94 | Operator::I64Store { .. }
95 | Operator::I32Store8 { .. }
96 | Operator::I32Store16 { .. }
97 | Operator::I32Load8S { .. }
98 | Operator::I32Load8U { .. }
99 | Operator::I32Load16S { .. }
100 | Operator::I32Load16U { .. }
101 | Operator::I64Load8S { .. }
102 | Operator::I64Load8U { .. }
103 | Operator::I64Load16S { .. }
104 | Operator::I64Load16U { .. }
105 | Operator::I64Load32S { .. }
106 | Operator::I64Load32U { .. }
107 | Operator::I64Store8 { .. }
108 | Operator::I64Store16 { .. }
109 | Operator::I64Store32 { .. } => 3,
110
111 Operator::I32Add
113 | Operator::I32Sub
114 | Operator::I64Add
115 | Operator::I64Sub
116 | Operator::I64LtS
117 | Operator::I64LtU
118 | Operator::I64GtS
119 | Operator::I64GtU
120 | Operator::I64LeS
121 | Operator::I64LeU
122 | Operator::I64GeS
123 | Operator::I64GeU
124 | Operator::I32Eqz
125 | Operator::I32Eq
126 | Operator::I32Ne
127 | Operator::I32LtS
128 | Operator::I32LtU
129 | Operator::I32GtS
130 | Operator::I32GtU
131 | Operator::I32LeS
132 | Operator::I32LeU
133 | Operator::I32GeS
134 | Operator::I32GeU
135 | Operator::I64Eqz
136 | Operator::I64Eq
137 | Operator::I64Ne
138 | Operator::I32And
139 | Operator::I32Or
140 | Operator::I32Xor
141 | Operator::I64And
142 | Operator::I64Or
143 | Operator::I64Xor => 1,
144 Operator::I32Shl
145 | Operator::I32ShrU
146 | Operator::I32ShrS
147 | Operator::I32Rotl
148 | Operator::I32Rotr
149 | Operator::I64Shl
150 | Operator::I64ShrU
151 | Operator::I64ShrS
152 | Operator::I64Rotl
153 | Operator::I64Rotr => 2,
154 Operator::I32Mul | Operator::I64Mul => 3,
155 Operator::I32DivS
156 | Operator::I32DivU
157 | Operator::I32RemS
158 | Operator::I32RemU
159 | Operator::I64DivS
160 | Operator::I64DivU
161 | Operator::I64RemS
162 | Operator::I64RemU => 80,
163 Operator::I32Clz | Operator::I64Clz => 105,
164
165 Operator::I32WrapI64
167 | Operator::I64ExtendI32S
168 | Operator::I64ExtendI32U
169 | Operator::I32Extend8S
170 | Operator::I32Extend16S
171 | Operator::I64Extend8S
172 | Operator::I64Extend16S
173 | Operator::I64Extend32S => 3,
174
175 _ => 1,
177 }
178}
179
180pub const WASM_MEMORY_WRITE_PER64_BITS_COST: u64 = 3;
184pub const WASM_MEMORY_READ_PER64_BITS_COST: u64 = 3;
186pub const WASM_BYTE_CODE_PER_BYTE_COST: u64 = 3;
188
189pub const fn wasm_memory_read_cost(len: usize) -> u64 {
191 let cost = ceil_div_8(len as u64).saturating_mul(WASM_MEMORY_READ_PER64_BITS_COST);
192 if cost == 0 {
193 return 1;
194 } cost
196}
197
198pub const fn wasm_memory_write_cost(len: usize) -> u64 {
200 let cost = ceil_div_8(len as u64).saturating_mul(WASM_MEMORY_WRITE_PER64_BITS_COST);
201 if cost == 0 {
202 return 1;
203 } cost
205}
206
207pub const fn ceil_div_8(l: u64) -> u64 {
209 l.saturating_add(7).saturating_div(8)
210}
211
212pub const BLOCKCHAIN_WRITE_PER_BYTE_COST: u64 = 30;
216pub const MIN_RECP_SIZE: u64 = 4;
218pub const MIN_CMDRECP_SIZE: u64 = 17;
220
221pub fn tx_inclusion_cost(tx_size: usize, commands_len: usize) -> u64 {
232 let tx_size = tx_size as u64;
234 let min_receipt_size = minimum_receipt_size(commands_len);
236 let rw_key_cost = (
238 get_cost(ACCOUNT_STATE_KEY_LENGTH, 8)
240 .saturating_add(set_cost_write_new_value(8))
242 .saturating_add(set_cost_rehash(ACCOUNT_STATE_KEY_LENGTH))
243 )
244 .saturating_mul(5);
245
246 tx_size
248 .saturating_add(min_receipt_size)
249 .saturating_mul(BLOCKCHAIN_WRITE_PER_BYTE_COST)
250 .saturating_add(rw_key_cost)
251}
252
253pub const fn minimum_receipt_size(commands_len: usize) -> u64 {
255 MIN_RECP_SIZE.saturating_add(MIN_CMDRECP_SIZE.saturating_mul(commands_len as u64))
256}
257
258pub const fn blockchain_return_values_cost(data_len: usize) -> u64 {
260 (data_len as u64).saturating_mul(BLOCKCHAIN_WRITE_PER_BYTE_COST)
262}
263
264pub const fn blockchain_log_cost(topic_len: usize, val_len: usize) -> u64 {
266 let topic_len = topic_len as u64;
267 let val_len = val_len as u64;
268 let log_len = topic_len.saturating_add(val_len);
269
270 (ceil_div_8(log_len).saturating_mul(WASM_MEMORY_READ_PER64_BITS_COST))
272 .saturating_add(topic_len.saturating_mul(CRYPTO_SHA256_PER_BYTE))
274 .saturating_add(log_len.saturating_mul(BLOCKCHAIN_WRITE_PER_BYTE_COST))
276}
277
278pub const ACCOUNT_STATE_KEY_LENGTH: usize = 33;
282pub const MPT_WRITE_PER_BYTE_COST: u64 = 2500;
284pub const MPT_READ_PER_BYTE_COST: u64 = 50;
286pub const MPT_TRAVERSE_PER_BYTE_COST: u64 = 20;
288pub const MPT_REHASH_PER_BYTE_COST: u64 = 130;
291pub const MPT_WRITE_REFUND_PROPORTION: u64 = 50;
293pub const MPT_GET_CODE_DISCOUNT_PROPORTION: u64 = 50;
295
296pub const fn get_cost(key_len: usize, value_len: usize) -> u64 {
298 let get_cost_1 = (value_len as u64).saturating_mul(MPT_READ_PER_BYTE_COST);
299 let get_cost_2 = (key_len as u64).saturating_mul(MPT_TRAVERSE_PER_BYTE_COST);
300 get_cost_1.saturating_add(get_cost_2)
301}
302
303pub const fn get_code_cost(code_len: usize) -> u64 {
305 get_cost(ACCOUNT_STATE_KEY_LENGTH, code_len)
307 .saturating_mul(MPT_GET_CODE_DISCOUNT_PROPORTION)
309 .saturating_div(100)
310}
311
312pub const fn set_cost_read_key(key_len: usize, value_len: usize) -> u64 {
314 get_cost(key_len, value_len)
315}
316
317#[allow(clippy::double_comparisons)]
319pub const fn set_cost_delete_old_value(
320 key_len: usize,
321 old_val_len: usize,
322 new_val_len: usize,
323) -> u64 {
324 let old_val_len = old_val_len as u64; let new_val_len = new_val_len as u64; if (old_val_len > 0 || old_val_len == 0) && new_val_len > 0 {
328 old_val_len
330 .saturating_mul(MPT_WRITE_PER_BYTE_COST * MPT_WRITE_REFUND_PROPORTION)
331 .saturating_div(100)
332 } else if old_val_len > 0 && new_val_len == 0 {
333 ((key_len as u64).saturating_add(old_val_len))
335 .saturating_mul(MPT_WRITE_PER_BYTE_COST * MPT_WRITE_REFUND_PROPORTION)
336 .saturating_div(100)
337 } else {
338 0
340 }
341}
342
343pub const fn set_cost_write_new_value(new_val_len: usize) -> u64 {
345 (new_val_len as u64).saturating_mul(MPT_WRITE_PER_BYTE_COST)
347}
348
349pub const fn set_cost_rehash(key_len: usize) -> u64 {
351 (key_len as u64).saturating_mul(MPT_REHASH_PER_BYTE_COST)
353}
354
355pub const fn contains_cost(key_len: usize) -> u64 {
357 (key_len as u64).saturating_mul(MPT_TRAVERSE_PER_BYTE_COST)
358}
359
360pub const CRYPTO_SHA256_PER_BYTE: u64 = 16;
364pub const CRYPTO_KECCAK256_PER_BYTE: u64 = 16;
366pub const CRYPTO_RIPEMD160_PER_BYTE: u64 = 16;
368pub const fn crypto_verify_ed25519_signature_cost(msg_len: usize) -> u64 {
370 1_400_000_u64.saturating_add((msg_len as u64).saturating_mul(16_u64))
372}