1

And I learned about how to wrap a pallet to make a precompile for Ethereum users to call those pallet functions ... see the video at https://www.youtube.com/watch?v=V9KfvhoqLJ4&t=1004s (time = 01:10:15), and code at https://github.com/PureStake/substrate-node-template/commits/frontier-workshop-2021

in this precompile function at https://github.com/PureStake/substrate-node-template/commit/142fe9a5ca9ca787925d3bd51c55db44caf444cd:


impl<Runtime> PalletTemplatePrecompile<Runtime>
where
    Runtime: pallet_template::Config + pallet_evm::Config,
    Runtime::Call: Dispatchable<PostInfo = PostDispatchInfo> + GetDispatchInfo,
    <Runtime::Call as Dispatchable>::Origin: From<Option<Runtime::AccountId>>,
    Runtime::Call: From<pallet_template::Call<Runtime>>,
{
    fn do_something(
        mut input: EvmDataReader,
        target_gas: Option<u64>,
        context: &Context,
    ) -> EvmResult<PrecompileOutput> {
        // This gasometer is a handy utility that will help us account for gas as we go.
        let mut gasometer = Gasometer::new(target_gas);

        // Bound check. We expect a single argument passed in.
        input.expect_arguments(1)?;

        // Parse the u32 value that will be dispatched to the pallet.
        let value = input.read::<u32>()?.into();

        // Use pallet-evm's account mapping to determine what AccountId to dispatch from.
        let origin = Runtime::AddressMapping::into_account_id(context.caller);
        let call =
            pallet_template::Call::<Runtime>::do_something{something: value};

        // Dispatch the call into the runtime.
        // The RuntimeHelper tells how much gas was actually used.
        let used_gas = RuntimeHelper::<Runtime>::try_dispatch(
            Some(origin).into(),
            call,
            gasometer.remaining_gas()?,
        )?;

        // Record the gas used in the gasometer
        gasometer.record_cost(used_gas)?;

        Ok(PrecompileOutput {
            exit_status: ExitSucceed::Stopped,
            cost: gasometer.used_gas(),
            output: Default::default(),
            logs: Default::default(),
        })
    }

in my pallet_template:

        pub fn do_something(
            origin: OriginFor<T>,
            call: Box<<T as Config>::Call>,
        ) -> DispatchResultWithPostInfo {
            let sender = ensure_signed(origin.clone())?;

            let special_accounts = <SepecialList<T>>::get();
            // check if this sender can send feeless txn

            // Dispatch the call.
            let result = call.dispatch(origin);

            if special_accounts.contains(sender) {
               Ok(Pays::No.into())
            } else {
               Ok(Pays::Yes.into())
            }
        }

Now. How can I specify which function from an Ethereum smart contract(deployed into the EVM in my parachain) to invoke?

How can I pass this call: Box<<T as Config>::Call> argument in the precompile to the do_something() in my pallet_template ?

1 Answer 1

0

For specifying which function from an Ethereum smart contract, use precompiles instead of a regular Ethereum contracts.

See reference: How to make gasless(EVM balance) transaction in Frontier EVM for certain Ethereum smart contract functions?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.