Contract.DecodingFailed when using Enum with non-unit-like variants in chain extension inputs
SailorSnoW opened this issue · comments
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
- Clone the following node repo: git@github.com:Allfeat/Allfeat.git
- Checkout the tofix/extension-decodefailed branch
- Start a dev node with
$ cargo run --release -- --dev --tmp
- Access the dev node through Polkadot/Substrate Portal - Local Node - Contracts UI
- Upload and instantiate the linked test contract (with the .contract)
test-contract.zip - Then try to interact with the
create()
message of the contract. You should have theDecodingFailed
error if you use aNone
in one of theOption<T>
fields and if you don't use theHolderOf(CollectionId)
variant.
Putting aSome
value in each of theOption<T>
fields with using theHolderOf(CollectionId)
variant don't cause aDecodingFailed
error.