elrond-sdk-erdjs icon indicating copy to clipboard operation
elrond-sdk-erdjs copied to clipboard

[v13] Problem with `checkArgumentsCardinality`

Open juliancwirko opened this issue 2 months ago • 9 comments

Hi, with v13, I have a problem with the checkArgumentsCardinality function.

ErrInvalidArgument [Error]: Invalid argument: Wrong number of arguments for endpoint (...)

I have something like: OptionalValue<MultiValueEncoded<CustomEnum>> in my sc for function argument.

Now, with sdk-core v12 it works ok, but with v13 I'm getting errors from checkArgumentsCardinality

I'm not sure, but it looks like in:

src/smartcontracts/nativeSerializer.ts 

getArgumentsCardinality doesn't set the max = Infinity; and variadic = true; for the type "optional<variadic<CustomEnum>>" (the string representation of the argument's type in ABI),

where CustomEnum is something like:

"CustomEnum": {
  "type": "enum",
  "variants": [
    {
      "name": "someOption0",
      "discriminant": 0
    },
    {
      "name": "someOption1",
      "discriminant": 1
    },
    {
      "name": "someOption2",
      "discriminant": 2
    },
    (...)
  ]
}

It looks like TypeCardinality for that param is: { lowerBound: 0, upperBound: 1 }, so it takes only the optional part. Should it take the variadic here first? Then it would be: { lowerBound: 0, upperBound: <max_upper_bound_or_in_this_case_the_length_of_the_enum_variants> }

I'm not sure if this is a bug or if the parameter definition is wrong, but it worked okay previously with the same setup.

Probably to check (haven't found time yet) last changes in:

src/smartcontracts/typesystem/typeExpressionParser.ts

juliancwirko avatar Apr 15 '24 10:04 juliancwirko

@juliancwirko, thanks a lot for the report and for the provided details :raised_hands:

We'll handle this as soon as possible :pray:

andreibancioiu avatar Apr 17 '24 10:04 andreibancioiu

in my sc for function argument.

@juliancwirko, to narrow down a bit the issue, do you think you can specify how is the function called? E.g. using the contract.methods approach, or using the newer SmartContractTransactionsFactory approach?

Also, how do the passed arguments look like (e.g. is the optional provided, are the variadic parameters wrapped in an array)?

We are preparing a scenario to reproduce the issue here:

https://github.com/multiversx/mx-sdk-js-core/pull/441

andreibancioiu avatar Apr 17 '24 11:04 andreibancioiu

It is through SmartContract.call so I think the SmartContractTransactionsFactory is used there.

It looks like:

contract.call({
    func: new ContractFunction(<fn_name>),
    args: [
      BytesValue.fromUTF8(...),
      BytesValue.fromUTF8(...),
      ...customEnumNamesAsStrings.map((enumName) =>
        EnumValue.fromName(
          EnumType.fromJSON(<json_representation>),
          enumName
        )
      ),
    ],
    value: TokenTransfer.egldFromAmount(...),
    gasLimit: ...,
    chainID: 'D',
    caller: ...,
  });

where json_representation is like:

{
  name: 'CustomEnum',
  variants: [{ name: 'Option1', discriminant: 0 }, { name: 'Option2', discriminant: 1 }],
}

juliancwirko avatar Apr 17 '24 11:04 juliancwirko

Workaround: do not unwrap the enum values.

That is, drop the ... from ...customEnumNamesAsStrings.map((enumName). Actually, this should be the correct way of passing the (optional) variadic values.

We'll analyze now why the behavior differs from v12 (maybe it was a bit more permissive around this).

andreibancioiu avatar Apr 17 '24 12:04 andreibancioiu

Oh, I see. The arguments should be like args: [arg1, arg2, [optionalVariadic1, optionalVariadic2]]. I'll test that later. Thanks.

juliancwirko avatar Apr 17 '24 12:04 juliancwirko

Yes, but in v12, it worked just as you've said (while it wouldn't have worked in the way it works for v13) - this is a breaking change (from v12 to v13) we weren't aware of, thanks for spotting it :pray:

In v12, for contract.call(), args could have only be an array of TypedValue. Now, in v13, typed values can be mixed with untyped ones.

We'll analyze this a bit more, then do a fix and / or update the migration notes.

Thank you!

andreibancioiu avatar Apr 17 '24 12:04 andreibancioiu

@juliancwirko, a more detailed analysis of the issue is here: https://github.com/multiversx/mx-sdk-js-core/pull/441.

For optional<variadic<...>>, you might be interested into this comment - it includes several ways to tackle the issue.

Furthermore, you might want to have MultiValueEncoded<CustomEnum> instead of OptionalValue<MultiValueEncoded<CustomEnum>>, in your contract.

Again, thank you for spotting this!

Let us know how it goes :pray:

andreibancioiu avatar Apr 18 '24 10:04 andreibancioiu

Sure, thanks for the detailed guides. It works great now for me. I will also modify the smart contract and update the 'legacy' code in js.

Please close the issue whenever you think it can be closed. Thanks again.

juliancwirko avatar Apr 18 '24 10:04 juliancwirko

Thank you!

We will leave the issue open for ~1 month.

andreibancioiu avatar Apr 18 '24 11:04 andreibancioiu