Unable to encode contract function
Closed this issue · 1 comments
reasje commented
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
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(),
];