ink_env/call/
create_builder.rs

1// Copyright (C) Use Ink (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#[cfg(feature = "unstable-hostfn")]
16use crate::Error;
17use crate::{
18    call::{
19        utils::{
20            EmptyArgumentList,
21            ReturnType,
22            Set,
23            Unset,
24        },
25        ExecutionInput,
26        Selector,
27    },
28    types::Environment,
29    ContractEnv,
30};
31use core::marker::PhantomData;
32use ink_primitives::{
33    reflect::{
34        AbiEncodeWith,
35        ScaleEncoding,
36        SolEncoding,
37    },
38    H160,
39    H256,
40    U256,
41};
42
43pub mod state {
44    //! Type states that tell what state of a instantiation argument has not
45    //! yet been set properly for a valid construction.
46}
47
48/// Contracts that can be constructed from an `AccountId`.
49///
50/// # Note
51///
52/// This is needed because of conflicting implementations of `From<T> for T`
53/// in the generated code of `ink`.
54///
55/// But it is possible to use `From<AccountId> for T` with [`crate::AccountIdGuard`]
56/// bound.
57pub trait FromAddr {
58    /// Creates the contract instance from the account ID of the already instantiated
59    /// contract.
60    fn from_addr(addr: H160) -> Self;
61}
62
63/// Represents any type that can be returned from an `ink!` constructor. The following
64/// contract implements the four different return type signatures implementing this trait:
65///
66/// - `Self`
67/// - `Result<Self, Error>`
68/// - `Contract`
69/// - `Result<Contract, Error>`
70///
71/// ```rust
72/// #[ink::contract]
73/// mod contract {
74///     #[ink(storage)]
75///     pub struct Contract {}
76///
77///     #[derive(Debug, PartialEq, Eq)]
78///     #[ink::scale_derive(Encode, Decode, TypeInfo)]
79///     pub enum Error {
80///         Foo,
81///     }
82///
83///     impl Contract {
84///         #[ink(constructor)]
85///         pub fn new_self() -> Self {
86///             Self {}
87///         }
88///
89///         #[ink(constructor)]
90///         pub fn new_storage_name() -> Contract {
91///             Contract {}
92///         }
93///
94///         #[ink(constructor)]
95///         pub fn new_result_self() -> Result<Self, Error> {
96///             Ok(Self {})
97///         }
98///
99///         #[ink(constructor)]
100///         pub fn new_result_storage_name() -> Result<Contract, Error> {
101///             Ok(Contract {})
102///         }
103///
104///         #[ink(message)]
105///         pub fn message(&self) {}
106///     }
107/// }
108/// ```
109///
110/// These constructor return signatures are then used by the `ContractRef` codegen for the
111/// [`CreateBuilder::returns`] type parameter.
112pub trait ConstructorReturnType<C> {
113    /// Is `true` if `Self` is `Result<C, E>`.
114    const IS_RESULT: bool = false;
115
116    /// The actual return type of the constructor.
117    /// - If a constructor returns `Self`, then `Output = Self`
118    /// - If a constructor returns a `Result<Self, E>`, then `Output = Result<Self, E>`
119    type Output;
120
121    /// The error type of the constructor return type.
122    type Error: scale::Decode;
123
124    /// Construct a success value of the `Output` type.
125    fn ok(value: C) -> Self::Output;
126
127    /// Construct an error value of the `Output` type.
128    ///
129    /// `Result` implementations should return `Some(Err(err))`, otherwise default to
130    /// `None`.
131    fn err(_err: Self::Error) -> Option<Self::Output> {
132        None
133    }
134}
135
136/// Blanket implementation for `ContractRef` types, generated for cross-contract calls.
137///
138/// In the context of a `ContractRef` inherent, `Self` from a constructor return
139/// type will become the type of the `ContractRef`'s type.
140impl<C> ConstructorReturnType<C> for C
141where
142    C: ContractEnv + FromAddr,
143{
144    type Output = C;
145    type Error = ();
146
147    fn ok(value: C) -> Self::Output {
148        value
149    }
150}
151
152/// Blanket implementation for a `Result<Self>` return type. `Self` in the context
153/// of a `ContractRef` inherent becomes the `ContractRef`s type.
154impl<C, E> ConstructorReturnType<C> for core::result::Result<C, E>
155where
156    C: ContractEnv + FromAddr,
157    E: scale::Decode,
158{
159    const IS_RESULT: bool = true;
160
161    type Output = core::result::Result<C, E>;
162    type Error = E;
163
164    fn ok(value: C) -> Self::Output {
165        Ok(value)
166    }
167
168    fn err(err: Self::Error) -> Option<Self::Output> {
169        Some(Err(err))
170    }
171}
172
173/// Defines the limit params for the new `ext::instantiate` host function.
174/// todo: rename
175#[derive(Clone, Debug)]
176pub struct LimitParamsV2 {
177    ref_time_limit: u64,
178    proof_size_limit: u64,
179    storage_deposit_limit: Option<U256>,
180}
181
182/// Builds up contract instantiations.
183#[derive(Debug)]
184pub struct CreateParams<E, ContractRef, Limits, Args, R, Abi> {
185    /// The code hash of the created contract.
186    code_hash: H256,
187    /// Parameters for weight and storage limits, differs for versions of the instantiate
188    /// host function.
189    limits: Limits,
190    /// The endowment for the instantiated contract.
191    /// todo: is this correct? or is the value here `U256`?
192    endowment: U256,
193    /// The input data for the instantiation.
194    exec_input: ExecutionInput<Args, Abi>,
195    /// The salt for determining the hash for the contract account ID.
196    salt_bytes: Option<[u8; 32]>,
197    /// The return type of the target contract's constructor method.
198    _return_type: ReturnType<R>,
199    /// The type of the reference to the contract returned from the constructor.
200    _phantom: PhantomData<fn() -> (E, ContractRef)>,
201}
202
203impl<E, ContractRef, Limits, Args, R, Abi>
204    CreateParams<E, ContractRef, Limits, Args, R, Abi>
205where
206    E: Environment,
207{
208    /// The code hash of the contract.
209    #[inline]
210    pub fn code_hash(&self) -> &H256 {
211        &self.code_hash
212    }
213
214    /// The endowment for the instantiated contract.
215    #[inline]
216    pub fn endowment(&self) -> &U256 {
217        &self.endowment
218    }
219
220    /// The raw encoded input data.
221    #[inline]
222    pub fn exec_input(&self) -> &ExecutionInput<Args, Abi> {
223        &self.exec_input
224    }
225
226    /// Modify the selector.
227    ///
228    /// Useful when using the [`CreateParams`] generated as part of the
229    /// `ContractRef`, but using a custom selector.
230    pub fn update_selector(&mut self, selector: Selector) {
231        self.exec_input.update_selector(selector)
232    }
233}
234
235impl<E, ContractRef, Args, R, Abi>
236    CreateParams<E, ContractRef, LimitParamsV2, Args, R, Abi>
237where
238    E: Environment,
239{
240    /// Gets the `ref_time_limit` part of the weight limit for the contract instantiation.
241    #[inline]
242    pub fn ref_time_limit(&self) -> u64 {
243        self.limits.ref_time_limit
244    }
245
246    /// Gets the `proof_size_limit` part of the weight limit for the contract
247    /// instantiation.
248    #[inline]
249    pub fn proof_size_limit(&self) -> u64 {
250        self.limits.proof_size_limit
251    }
252
253    /// Gets the `storage_deposit_limit` for the contract instantiation.
254    #[inline]
255    pub fn storage_deposit_limit(&self) -> Option<&U256> {
256        self.limits.storage_deposit_limit.as_ref()
257    }
258}
259
260impl<E, ContractRef, Limits, Args, R, Abi>
261    CreateParams<E, ContractRef, Limits, Args, R, Abi>
262where
263    E: Environment,
264{
265    /// The salt for determining the hash for the contract account ID.
266    #[inline]
267    pub fn salt_bytes(&self) -> &Option<[u8; 32]> {
268        &self.salt_bytes
269    }
270}
271
272impl<E, ContractRef, Args, R, Abi>
273    CreateParams<E, ContractRef, LimitParamsV2, Args, R, Abi>
274where
275    E: Environment,
276    ContractRef: FromAddr + crate::ContractReverseReference,
277    <ContractRef as crate::ContractReverseReference>::Type:
278        crate::reflect::ContractConstructorDecoder,
279    <ContractRef as crate::ContractReverseReference>::Type:
280        crate::reflect::ContractMessageDecoder,
281    Args: AbiEncodeWith<Abi>,
282    R: ConstructorReturnType<ContractRef>,
283{
284    /// todo
285    /// Instantiates the contract and returns its account ID back to the caller.
286    ///
287    /// # Panics
288    ///
289    /// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an
290    /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle
291    /// those use the [`try_instantiate`][`CreateParams::try_instantiate`] method
292    /// instead.
293    #[inline]
294    #[cfg(feature = "unstable-hostfn")]
295    pub fn instantiate(&self) -> <R as ConstructorReturnType<ContractRef>>::Output {
296        crate::instantiate_contract(self)
297            .unwrap_or_else(|env_error| {
298                panic!("Cross-contract instantiation failed with {env_error:?}")
299            })
300            .unwrap_or_else(|lang_error| {
301                panic!("Received a `LangError` while instantiating: {lang_error:?}")
302            })
303    }
304
305    /// Instantiates the contract and returns its account ID back to the caller.
306    ///
307    /// # Note
308    ///
309    /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner
310    /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be
311    /// handled by the caller.
312    #[inline]
313    #[cfg(feature = "unstable-hostfn")]
314    pub fn try_instantiate(
315        &self,
316    ) -> Result<
317        ink_primitives::ConstructorResult<
318            <R as ConstructorReturnType<ContractRef>>::Output,
319        >,
320        Error,
321    > {
322        crate::instantiate_contract(self)
323    }
324}
325
326/// Builds up contract instantiations.
327#[derive(Clone)]
328pub struct CreateBuilder<E, ContractRef, Limits, Args, RetType>
329where
330    E: Environment,
331{
332    code_hash: H256,
333    limits: Limits,
334    endowment: U256,
335    exec_input: Args,
336    salt: Option<[u8; 32]>,
337    return_type: RetType,
338    _phantom: PhantomData<fn() -> (E, ContractRef)>,
339}
340
341/// Returns a new [`CreateBuilder`] to build up the parameters to a cross-contract
342/// instantiation for a contract that uses the ink! ABI (SCALE Encoding).
343///
344/// # Example
345///
346/// **Note:** The shown examples panic because there is currently no cross-calling
347///           support in the off-chain testing environment. However, this code
348///           should work fine in on-chain environments.
349///
350/// ## Example 1: Returns Address of Instantiated Contract
351///
352/// The below example shows instantiation of contract of type `MyContract`.
353///
354/// The used constructor:
355///
356/// - has a selector equal to `0xDEADBEEF`
357/// - is provided with 4000 units of gas for its execution
358/// - is provided with 25 units of transferred value for the new contract instance
359/// - receives the following arguments in order 1. an `i32` with value `42` 2. a `bool`
360///   with value `true` 3. an array of 32 `u8` with value `0x10`
361///
362/// ```should_panic
363/// # use ::ink_env::{
364/// #     Environment,
365/// #     DefaultEnvironment,
366/// #     call::{build_create, Selector, ExecutionInput, FromAddr}
367/// # };
368/// # type Hash = <DefaultEnvironment as Environment>::Hash;
369/// #
370/// # #[ink::contract]
371/// # pub mod contract {
372/// #     #[ink(storage)]
373/// #     pub struct MyContract {}
374/// #
375/// #     impl MyContract {
376/// #         #[ink(constructor)]
377/// #         pub fn my_constructor() -> Self { Self {} }
378/// #
379/// #         #[ink(message)]
380/// #         pub fn message(&self) {}
381/// #     }
382/// # }
383/// # use contract::MyContractRef;
384/// let my_contract: MyContractRef = build_create::<MyContractRef>()
385///     .code_hash(ink::H256::from([0x42; 32]))
386///     .endowment(25.into())
387///     .exec_input(
388///         ExecutionInput::new(Selector::new(ink::selector_bytes!("my_constructor")))
389///             .push_arg(42)
390///             .push_arg(true)
391///             .push_arg(&[0x10u8; 32]),
392///     )
393///     .salt_bytes(Some([1u8; 32]))
394///     .returns::<MyContractRef>()
395///     .instantiate();
396/// ```
397///
398/// ## Example 2: Handles Result from Fallible Constructor
399///
400/// ```should_panic
401/// # use ::ink_env::{
402/// #     Environment,
403/// #     DefaultEnvironment,
404/// #     call::{build_create, Selector, ExecutionInput, FromAddr}
405/// # };
406/// # type Hash = <DefaultEnvironment as Environment>::Hash;
407/// #
408/// # #[ink::contract]
409/// # pub mod contract {
410/// #     #[derive(scale::Encode, scale::Decode, Debug)]
411/// #     #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
412/// #     pub struct ConstructorError;
413/// #
414/// #     #[ink(storage)]
415/// #     pub struct MyContract {}
416/// #
417/// #     impl MyContract {
418/// #         #[ink(constructor)]
419/// #         pub fn my_constructor() -> Result<Self, ConstructorError> {
420/// #             Ok(Self {})
421/// #         }
422/// #
423/// #         #[ink(message)]
424/// #         pub fn message(&self) {}
425/// #     }
426/// # }
427/// # use contract::{MyContractRef, ConstructorError};
428/// let my_contract: MyContractRef = build_create::<MyContractRef>()
429///     .code_hash(ink::H256::from([0x42; 32]))
430///     .endowment(25.into())
431///     .exec_input(
432///         ExecutionInput::new(Selector::new(ink::selector_bytes!("my_constructor")))
433///             .push_arg(42)
434///             .push_arg(true)
435///             .push_arg(&[0x10u8; 32]),
436///     )
437///     .salt_bytes(Some([1u8; 32]))
438///     .returns::<Result<MyContractRef, ConstructorError>>()
439///     .instantiate()
440///     .expect("Constructor should have executed successfully.");
441/// ```
442#[allow(clippy::type_complexity)]
443pub fn build_create<ContractRef>() -> CreateBuilder<
444    <ContractRef as ContractEnv>::Env,
445    ContractRef,
446    Set<LimitParamsV2>,
447    Unset<ExecutionInput<EmptyArgumentList<ScaleEncoding>, ScaleEncoding>>,
448    Unset<ReturnType<()>>,
449>
450where
451    ContractRef: ContractEnv,
452{
453    CreateBuilder {
454        code_hash: Default::default(),
455        limits: Set(LimitParamsV2 {
456            ref_time_limit: u64::MAX,
457            proof_size_limit: u64::MAX,
458            storage_deposit_limit: None,
459        }),
460        endowment: Default::default(),
461        exec_input: Default::default(),
462        salt: Default::default(),
463        return_type: Default::default(),
464        _phantom: Default::default(),
465    }
466}
467
468/// Returns a new [`CreateBuilder`] to build up the parameters to a cross-contract
469/// instantiation for an ink! contract that uses Solidity ABI Encoding.
470/// See [`build_create`] for more details on usage.
471#[allow(clippy::type_complexity)]
472pub fn build_create_solidity<ContractRef>() -> CreateBuilder<
473    <ContractRef as ContractEnv>::Env,
474    ContractRef,
475    Set<LimitParamsV2>,
476    Unset<ExecutionInput<EmptyArgumentList<SolEncoding>, SolEncoding>>,
477    Unset<ReturnType<()>>,
478>
479where
480    ContractRef: ContractEnv,
481{
482    CreateBuilder {
483        code_hash: Default::default(),
484        limits: Set(LimitParamsV2 {
485            ref_time_limit: u64::MAX,
486            proof_size_limit: u64::MAX,
487            storage_deposit_limit: None,
488        }),
489        endowment: Default::default(),
490        exec_input: Default::default(),
491        salt: Default::default(),
492        return_type: Default::default(),
493        _phantom: Default::default(),
494    }
495}
496
497impl<E, ContractRef, Limits, Args, RetType>
498    CreateBuilder<E, ContractRef, Limits, Args, RetType>
499where
500    E: Environment,
501{
502    /// Sets the used code hash for the contract instantiation.
503    #[inline]
504    pub fn code_hash(
505        self,
506        code_hash: H256,
507    ) -> CreateBuilder<E, ContractRef, Limits, Args, RetType> {
508        CreateBuilder {
509            code_hash,
510            limits: self.limits,
511            endowment: self.endowment,
512            exec_input: self.exec_input,
513            salt: self.salt,
514            return_type: self.return_type,
515            _phantom: Default::default(),
516        }
517    }
518}
519
520impl<E, ContractRef, Args, RetType>
521    CreateBuilder<E, ContractRef, Set<LimitParamsV2>, Args, RetType>
522where
523    E: Environment,
524{
525    /// Sets the `ref_time_limit` part of the weight limit for the contract instantiation.
526    #[inline]
527    pub fn ref_time_limit(self, ref_time_limit: u64) -> Self {
528        CreateBuilder {
529            limits: Set(LimitParamsV2 {
530                ref_time_limit,
531                ..self.limits.value()
532            }),
533            ..self
534        }
535    }
536
537    /// Sets the `proof_size_limit` part of the weight limit for the contract
538    /// instantiation.
539    #[inline]
540    pub fn proof_size_limit(self, proof_size_limit: u64) -> Self {
541        CreateBuilder {
542            limits: Set(LimitParamsV2 {
543                proof_size_limit,
544                ..self.limits.value()
545            }),
546            ..self
547        }
548    }
549
550    /// Sets the `storage_deposit_limit` for the contract instantiation.
551    #[inline]
552    pub fn storage_deposit_limit(self, storage_deposit_limit: U256) -> Self {
553        CreateBuilder {
554            limits: Set(LimitParamsV2 {
555                storage_deposit_limit: Some(storage_deposit_limit),
556                ..self.limits.value()
557            }),
558            ..self
559        }
560    }
561}
562
563impl<E, ContractRef, Limits, Args, RetType>
564    CreateBuilder<E, ContractRef, Limits, Args, RetType>
565where
566    E: Environment,
567{
568    /// Sets the value transferred upon the execution of the call.
569    #[inline]
570    pub fn endowment(
571        self,
572        endowment: U256,
573    ) -> CreateBuilder<E, ContractRef, Limits, Args, RetType> {
574        CreateBuilder {
575            code_hash: self.code_hash,
576            limits: self.limits,
577            endowment,
578            exec_input: self.exec_input,
579            salt: self.salt,
580            return_type: self.return_type,
581            _phantom: Default::default(),
582        }
583    }
584}
585
586impl<E, ContractRef, Limits, RetType, Abi>
587    CreateBuilder<
588        E,
589        ContractRef,
590        Limits,
591        Unset<ExecutionInput<EmptyArgumentList<Abi>, Abi>>,
592        RetType,
593    >
594where
595    E: Environment,
596{
597    /// Sets the value transferred upon the execution of the call.
598    #[inline]
599    pub fn exec_input<Args>(
600        self,
601        exec_input: ExecutionInput<Args, Abi>,
602    ) -> CreateBuilder<E, ContractRef, Limits, Set<ExecutionInput<Args, Abi>>, RetType>
603    {
604        CreateBuilder {
605            code_hash: self.code_hash,
606            limits: self.limits,
607            endowment: self.endowment,
608            exec_input: Set(exec_input),
609            salt: self.salt,
610            return_type: self.return_type,
611            _phantom: Default::default(),
612        }
613    }
614}
615
616impl<E, ContractRef, Limits, Args, RetType>
617    CreateBuilder<E, ContractRef, Limits, Args, RetType>
618where
619    E: Environment,
620{
621    /// Sets the salt used for the execution of the call.
622    #[inline]
623    pub fn salt_bytes(
624        self,
625        salt: Option<[u8; 32]>,
626    ) -> CreateBuilder<E, ContractRef, Limits, Args, RetType> {
627        CreateBuilder {
628            code_hash: self.code_hash,
629            limits: self.limits,
630            endowment: self.endowment,
631            exec_input: self.exec_input,
632            salt,
633            return_type: self.return_type,
634            _phantom: Default::default(),
635        }
636    }
637}
638
639impl<E, ContractRef, Limits, Args>
640    CreateBuilder<E, ContractRef, Limits, Args, Unset<ReturnType<()>>>
641where
642    E: Environment,
643{
644    /// Sets the type of the returned value upon the execution of the constructor.
645    ///
646    /// # Note
647    ///
648    /// Constructors are not able to return arbitrary values. Instead, a successful call
649    /// to a constructor returns the address at which the contract was instantiated.
650    ///
651    /// Therefore this must always be a reference (i.e. `ContractRef`) to the contract
652    /// you're trying to instantiate.
653    #[inline]
654    pub fn returns<R>(
655        self,
656    ) -> CreateBuilder<E, ContractRef, Limits, Args, Set<ReturnType<R>>>
657    where
658        ContractRef: FromAddr,
659        R: ConstructorReturnType<ContractRef>,
660    {
661        CreateBuilder {
662            code_hash: self.code_hash,
663            limits: self.limits,
664            endowment: self.endowment,
665            exec_input: self.exec_input,
666            salt: self.salt,
667            return_type: Set(Default::default()),
668            _phantom: Default::default(),
669        }
670    }
671}
672
673impl<E, ContractRef, Limits, Args, RetType, Abi>
674    CreateBuilder<
675        E,
676        ContractRef,
677        Set<Limits>,
678        Set<ExecutionInput<Args, Abi>>,
679        Set<ReturnType<RetType>>,
680    >
681where
682    E: Environment,
683{
684    /// Finalizes the `CreateBuilder`, allowing it to instantiate a contract.
685    #[inline]
686    pub fn params(self) -> CreateParams<E, ContractRef, Limits, Args, RetType, Abi> {
687        CreateParams {
688            code_hash: self.code_hash,
689            limits: self.limits.value(),
690            endowment: self.endowment,
691            exec_input: self.exec_input.value(),
692            salt_bytes: self.salt,
693            _return_type: Default::default(),
694            _phantom: Default::default(),
695        }
696    }
697}
698
699impl<E, ContractRef, Args, RetType, Abi>
700    CreateBuilder<
701        E,
702        ContractRef,
703        Set<LimitParamsV2>,
704        Set<ExecutionInput<Args, Abi>>,
705        Set<ReturnType<RetType>>,
706    >
707where
708    E: Environment,
709    ContractRef: FromAddr + crate::ContractReverseReference,
710    <ContractRef as crate::ContractReverseReference>::Type:
711        crate::reflect::ContractConstructorDecoder,
712    <ContractRef as crate::ContractReverseReference>::Type:
713        crate::reflect::ContractMessageDecoder,
714    Args: AbiEncodeWith<Abi>,
715    RetType: ConstructorReturnType<ContractRef>,
716{
717    /// todo check comment
718    /// Instantiates the contract and returns its account ID back to the caller.
719    ///
720    /// # Panics
721    ///
722    /// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an
723    /// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle
724    /// those use the [`try_instantiate`][`CreateBuilder::try_instantiate`] method
725    /// instead.
726    #[inline]
727    #[cfg(feature = "unstable-hostfn")]
728    pub fn instantiate(self) -> <RetType as ConstructorReturnType<ContractRef>>::Output {
729        self.params().instantiate()
730    }
731
732    /// todo check comment
733    /// Instantiates the contract and returns its account ID back to the caller.
734    ///
735    /// # Note
736    ///
737    /// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner
738    /// [`ink::primitives::LangError`][`ink_primitives::LangError`], both of which can be
739    /// handled by the caller.
740    #[inline]
741    #[cfg(feature = "unstable-hostfn")]
742    pub fn try_instantiate(
743        self,
744    ) -> Result<
745        ink_primitives::ConstructorResult<
746            <RetType as ConstructorReturnType<ContractRef>>::Output,
747        >,
748        Error,
749    > {
750        self.params().try_instantiate()
751    }
752}