use-ink / ink

Polkadot's ink! to write smart contracts.

Home Page:https://use.ink

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Contract.DecodingFailed when using Enum with non-unit-like variants in chain extension inputs

SailorSnoW opened this issue · comments

commented

Is there an existing issue?

  • I have searched the existing issues

Experiencing problems? Have you tried our Stack Exchange first?

  • This is not a support question.

Description of bug

We are currently developing a chain extension to be able to use the NFTs pallet from the contract side on-chain.

Because it fit better with our needs, we use the second method as described in this video (Chain Extension Builder):
https://www.youtube.com/watch?v=-T-HKy_vFCo&t=2427s

The problem:

The implementation went good but we are actually stuck on the following problem:
Using an enum containing a non-unit-like variant (for example Some(T) in the enum Option<T>) make it impossible to decode the input on the substrate side with env.read_as() ONLY if a unit-like variant of the Enum is selected by the user (for example None).
This return a Contract.DecodingFailed error.

You can find the chain extension code of this demo at the following repo and branch (don't mind the rest of the code as it's in a really WIP state): to-fix/extension-decodingfailed
The repo is divided in 4 parts:

  • Root crate: The Ink side of the chain extension with the chain extension builder implementation.
  • impls_runtime crate: The substrate side of the chain extension with the ChainExtension trait implemented on the struct for the runtime.
  • types crate: The shared types between the substrate and ink side to avoid some conflicts between ink and runtime dependencies.
  • test_contracts create: Contain the code of the testing contract used above (basically a simple wrapper of the developed extensions fn).

What have been tested:

  • Destructuring field parameters (one parameter for each type)
  • Not using env.read_as() in substrate side => work ✔
  • Not using any Option and custom Enum tuple-variant => work ✔

My guess:

Something that mess with the total size of what env.read_as() expect, as using an unit-like variant of an Enum decrease the dynamic size of the object ? Maybe something with the MaxEncodedLen derivation ?

Steps to reproduce

  1. Clone the following node repo: git@github.com:Allfeat/Allfeat.git
  2. Checkout the tofix/extension-decodefailed branch
  3. Start a dev node with $ cargo run --release -- --dev --tmp
  4. Access the dev node through Polkadot/Substrate Portal - Local Node - Contracts UI
  5. Upload and instantiate the linked test contract (with the .contract)
    test-contract.zip
  6. Then try to interact with the create() message of the contract. You should have the DecodingFailed error if you use a None in one of the Option<T> fields and if you don't use the HolderOf(CollectionId) variant.
    Putting a Some value in each of the Option<T> fields with using the HolderOf(CollectionId) variant don't cause a DecodingFailed error.