1

I'm trying to write something similar to Moonbeam's assets-erc20 precompile.

I'm using Moonbeam's #[precompile] procedural macros.

pub type AssetIdOf<R> =
        <<R as pallet_evm::Config>::Fungibles as Inspect<<R as frame_system::Config>::AccountId>>::AssetId;

pub type BalanceOf<R> = 
        <<R as pallet_evm::Config>::Fungibles as Inspect<<R as frame_system::Config>::AccountId>>::Balance;

pub struct Fungibles<R>(PhantomData<R>);

#[precompile_utils::precompile]
impl<R> Fungibles<R>
where
    R: pallet_evm::Config,
    AssetIdOf<R>: EvmData,
    BalanceOf<R>: Into<U256>,
{

    #[precompile::public("totalSupply()")]
    #[precompile::view]
    fn total_supply(
        handle: &mut impl PrecompileHandle,
        asset_id: AssetIdOf<R>,
    ) -> EvmResult<U256> {
        handle.record_cost(RuntimeHelper::<R>::db_read_gas_cost())?;
        
        Ok(R::Fungibles::total_issuance(asset_id).into())
    }

    // todo: remaining erc20 methods
}

I'm running into this compilation error.

  --> frame/evm/precompile/fungibles/src/lib.rs:74:29
   |
63 | impl<R> Fungibles<R>
   |                  - help: you might be missing a type parameter: `<R>`
...
74 |         asset_id: AssetIdOf<R>,
   |                             ^ not found in this scope

For more information about this error, try `rustc --explain E0412`.

It's quite confusing because <R> is not missing.

I'm trying to figure out whether:

  • this is a Rust syntax error
  • I'm misusing the #[precompile] macro

Note: my approach is using loose coupling (as opposed to assets-erc20's tight coupling). I attempted switching to a tight coupling strategy and the issue remained, so that is unlikely to be the root cause.

1

1 Answer 1

3

This is the case described here in the docs: https://github.com/PureStake/moonbeam/blob/master/precompiles/utils/macro/docs/precompile_macro.md#solidity-signatures-test

It is because the macro automatically generates a test to ensure that the arguments of the functions match the Solidity signature you provide. However here one of your arguments is generic over R, which means its corresponding Solidity type could vary based on the configuration of your Runtime (it shouldn't however since the signature string cannot vary). It occurs as soon as you have at least one argument that use at least of the type parameters of your precompile. Note that in your case the signature doesn't match, and you should prefer using non dependent types like H256 and add a bound like AssetIdOf<R>: TryFrom<H256>, which would give the Solidity signarure "totalSupply(bytes32)".

To fix the issue you should add the annotation #[precompile::test_concrete_types(mock::Runtime)] on the impl block by listing a concrete type for your Runtime, ideally a mock Runtime. If you have other type parameters you must provide concrete types for each in the same order.

We'll see in the future if we can have a better error message.

2

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