xclud / web3dart

Ethereum library, written in Dart.
https://pub.dev/packages/web3dart
MIT License
170 stars 94 forks source link

Unable to encode contract function #137

Closed reasje closed 4 months ago

reasje commented 4 months ago

Hello, I am trying to encode one of contracts functions with It's all parameters, Unfortunatly I have faced below Issue

Claim reward function after code generation with web3dart from json ABI :

  Future<String> claimRewards(
    BigInt MEP1004TokenId,
    _i1.EthereumAddress to,
    List<dynamic> proofs,
    List<BigInt> epochIds,
    List<dynamic> rewards, {
    required _i1.Credentials credentials,
    _i1.Transaction? transaction,
  }) async {
    final function = self.abi.functions[7];
    assert(checkSignature(function, '89c64b7d'));
    final params = [
      MEP1004TokenId,
      to,
      proofs,
      epochIds,
      rewards,
    ];
    return write(
      credentials,
      transaction,
      function,
      params,
    );
  }

Encoding function : (I am sure below code logic is correct) The error is being thrown in return function.encodeCall(params); and that happens when trying to encode the proofsArray variable :

    final function = mep2542.self.abi.functions[7];
    assert(checkSignature(function, '89c64b7d'));
    final params = [
      BigInt.parse(miner.mep1004TokenId!),
      to,
      proofsArray,
      epochIds,
      rewardInfoArray,
    ];
    return function.encodeCall(params);

contract ABI :

    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "MEP1004TokenId",
                "type": "uint256"
            },
            {
                "internalType": "address",
                "name": "to",
                "type": "address"
            },
            {
                "components": [
                    {
                        "internalType": "bytes32[]",
                        "name": "proofs",
                        "type": "bytes32[]"
                    }
                ],
                "internalType": "struct MEP2542.ProofArray[]",
                "name": "proofs",
                "type": "tuple[]"
            },
            {
                "internalType": "uint256[]",
                "name": "epochIds",
                "type": "uint256[]"
            },
            {
                "components": [
                    {
                        "internalType": "address[]",
                        "name": "token",
                        "type": "address[]"
                    },
                    {
                        "internalType": "uint256[]",
                        "name": "amount",
                        "type": "uint256[]"
                    }
                ],
                "internalType": "struct MEP2542.RewardInfo[]",
                "name": "rewards",
                "type": "tuple[]"
            }
        ],
        "name": "claimRewards",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },

proofsArray :

final List<ProofsRequestModel> proofsArray = [];

class ProofsRequestModel {
  factory ProofsRequestModel.fromJson(String source) =>
      ProofsRequestModel.fromMap(json.decode(source));

  factory ProofsRequestModel.fromMap(Map<String, dynamic> map) {
    return ProofsRequestModel(
      proofs: List<String>.from(map['proofs']),
    );
  }
  ProofsRequestModel({
    required this.proofs,
  });
  List<String> proofs;

  ProofsRequestModel copyWith({
    List<String>? proofs,
  }) {
    return ProofsRequestModel(
      proofs: proofs ?? this.proofs,
    );
  }

  Map<String, dynamic> toMap() {
    return {
      'proofs': proofs,
    };
  }

  String toJson() => json.encode(toMap());

  @override
  String toString() => 'ProofsRequestModel(proofs: $proofs)';

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is ProofsRequestModel && listEquals(other.proofs, proofs);
  }

  @override
  int get hashCode => proofs.hashCode;
}

rewardInfoArray :

final List<RewardsRequestModel> rewardInfoArray = [];

class RewardsRequestModel {
  factory RewardsRequestModel.fromJson(String source) =>
      RewardsRequestModel.fromMap(json.decode(source));

  factory RewardsRequestModel.fromMap(Map<String, dynamic> map) {
    return RewardsRequestModel(
      amount: List<BigInt>.from(map['amount']?.map((x) => BigInt.parse(x))),
      token: List<EthereumAddress>.from(map['token']),
    );
  }
  RewardsRequestModel({
    required this.amount,
    required this.token,
  });
  List<BigInt> amount;
  List<EthereumAddress> token;

  RewardsRequestModel copyWith({
    List<BigInt>? amount,
    List<EthereumAddress>? token,
  }) {
    return RewardsRequestModel(
      amount: amount ?? this.amount,
      token: token ?? this.token,
    );
  }

  Map<String, dynamic> toMap() {
    return {
      'token': token.map((e) => e.toString() as dynamic).toList().toString(),
      'amount': amount.map((e) => e.toString() as dynamic).toList().toString()
    };
  }

  String toJson() => json.encode(toMap());

  @override
  String toString() => 'RewardsRequestModel(amount: $amount, token: $token)';

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is RewardsRequestModel &&
        listEquals(other.amount, amount) &&
        listEquals(other.token, token);
  }

  @override
  int get hashCode => amount.hashCode ^ token.hashCode;
}

TS code that is working!

Error Message :

'ProofsRequestModel' is not a subtype of type 'List<dynamic>' of 'data'
reasje commented 4 months ago

I was able to solve the problem by passing solidity structs with [] in Flutter side, So the final params looks like this, And in my case some properties like proofs array required one more [] too.

    final params = [
      BigInt.parse(miner.mep1004TokenId!),
      proofsArray
          .map(
            (e) => [e.proofs.map((e) => MXCType.hexToUint8List(e)).toList()],
          )
          .toList(),
      epochIds,
      rewardInfoArray.map((e) => [e.token, e.amount]).toList(),
    ];