zksync_web3_rs/zks_wallet/requests/
call_request.rs

1use ethers::{
2    abi::{encode, Function, HumanReadableParser, ParseError},
3    types::{Address, Eip1559TransactionRequest},
4};
5use std::fmt::Debug;
6
7use crate::{
8    zks_utils::{self, is_precompile},
9    zks_wallet::errors::ZKRequestError,
10};
11
12#[derive(Clone, Debug)]
13pub struct CallRequest {
14    pub to: Address,
15    pub function_signature: String,
16    pub function_parameters: Option<Vec<String>>,
17}
18
19impl CallRequest {
20    pub fn new(to: Address, function_signature: String) -> Self {
21        Self {
22            to,
23            function_signature,
24            function_parameters: None,
25        }
26    }
27
28    pub fn function_parameters(mut self, function_parameters: Vec<String>) -> Self {
29        self.function_parameters = Some(function_parameters);
30        self
31    }
32
33    pub fn to(mut self, to: Address) -> Self {
34        self.to = to;
35        self
36    }
37
38    pub fn function_signature(mut self, function_signature: String) -> Self {
39        self.function_signature = function_signature;
40        self
41    }
42
43    pub fn get_parsed_function(&self) -> Result<Function, ParseError> {
44        if self.to == zks_utils::ECADD_PRECOMPILE_ADDRESS {
45            Ok(zks_utils::ec_add_function())
46        } else if self.to == zks_utils::ECMUL_PRECOMPILE_ADDRESS {
47            Ok(zks_utils::ec_mul_function())
48        } else if self.to == zks_utils::MODEXP_PRECOMPILE_ADDRESS {
49            Ok(zks_utils::mod_exp_function())
50        } else {
51            HumanReadableParser::parse_function(&self.function_signature)
52                .map_err(ParseError::LexerError)
53        }
54    }
55}
56
57impl TryFrom<CallRequest> for Eip1559TransactionRequest {
58    type Error = ZKRequestError;
59
60    fn try_from(request: CallRequest) -> Result<Eip1559TransactionRequest, Self::Error> {
61        let function = request.get_parsed_function()?;
62        let function_args = if let Some(function_args) = request.function_parameters {
63            function.decode_input(&zks_utils::encode_args(&function, &function_args)?)?
64        } else {
65            vec![]
66        };
67
68        let data = match (!function_args.is_empty(), is_precompile(request.to)) {
69            // The contract to call is a precompile with arguments.
70            (true, true) => encode(&function_args),
71            // The contract to call is a regular contract with arguments.
72            (true, false) => function.encode_input(&function_args)?,
73            // The contract to call is a precompile without arguments.
74            (false, true) => Default::default(),
75            // The contract to call is a regular contract without arguments.
76            (false, false) => function.short_signature().into(),
77        };
78
79        Ok(Eip1559TransactionRequest::new().to(request.to).data(data))
80    }
81}