1use std::{cell::RefCell, collections::BTreeMap, sync::Arc};
20
21use ethereum_types::{H160, H256, U256};
22use evm::{ExitError, ExitReason};
23use jsonrpsee::{core::RpcResult, types::error::CALL_EXECUTION_FAILED_CODE};
24use scale_codec::{Decode, Encode};
25use sc_client_api::backend::{Backend, StorageProvider};
27use sc_transaction_pool_api::TransactionPool;
28use sp_api::{ApiExt, CallApiAt, CallApiAtParams, CallContext, ProvideRuntimeApi};
29use sp_block_builder::BlockBuilder as BlockBuilderApi;
30use sp_blockchain::HeaderBackend;
31use sp_externalities::Extensions;
32use sp_inherents::CreateInherentDataProviders;
33use sp_io::hashing::{blake2_128, twox_128};
34use sp_runtime::{
35 traits::{Block as BlockT, HashingFor},
36 DispatchError, SaturatedConversion,
37};
38use sp_state_machine::OverlayedChanges;
39use fc_rpc_core::types::*;
41use fp_evm::{ExecutionInfo, ExecutionInfoV2};
42use fp_rpc::{EthereumRuntimeRPCApi, RuntimeStorageOverride};
43use fp_storage::constants::{EVM_ACCOUNT_CODES, EVM_ACCOUNT_STORAGES, PALLET_EVM};
44
45use crate::{
46 eth::{Eth, EthConfig},
47 frontier_backend_client, internal_err,
48};
49
50pub trait EstimateGasAdapter {
59 fn adapt_request(request: TransactionRequest) -> TransactionRequest;
60}
61
62impl EstimateGasAdapter for () {
63 fn adapt_request(request: TransactionRequest) -> TransactionRequest {
64 request
65 }
66}
67
68impl<B, C, P, CT, BE, CIDP, EC> Eth<B, C, P, CT, BE, CIDP, EC>
69where
70 B: BlockT,
71 C: CallApiAt<B> + ProvideRuntimeApi<B>,
72 C::Api: BlockBuilderApi<B> + EthereumRuntimeRPCApi<B>,
73 C: HeaderBackend<B> + StorageProvider<B, BE> + 'static,
74 BE: Backend<B> + 'static,
75 CIDP: CreateInherentDataProviders<B, ()> + Send + 'static,
76 EC: EthConfig<B, C>,
77 P: TransactionPool<Block = B, Hash = B::Hash> + 'static,
78{
79 pub async fn call(
80 &self,
81 request: TransactionRequest,
82 number_or_hash: Option<BlockNumberOrHash>,
83 state_overrides: Option<BTreeMap<H160, CallStateOverride>>,
84 ) -> RpcResult<Bytes> {
85 let TransactionRequest {
86 from,
87 to,
88 gas_price,
89 max_fee_per_gas,
90 max_priority_fee_per_gas,
91 gas,
92 value,
93 data,
94 nonce,
95 access_list,
96 authorization_list,
97 ..
98 } = request;
99
100 let (gas_price, max_fee_per_gas, max_priority_fee_per_gas) = {
101 let details = fee_details(gas_price, max_fee_per_gas, max_priority_fee_per_gas)?;
102 (
103 details.gas_price,
104 details.max_fee_per_gas,
105 details.max_priority_fee_per_gas,
106 )
107 };
108
109 let (substrate_hash, mut api) = match frontier_backend_client::native_block_id::<B, C>(
110 self.client.as_ref(),
111 self.backend.as_ref(),
112 number_or_hash,
113 )
114 .await?
115 {
116 Some(id) => {
117 let hash = self.client.expect_block_hash_from_id(&id).map_err(|_| {
118 crate::err(CALL_EXECUTION_FAILED_CODE, "header not found", None)
119 })?;
120 (hash, self.client.runtime_api())
121 }
122 None => {
123 let (hash, api) = self.pending_runtime_api().await.map_err(|err| {
125 internal_err(format!("Create pending runtime api error: {err}"))
126 })?;
127 (hash, api)
128 }
129 };
130
131 api.record_proof();
133 let recorder: sp_trie::recorder::Recorder<HashingFor<B>> = Default::default();
134 let ext = sp_trie::proof_size_extension::ProofSizeExt::new(recorder.clone());
135 api.register_extension(ext);
136
137 let api_version = if let Ok(Some(api_version)) =
138 api.api_version::<dyn EthereumRuntimeRPCApi<B>>(substrate_hash)
139 {
140 api_version
141 } else {
142 return Err(internal_err("failed to retrieve Runtime Api version"));
143 };
144
145 let block = if api_version > 1 {
146 api.current_block(substrate_hash)
147 .map_err(|err| internal_err(format!("runtime error: {err}")))?
148 } else {
149 #[allow(deprecated)]
150 let legacy_block = api
151 .current_block_before_version_2(substrate_hash)
152 .map_err(|err| internal_err(format!("runtime error: {err}")))?;
153 legacy_block.map(|block| block.into())
154 };
155
156 let block_gas_limit = block
157 .ok_or_else(|| internal_err("block unavailable, cannot query gas limit"))?
158 .header
159 .gas_limit;
160 let max_gas_limit = block_gas_limit * self.execute_gas_limit_multiplier;
161
162 let gas_limit = match gas {
164 Some(amount) => {
165 if amount > max_gas_limit {
166 return Err(internal_err(format!(
167 "provided gas limit is too high (can be up to {}x the block gas limit)",
168 self.execute_gas_limit_multiplier
169 )));
170 }
171 amount
172 }
173 None => match api.gas_limit_multiplier_support(substrate_hash) {
176 Ok(_) => max_gas_limit,
177 _ => block_gas_limit,
178 },
179 };
180
181 let data = data.into_bytes().map(|d| d.into_vec()).unwrap_or_default();
182 match to {
183 Some(to) => {
184 if api_version == 1 {
185 #[allow(deprecated)]
187 let info = api.call_before_version_2(
188 substrate_hash,
189 from.unwrap_or_default(),
190 to,
191 data,
192 value.unwrap_or_default(),
193 gas_limit,
194 gas_price,
195 nonce,
196 false,
197 )
198 .map_err(|err| internal_err(format!("runtime error: {err}")))?
199 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
200
201 error_on_execution_failure(&info.exit_reason, &info.value)?;
202 Ok(Bytes(info.value))
203 } else if api_version >= 2 && api_version < 4 {
204 #[allow(deprecated)]
206 let info = api.call_before_version_4(
207 substrate_hash,
208 from.unwrap_or_default(),
209 to,
210 data,
211 value.unwrap_or_default(),
212 gas_limit,
213 max_fee_per_gas,
214 max_priority_fee_per_gas,
215 nonce,
216 false,
217 )
218 .map_err(|err| internal_err(format!("runtime error: {err}")))?
219 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
220
221 error_on_execution_failure(&info.exit_reason, &info.value)?;
222 Ok(Bytes(info.value))
223 } else if api_version == 4 || api_version == 5 {
224 let encoded_params = Encode::encode(&(
226 &from.unwrap_or_default(),
227 &to,
228 &data,
229 &value.unwrap_or_default(),
230 &gas_limit,
231 &max_fee_per_gas,
232 &max_priority_fee_per_gas,
233 &nonce,
234 &false,
235 &Some(
236 access_list
237 .unwrap_or_default()
238 .into_iter()
239 .map(|item| (item.address, item.storage_keys))
240 .collect::<Vec<(sp_core::H160, Vec<H256>)>>(),
241 ),
242 ));
243 let overlayed_changes = self.create_overrides_overlay(
244 substrate_hash,
245 api_version,
246 state_overrides,
247 )?;
248
249 let recorder: sp_trie::recorder::Recorder<HashingFor<B>> = Default::default();
251 let ext = sp_trie::proof_size_extension::ProofSizeExt::new(recorder.clone());
252 let mut exts = Extensions::new();
253 exts.register(ext);
254
255 let params = CallApiAtParams {
256 at: substrate_hash,
257 function: "EthereumRuntimeRPCApi_call",
258 arguments: encoded_params,
259 overlayed_changes: &RefCell::new(overlayed_changes),
260 call_context: CallContext::Offchain,
261 recorder: &Some(recorder),
262 extensions: &RefCell::new(exts),
263 };
264
265 let value = if api_version == 4 {
266 let info = self
267 .client
268 .call_api_at(params)
269 .and_then(|r| {
270 Result::map_err(
271 <Result<ExecutionInfo::<Vec<u8>>, DispatchError> as Decode>::decode(&mut &r[..]),
272 |error| sp_api::ApiError::FailedToDecodeReturnValue {
273 function: "EthereumRuntimeRPCApi_call",
274 error,
275 raw: r
276 },
277 )
278 })
279 .map_err(|err| internal_err(format!("runtime error: {err}")))?
280 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
281
282 error_on_execution_failure(&info.exit_reason, &info.value)?;
283 info.value
284 } else if api_version == 5 {
285 let info = self
286 .client
287 .call_api_at(params)
288 .and_then(|r| {
289 Result::map_err(
290 <Result<ExecutionInfoV2::<Vec<u8>>, DispatchError> as Decode>::decode(&mut &r[..]),
291 |error| sp_api::ApiError::FailedToDecodeReturnValue {
292 function: "EthereumRuntimeRPCApi_call",
293 error,
294 raw: r
295 },
296 )
297 })
298 .map_err(|err| internal_err(format!("runtime error: {err}")))?
299 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
300
301 error_on_execution_failure(&info.exit_reason, &info.value)?;
302 info.value
303 } else {
304 return Err(internal_err(format!(
305 "Unsupported EthereumRuntimeRPCApi version: {api_version}"
306 )));
307 };
308
309 Ok(Bytes(value))
310 } else if api_version == 6 {
311 let access_list = access_list
313 .unwrap_or_default()
314 .into_iter()
315 .map(|item| (item.address, item.storage_keys))
316 .collect::<Vec<(sp_core::H160, Vec<H256>)>>();
317
318 let encoded_params = Encode::encode(&(
319 &from.unwrap_or_default(),
320 &to,
321 &data,
322 &value.unwrap_or_default(),
323 &gas_limit,
324 &max_fee_per_gas,
325 &max_priority_fee_per_gas,
326 &nonce,
327 &false,
328 &Some(access_list),
329 &authorization_list,
330 ));
331 let overlayed_changes = self.create_overrides_overlay(
332 substrate_hash,
333 api_version,
334 state_overrides,
335 )?;
336
337 let recorder: sp_trie::recorder::Recorder<HashingFor<B>> = Default::default();
339 let ext = sp_trie::proof_size_extension::ProofSizeExt::new(recorder.clone());
340 let mut exts = Extensions::new();
341 exts.register(ext);
342
343 let params = CallApiAtParams {
344 at: substrate_hash,
345 function: "EthereumRuntimeRPCApi_call",
346 arguments: encoded_params,
347 overlayed_changes: &RefCell::new(overlayed_changes),
348 call_context: CallContext::Offchain,
349 recorder: &Some(recorder),
350 extensions: &RefCell::new(exts),
351 };
352
353 let info =
354 self.client
355 .call_api_at(params)
356 .and_then(|r| {
357 Result::map_err(
358 <Result<ExecutionInfoV2::<Vec<u8>>, DispatchError> as Decode>::decode(&mut &r[..]),
359 |error| sp_api::ApiError::FailedToDecodeReturnValue {
360 function: "EthereumRuntimeRPCApi_call",
361 error,
362 raw: r
363 },
364 )
365 })
366 .map_err(|err| internal_err(format!("runtime error: {err}")))?
367 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
368
369 error_on_execution_failure(&info.exit_reason, &info.value)?;
370
371 Ok(Bytes(info.value))
372 } else {
373 Err(internal_err("failed to retrieve Runtime Api version"))
374 }
375 }
376 None => {
377 if api_version == 1 {
378 #[allow(deprecated)]
380 let info = api.create_before_version_2(
381 substrate_hash,
382 from.unwrap_or_default(),
383 data,
384 value.unwrap_or_default(),
385 gas_limit,
386 gas_price,
387 nonce,
388 false,
389 )
390 .map_err(|err| internal_err(format!("runtime error: {err}")))?
391 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
392
393 error_on_execution_failure(&info.exit_reason, &[])?;
394
395 let code = api
396 .account_code_at(substrate_hash, info.value)
397 .map_err(|err| internal_err(format!("runtime error: {err}")))?;
398 Ok(Bytes(code))
399 } else if api_version >= 2 && api_version < 4 {
400 #[allow(deprecated)]
402 let info = api.create_before_version_4(
403 substrate_hash,
404 from.unwrap_or_default(),
405 data,
406 value.unwrap_or_default(),
407 gas_limit,
408 max_fee_per_gas,
409 max_priority_fee_per_gas,
410 nonce,
411 false,
412 )
413 .map_err(|err| internal_err(format!("runtime error: {err}")))?
414 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
415
416 error_on_execution_failure(&info.exit_reason, &[])?;
417
418 let code = api
419 .account_code_at(substrate_hash, info.value)
420 .map_err(|err| internal_err(format!("runtime error: {err}")))?;
421 Ok(Bytes(code))
422 } else if api_version == 4 {
423 let access_list = access_list.unwrap_or_default();
425 #[allow(deprecated)]
426 let info = api.create_before_version_5(
427 substrate_hash,
428 from.unwrap_or_default(),
429 data,
430 value.unwrap_or_default(),
431 gas_limit,
432 max_fee_per_gas,
433 max_priority_fee_per_gas,
434 nonce,
435 false,
436 Some(
437 access_list
438 .into_iter()
439 .map(|item| (item.address, item.storage_keys))
440 .collect(),
441 ),
442 )
443 .map_err(|err| internal_err(format!("runtime error: {err}")))?
444 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
445
446 error_on_execution_failure(&info.exit_reason, &[])?;
447
448 let code = api
449 .account_code_at(substrate_hash, info.value)
450 .map_err(|err| internal_err(format!("runtime error: {err}")))?;
451 Ok(Bytes(code))
452 } else if api_version == 5 {
453 let access_list = access_list.unwrap_or_default();
455 #[allow(deprecated)]
456 let info = api.create_before_version_6(
457 substrate_hash,
458 from.unwrap_or_default(),
459 data,
460 value.unwrap_or_default(),
461 gas_limit,
462 max_fee_per_gas,
463 max_priority_fee_per_gas,
464 nonce,
465 false,
466 Some(
467 access_list
468 .into_iter()
469 .map(|item| (item.address, item.storage_keys))
470 .collect(),
471 ),
472 )
473 .map_err(|err| internal_err(format!("runtime error: {err}")))?
474 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
475
476 error_on_execution_failure(&info.exit_reason, &[])?;
477
478 let code = api
479 .account_code_at(substrate_hash, info.value)
480 .map_err(|err| internal_err(format!("runtime error: {err}")))?;
481 Ok(Bytes(code))
482 } else if api_version == 6 {
483 let access_list = access_list.unwrap_or_default();
485 let authorization_list = authorization_list.unwrap_or_default();
486 let info = api
487 .create(
488 substrate_hash,
489 from.unwrap_or_default(),
490 data,
491 value.unwrap_or_default(),
492 gas_limit,
493 max_fee_per_gas,
494 max_priority_fee_per_gas,
495 nonce,
496 false,
497 Some(
498 access_list
499 .into_iter()
500 .map(|item| (item.address, item.storage_keys))
501 .collect(),
502 ),
503 Some(authorization_list),
504 )
505 .map_err(|err| internal_err(format!("runtime error: {err}")))?
506 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
507
508 error_on_execution_failure(&info.exit_reason, &[])?;
509
510 let code = api
511 .account_code_at(substrate_hash, info.value)
512 .map_err(|err| internal_err(format!("runtime error: {err}")))?;
513 Ok(Bytes(code))
514 } else {
515 Err(internal_err("failed to retrieve Runtime Api version"))
516 }
517 }
518 }
519 }
520
521 pub async fn estimate_gas(
522 &self,
523 request: TransactionRequest,
524 number_or_hash: Option<BlockNumberOrHash>,
525 ) -> RpcResult<U256> {
526 let client = Arc::clone(&self.client);
527 let block_data_cache = Arc::clone(&self.block_data_cache);
528
529 const MIN_GAS_PER_TX: U256 = U256([21_000, 0, 0, 0]);
531
532 let (substrate_hash, api) = match frontier_backend_client::native_block_id::<B, C>(
534 self.client.as_ref(),
535 self.backend.as_ref(),
536 number_or_hash,
537 )
538 .await?
539 {
540 Some(id) => {
541 let hash = client.expect_block_hash_from_id(&id).map_err(|_| {
542 crate::err(CALL_EXECUTION_FAILED_CODE, "header not found", None)
543 })?;
544 (hash, client.runtime_api())
545 }
546 None => {
547 let (hash, api) = self.pending_runtime_api().await.map_err(|err| {
549 internal_err(format!("Create pending runtime api error: {err}"))
550 })?;
551 (hash, api)
552 }
553 };
554
555 let request = EC::EstimateGasAdapter::adapt_request(request);
557
558 let is_simple_transfer = match &request.data() {
560 None => true,
561 Some(vec) => vec.0.is_empty(),
562 };
563 if is_simple_transfer {
564 if let Some(to) = request.to {
565 let to_code = api
566 .account_code_at(substrate_hash, to)
567 .map_err(|err| internal_err(format!("runtime error: {err}")))?;
568 if to_code.is_empty() {
569 return Ok(MIN_GAS_PER_TX);
570 }
571 }
572 }
573
574 let block_gas_limit = {
575 let block = block_data_cache.current_block(substrate_hash).await;
576 block
577 .ok_or_else(|| internal_err("block unavailable, cannot query gas limit"))?
578 .header
579 .gas_limit
580 };
581
582 let max_gas_limit = block_gas_limit * self.execute_gas_limit_multiplier;
583
584 let mut highest = match request.gas {
586 Some(amount) => {
587 if amount > max_gas_limit {
588 return Err(internal_err(format!(
589 "provided gas limit is too high (can be up to {}x the block gas limit)",
590 self.execute_gas_limit_multiplier
591 )));
592 }
593 amount
594 }
595 None => match api.gas_limit_multiplier_support(substrate_hash) {
598 Ok(_) => max_gas_limit,
599 _ => block_gas_limit,
600 },
601 };
602
603 let (gas_price, max_fee_per_gas, max_priority_fee_per_gas, fee_cap) = {
604 let details = fee_details(
605 request.gas_price,
606 request.max_fee_per_gas,
607 request.max_priority_fee_per_gas,
608 )?;
609 (
610 details.gas_price,
611 details.max_fee_per_gas,
612 details.max_priority_fee_per_gas,
613 details.fee_cap,
614 )
615 };
616
617 if let Some(from) = request.from {
619 if fee_cap > U256::zero() {
620 let balance = api
621 .account_basic(substrate_hash, from)
622 .map_err(|err| internal_err(format!("runtime error: {err}")))?
623 .balance;
624 let mut available = balance;
625 if let Some(value) = request.value {
626 if value > available {
627 return Err(internal_err("insufficient funds for transfer"));
628 }
629 available -= value;
630 }
631 let allowance = available / fee_cap;
632 if highest > allowance {
633 log::warn!(
634 "Gas estimation capped by limited funds original {} balance {} sent {} feecap {} fundable {}",
635 highest,
636 balance,
637 request.value.unwrap_or_default(),
638 fee_cap,
639 allowance
640 );
641 highest = allowance;
642 }
643 }
644 }
645
646 struct ExecutableResult {
647 data: Vec<u8>,
648 exit_reason: ExitReason,
649 used_gas: U256,
650 }
651
652 #[rustfmt::skip]
664 let executable = move |
665 request, gas_limit, api_version, api: sp_api::ApiRef<'_, C::Api>, estimate_mode
666 | -> RpcResult<ExecutableResult> {
667 let TransactionRequest {
668 from,
669 to,
670 gas,
671 value,
672 data,
673 access_list,
674 authorization_list,
675 ..
676 } = request;
677
678 let gas_limit = core::cmp::min(gas.unwrap_or(gas_limit), gas_limit);
680
681 let data = data.into_bytes().map(|d| d.0).unwrap_or_default();
682
683 let (exit_reason, data, used_gas) = match to {
684 Some(to) => {
685 if api_version == 1 {
686 #[allow(deprecated)]
688 let info = api.call_before_version_2(
689 substrate_hash,
690 from.unwrap_or_default(),
691 to,
692 data,
693 value.unwrap_or_default(),
694 gas_limit,
695 gas_price,
696 None,
697 estimate_mode,
698 )
699 .map_err(|err| internal_err(format!("runtime error: {err}")))?
700 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
701
702 (info.exit_reason, info.value, info.used_gas)
703 } else if api_version < 4 {
704 #[allow(deprecated)]
706 let info = api.call_before_version_4(
707 substrate_hash,
708 from.unwrap_or_default(),
709 to,
710 data,
711 value.unwrap_or_default(),
712 gas_limit,
713 max_fee_per_gas,
714 max_priority_fee_per_gas,
715 None,
716 estimate_mode,
717 )
718 .map_err(|err| internal_err(format!("runtime error: {err}")))?
719 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
720
721 (info.exit_reason, info.value, info.used_gas)
722 } else if api_version == 4 {
723 let access_list = access_list.unwrap_or_default();
725 #[allow(deprecated)]
726 let info = api.call_before_version_5(
727 substrate_hash,
728 from.unwrap_or_default(),
729 to,
730 data,
731 value.unwrap_or_default(),
732 gas_limit,
733 max_fee_per_gas,
734 max_priority_fee_per_gas,
735 None,
736 estimate_mode,
737 Some(
738 access_list
739 .into_iter()
740 .map(|item| (item.address, item.storage_keys))
741 .collect(),
742 ),
743 )
744 .map_err(|err| internal_err(format!("runtime error: {err}")))?
745 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
746
747 (info.exit_reason, info.value, info.used_gas)
748 } else if api_version == 5 {
749 let encoded_params = Encode::encode(&(
751 &from.unwrap_or_default(),
752 &to,
753 &data,
754 &value.unwrap_or_default(),
755 &gas_limit,
756 &max_fee_per_gas,
757 &max_priority_fee_per_gas,
758 &None::<Option<U256>>,
759 &estimate_mode,
760 &Some(
761 access_list
762 .unwrap_or_default()
763 .into_iter()
764 .map(|item| (item.address, item.storage_keys))
765 .collect::<Vec<(sp_core::H160, Vec<H256>)>>(),
766 ),
767 ));
768
769 let recorder: sp_trie::recorder::Recorder<HashingFor<B>> = Default::default();
771 let ext = sp_trie::proof_size_extension::ProofSizeExt::new(recorder.clone());
772 let mut exts = Extensions::new();
773 exts.register(ext);
774
775 let params = CallApiAtParams {
776 at: substrate_hash,
777 function: "EthereumRuntimeRPCApi_call",
778 arguments: encoded_params,
779 overlayed_changes: &RefCell::new(Default::default()),
780 call_context: CallContext::Offchain,
781 recorder: &Some(recorder),
782 extensions: &RefCell::new(exts),
783 };
784
785 let info = self
786 .client
787 .call_api_at(params)
788 .and_then(|r| {
789 Result::map_err(
790 <Result<ExecutionInfoV2::<Vec<u8>>, DispatchError> as Decode>::decode(&mut &r[..]),
791 |error| sp_api::ApiError::FailedToDecodeReturnValue {
792 function: "EthereumRuntimeRPCApi_call",
793 error,
794 raw: r
795 },
796 )
797 })
798 .map_err(|err| internal_err(format!("runtime error: {err}")))?
799 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
800
801 (info.exit_reason, info.value, info.used_gas.effective)
802 } else if api_version == 6 {
803 let access_list = access_list
805 .unwrap_or_default()
806 .into_iter()
807 .map(|item| (item.address, item.storage_keys))
808 .collect::<Vec<(sp_core::H160, Vec<H256>)>>();
809
810 let encoded_params = Encode::encode(&(
811 &from.unwrap_or_default(),
812 &to,
813 &data,
814 &value.unwrap_or_default(),
815 &gas_limit,
816 &max_fee_per_gas,
817 &max_priority_fee_per_gas,
818 &None::<Option<U256>>,
819 &estimate_mode,
820 &Some(
821 access_list
822 ),
823 &authorization_list,
824 ));
825
826 let recorder: sp_trie::recorder::Recorder<HashingFor<B>> = Default::default();
828 let ext = sp_trie::proof_size_extension::ProofSizeExt::new(recorder.clone());
829 let mut exts = Extensions::new();
830 exts.register(ext);
831
832 let params = CallApiAtParams {
833 at: substrate_hash,
834 function: "EthereumRuntimeRPCApi_call",
835 arguments: encoded_params,
836 overlayed_changes: &RefCell::new(Default::default()),
837 call_context: CallContext::Offchain,
838 recorder: &Some(recorder),
839 extensions: &RefCell::new(exts),
840 };
841
842 let info = self
843 .client
844 .call_api_at(params)
845 .and_then(|r| {
846 Result::map_err(
847 <Result<ExecutionInfoV2::<Vec<u8>>, DispatchError> as Decode>::decode(&mut &r[..]),
848 |error| sp_api::ApiError::FailedToDecodeReturnValue {
849 function: "EthereumRuntimeRPCApi_call",
850 error,
851 raw: r
852 },
853 )
854 })
855 .map_err(|err| internal_err(format!("runtime error: {err}")))?
856 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
857
858 (info.exit_reason, info.value, info.used_gas.effective)
859 } else {
860 return Err(internal_err(format!("Unsupported EthereumRuntimeRPCApi version: {api_version}")));
861 }
862 }
863 None => {
864 if api_version == 1 {
865 #[allow(deprecated)]
867 let info = api.create_before_version_2(
868 substrate_hash,
869 from.unwrap_or_default(),
870 data,
871 value.unwrap_or_default(),
872 gas_limit,
873 gas_price,
874 None,
875 estimate_mode,
876 )
877 .map_err(|err| internal_err(format!("runtime error: {err}")))?
878 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
879
880 (info.exit_reason, Vec::new(), info.used_gas)
881 } else if api_version < 4 {
882 #[allow(deprecated)]
884 let info = api.create_before_version_4(
885 substrate_hash,
886 from.unwrap_or_default(),
887 data,
888 value.unwrap_or_default(),
889 gas_limit,
890 max_fee_per_gas,
891 max_priority_fee_per_gas,
892 None,
893 estimate_mode,
894 )
895 .map_err(|err| internal_err(format!("runtime error: {err}")))?
896 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
897
898 (info.exit_reason, Vec::new(), info.used_gas)
899 } else if api_version == 4 {
900 let access_list = access_list.unwrap_or_default();
902 #[allow(deprecated)]
903 let info = api.create_before_version_5(
904 substrate_hash,
905 from.unwrap_or_default(),
906 data,
907 value.unwrap_or_default(),
908 gas_limit,
909 max_fee_per_gas,
910 max_priority_fee_per_gas,
911 None,
912 estimate_mode,
913 Some(
914 access_list
915 .into_iter()
916 .map(|item| (item.address, item.storage_keys))
917 .collect(),
918 ),
919 )
920 .map_err(|err| internal_err(format!("runtime error: {err}")))?
921 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
922
923 (info.exit_reason, Vec::new(), info.used_gas)
924 } else if api_version == 5 {
925 let encoded_params = Encode::encode(&(
927 &from.unwrap_or_default(),
928 &data,
929 &value.unwrap_or_default(),
930 &gas_limit,
931 &max_fee_per_gas,
932 &max_priority_fee_per_gas,
933 &None::<Option<U256>>,
934 &estimate_mode,
935 &Some(
936 access_list
937 .unwrap_or_default()
938 .into_iter()
939 .map(|item| (item.address, item.storage_keys))
940 .collect::<Vec<(sp_core::H160, Vec<H256>)>>(),
941 ),
942 ));
943
944 let recorder: sp_trie::recorder::Recorder<HashingFor<B>> = Default::default();
946 let ext = sp_trie::proof_size_extension::ProofSizeExt::new(recorder.clone());
947 let mut exts = Extensions::new();
948 exts.register(ext);
949
950 let params = CallApiAtParams {
951 at: substrate_hash,
952 function: "EthereumRuntimeRPCApi_create",
953 arguments: encoded_params,
954 overlayed_changes: &RefCell::new(Default::default()),
955 call_context: CallContext::Offchain,
956 recorder: &Some(recorder),
957 extensions: &RefCell::new(exts),
958 };
959
960 let info = self
961 .client
962 .call_api_at(params)
963 .and_then(|r| {
964 Result::map_err(
965 <Result<ExecutionInfoV2::<H160>, DispatchError> as Decode>::decode(&mut &r[..]),
966 |error| sp_api::ApiError::FailedToDecodeReturnValue {
967 function: "EthereumRuntimeRPCApi_create",
968 error,
969 raw: r
970 },
971 )
972 })
973 .map_err(|err| internal_err(format!("runtime error: {err}")))?
974 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
975
976 (info.exit_reason, Vec::new(), info.used_gas.effective)
977 } else if api_version == 6 {
978 let access_list = access_list
980 .unwrap_or_default()
981 .into_iter()
982 .map(|item| (item.address, item.storage_keys))
983 .collect::<Vec<(sp_core::H160, Vec<H256>)>>();
984
985 let encoded_params = Encode::encode(&(
986 &from.unwrap_or_default(),
987 &data,
988 &value.unwrap_or_default(),
989 &gas_limit,
990 &max_fee_per_gas,
991 &max_priority_fee_per_gas,
992 &None::<Option<U256>>,
993 &estimate_mode,
994 &Some(
995 access_list
996 ),
997 &authorization_list,
998 ));
999
1000 let recorder: sp_trie::recorder::Recorder<HashingFor<B>> = Default::default();
1002 let ext = sp_trie::proof_size_extension::ProofSizeExt::new(recorder.clone());
1003 let mut exts = Extensions::new();
1004 exts.register(ext);
1005
1006 let params = CallApiAtParams {
1007 at: substrate_hash,
1008 function: "EthereumRuntimeRPCApi_create",
1009 arguments: encoded_params,
1010 overlayed_changes: &RefCell::new(Default::default()),
1011 call_context: CallContext::Offchain,
1012 recorder: &Some(recorder),
1013 extensions: &RefCell::new(exts),
1014 };
1015
1016 let info = self
1017 .client
1018 .call_api_at(params)
1019 .and_then(|r| {
1020 Result::map_err(
1021 <Result<ExecutionInfoV2::<H160>, DispatchError> as Decode>::decode(&mut &r[..]),
1022 |error| sp_api::ApiError::FailedToDecodeReturnValue {
1023 function: "EthereumRuntimeRPCApi_create",
1024 error,
1025 raw: r
1026 },
1027 )
1028 })
1029 .map_err(|err| internal_err(format!("runtime error: {err}")))?
1030 .map_err(|err| internal_err(format!("execution fatal: {err:?}")))?;
1031
1032 (info.exit_reason, Vec::new(), info.used_gas.effective)
1033 } else {
1034 return Err(internal_err(format!("Unsupported EthereumRuntimeRPCApi version: {api_version}")));
1035 }
1036 }
1037 };
1038 Ok(ExecutableResult {
1039 exit_reason,
1040 data,
1041 used_gas,
1042 })
1043 };
1044 let api_version = if let Ok(Some(api_version)) =
1045 client
1046 .runtime_api()
1047 .api_version::<dyn EthereumRuntimeRPCApi<B>>(substrate_hash)
1048 {
1049 api_version
1050 } else {
1051 return Err(internal_err("failed to retrieve Runtime Api version"));
1052 };
1053
1054 let cap = highest;
1056 let estimate_mode = !cfg!(feature = "rpc-binary-search-estimate");
1057 let ExecutableResult {
1058 data,
1059 exit_reason,
1060 used_gas,
1061 } = executable(
1062 request.clone(),
1063 highest,
1064 api_version,
1065 client.runtime_api(),
1066 estimate_mode,
1067 )?;
1068 match exit_reason {
1069 ExitReason::Succeed(_) => (),
1070 ExitReason::Error(ExitError::OutOfGas) => {
1071 return Err(internal_err(format!(
1072 "gas required exceeds allowance {cap}"
1073 )))
1074 }
1075 ExitReason::Revert(revert) => {
1079 if request.gas.is_some() || request.gas_price.is_some() {
1080 let ExecutableResult {
1084 data,
1085 exit_reason,
1086 used_gas: _,
1087 } = executable(
1088 request.clone(),
1089 max_gas_limit,
1090 api_version,
1091 client.runtime_api(),
1092 estimate_mode,
1093 )?;
1094 match exit_reason {
1095 ExitReason::Succeed(_) => {
1096 return Err(internal_err(format!(
1097 "gas required exceeds allowance {cap}",
1098 )))
1099 }
1100 other => error_on_execution_failure(&other, &data)?,
1102 }
1103 } else {
1104 error_on_execution_failure(&ExitReason::Revert(revert), &data)?
1106 }
1107 }
1108 other => error_on_execution_failure(&other, &data)?,
1109 };
1110
1111 #[cfg(not(feature = "rpc-binary-search-estimate"))]
1112 {
1113 Ok(used_gas)
1114 }
1115 #[cfg(feature = "rpc-binary-search-estimate")]
1116 {
1117 let estimate_mode = false;
1119 let mut lowest = MIN_GAS_PER_TX;
1121
1122 let mut mid = std::cmp::min(used_gas * 3, (highest + lowest) / 2);
1124
1125 let mut previous_highest = highest;
1127 while (highest - lowest) > U256::one() {
1128 let ExecutableResult {
1129 data,
1130 exit_reason,
1131 used_gas: _,
1132 } = executable(
1133 request.clone(),
1134 mid,
1135 api_version,
1136 client.runtime_api(),
1137 estimate_mode,
1138 )?;
1139 match exit_reason {
1140 ExitReason::Succeed(_) => {
1141 highest = mid;
1142 if (previous_highest - highest) * 10 / previous_highest < U256::one() {
1145 return Ok(highest);
1146 }
1147 previous_highest = highest;
1148 }
1149 ExitReason::Revert(_)
1150 | ExitReason::Error(ExitError::OutOfGas)
1151 | ExitReason::Error(ExitError::InvalidCode(_)) => {
1152 lowest = mid;
1153 }
1154 other => error_on_execution_failure(&other, &data)?,
1155 }
1156 mid = (highest + lowest) / 2;
1157 }
1158
1159 Ok(highest)
1160 }
1161 }
1162
1163 fn create_overrides_overlay(
1166 &self,
1167 block_hash: B::Hash,
1168 api_version: u32,
1169 state_overrides: Option<BTreeMap<H160, CallStateOverride>>,
1170 ) -> RpcResult<OverlayedChanges<HashingFor<B>>> {
1171 let mut overlayed_changes = OverlayedChanges::default();
1172 if let Some(state_overrides) = state_overrides {
1173 for (address, state_override) in state_overrides {
1174 if EC::RuntimeStorageOverride::is_enabled() {
1175 EC::RuntimeStorageOverride::set_overlayed_changes(
1176 self.client.as_ref(),
1177 &mut overlayed_changes,
1178 block_hash,
1179 api_version,
1180 address,
1181 state_override.balance,
1182 state_override.nonce,
1183 );
1184 } else if state_override.balance.is_some() || state_override.nonce.is_some() {
1185 return Err(internal_err(
1186 "state override unsupported for balance and nonce",
1187 ));
1188 }
1189
1190 if let Some(code) = &state_override.code {
1191 let mut key = [twox_128(PALLET_EVM), twox_128(EVM_ACCOUNT_CODES)]
1192 .concat()
1193 .to_vec();
1194 key.extend(blake2_128(address.as_bytes()));
1195 key.extend(address.as_bytes());
1196 let encoded_code = code.clone().into_vec().encode();
1197 overlayed_changes.set_storage(key.clone(), Some(encoded_code));
1198 }
1199
1200 let mut account_storage_key =
1201 [twox_128(PALLET_EVM), twox_128(EVM_ACCOUNT_STORAGES)]
1202 .concat()
1203 .to_vec();
1204 account_storage_key.extend(blake2_128(address.as_bytes()));
1205 account_storage_key.extend(address.as_bytes());
1206
1207 if let Some(state) = &state_override.state {
1209 if let Ok(all_keys) = self.client.storage_keys(
1211 block_hash,
1212 Some(&sp_storage::StorageKey(account_storage_key.clone())),
1213 None,
1214 ) {
1215 for key in all_keys {
1216 overlayed_changes.set_storage(key.0, None);
1217 }
1218 }
1219 for (k, v) in state {
1221 let mut slot_key = account_storage_key.clone();
1222 slot_key.extend(blake2_128(k.as_bytes()));
1223 slot_key.extend(k.as_bytes());
1224
1225 overlayed_changes.set_storage(slot_key, Some(v.as_bytes().to_owned()));
1226 }
1227 }
1228
1229 if let Some(state_diff) = &state_override.state_diff {
1230 for (k, v) in state_diff {
1231 let mut slot_key = account_storage_key.clone();
1232 slot_key.extend(blake2_128(k.as_bytes()));
1233 slot_key.extend(k.as_bytes());
1234
1235 overlayed_changes.set_storage(slot_key, Some(v.as_bytes().to_owned()));
1236 }
1237 }
1238 }
1239 }
1240
1241 Ok(overlayed_changes)
1242 }
1243}
1244
1245pub fn error_on_execution_failure(reason: &ExitReason, data: &[u8]) -> RpcResult<()> {
1246 match reason {
1247 ExitReason::Succeed(_) => Ok(()),
1248 ExitReason::Error(err) => {
1249 if *err == ExitError::OutOfGas {
1250 return Err(internal_err("out of gas"));
1252 }
1253 Err(crate::internal_err_with_data(
1254 format!("evm error: {err:?}"),
1255 &[],
1256 ))
1257 }
1258 ExitReason::Revert(_) => {
1259 const LEN_START: usize = 36;
1260 const MESSAGE_START: usize = 68;
1261
1262 let mut message = "VM Exception while processing transaction: revert".to_string();
1263 if data.len() > MESSAGE_START {
1266 let message_len = U256::from_big_endian(&data[LEN_START..MESSAGE_START])
1267 .saturated_into::<usize>();
1268 let message_end = MESSAGE_START.saturating_add(message_len);
1269
1270 if data.len() >= message_end {
1271 let body: &[u8] = &data[MESSAGE_START..message_end];
1272 if let Ok(reason) = std::str::from_utf8(body) {
1273 message = format!("{message} {reason}");
1274 }
1275 }
1276 }
1277 Err(crate::internal_err_with_data(message, data))
1278 }
1279 ExitReason::Fatal(err) => Err(crate::internal_err_with_data(
1280 format!("evm fatal: {err:?}"),
1281 &[],
1282 )),
1283 }
1284}
1285
1286struct FeeDetails {
1287 gas_price: Option<U256>,
1288 max_fee_per_gas: Option<U256>,
1289 max_priority_fee_per_gas: Option<U256>,
1290 fee_cap: U256,
1291}
1292
1293fn fee_details(
1294 request_gas_price: Option<U256>,
1295 request_max_fee_per_gas: Option<U256>,
1296 request_priority_fee_per_gas: Option<U256>,
1297) -> RpcResult<FeeDetails> {
1298 match (
1299 request_gas_price,
1300 request_max_fee_per_gas,
1301 request_priority_fee_per_gas,
1302 ) {
1303 (Some(_), Some(_), Some(_)) => Err(internal_err(
1304 "both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified",
1305 )),
1306 (gas_price, None, None) if gas_price.is_some() => Ok(FeeDetails {
1308 gas_price,
1309 max_fee_per_gas: None,
1310 max_priority_fee_per_gas: None,
1311 fee_cap: gas_price.unwrap_or_default(),
1312 }),
1313 (None, Some(max_fee), Some(max_priority)) => {
1315 if max_priority > max_fee {
1316 return Err(internal_err(
1317 "Invalid input: `max_priority_fee_per_gas` greater than `max_fee_per_gas`",
1318 ));
1319 }
1320 Ok(FeeDetails {
1321 gas_price: None,
1322 max_fee_per_gas: Some(max_fee),
1323 max_priority_fee_per_gas: Some(max_priority),
1324 fee_cap: max_fee,
1325 })
1326 }
1327 _ => Ok(FeeDetails {
1329 gas_price: None,
1330 max_fee_per_gas: None,
1332 max_priority_fee_per_gas: Some(U256::zero()),
1333 fee_cap: U256::zero(),
1334 }),
1335 }
1336}