CW-1086: Polygon Issues (#2329)

* fix(polygon): Polygon wallets not showing in address book when sending tokens

* feat(polygon_issues): Enhance gas price handling in EVM Chains

This change:
- Updates gas price calculation to account for minimum priority fee in Polygon
- Adjusts gas price handling to use maxFeePerGas when gasPrice is not provided.
- Fixes issue with send all for Polygon
This commit is contained in:
David Adegoke 2025-06-24 03:41:43 +01:00 committed by GitHub
parent 5082dc20f3
commit 4434ad7363
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 63 additions and 16 deletions

View file

@ -109,7 +109,6 @@ abstract class EVMChainClient {
sender: senderAddress, sender: senderAddress,
to: toAddress, to: toAddress,
value: value, value: value,
// maxFeePerGas: maxFeePerGas,
); );
return estimatedGas.toInt(); return estimatedGas.toInt();
@ -165,6 +164,7 @@ abstract class EVMChainClient {
required int exponent, required int exponent,
String? contractAddress, String? contractAddress,
String? data, String? data,
int? gasPrice,
}) async { }) async {
assert(currency == CryptoCurrency.eth || assert(currency == CryptoCurrency.eth ||
currency == CryptoCurrency.maticpoly || currency == CryptoCurrency.maticpoly ||
@ -180,6 +180,7 @@ abstract class EVMChainClient {
data: data != null ? hexToBytes(data) : null, data: data != null ? hexToBytes(data) : null,
maxGas: estimatedGasUnits, maxGas: estimatedGasUnits,
maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
gasPrice: gasPrice != null ? EtherAmount.fromInt(EtherUnit.wei, gasPrice) : null,
); );
Uint8List signedTransaction; Uint8List signedTransaction;
@ -224,6 +225,7 @@ abstract class EVMChainClient {
required EVMChainTransactionPriority priority, required EVMChainTransactionPriority priority,
required int exponent, required int exponent,
required String contractAddress, required String contractAddress,
int? gasPrice,
}) async { }) async {
final Transaction transaction = createTransaction( final Transaction transaction = createTransaction(
@ -233,6 +235,7 @@ abstract class EVMChainClient {
amount: EtherAmount.zero(), amount: EtherAmount.zero(),
maxGas: estimatedGasUnits, maxGas: estimatedGasUnits,
maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
gasPrice: gasPrice != null ? EtherAmount.fromInt(EtherUnit.wei, gasPrice) : null,
); );
final erc20 = ERC20( final erc20 = ERC20(

View file

@ -263,31 +263,65 @@ abstract class EVMChainWalletBase
final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt(); final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt();
int maxFeePerGas; int maxFeePerGas;
int adjustedGasPrice;
bool isPolygon = _client.chainId == 137;
if (gasBaseFee != null) { if (gasBaseFee != null) {
// MaxFeePerGas with EIP1559; // MaxFeePerGas with EIP1559;
maxFeePerGas = gasBaseFee! + priorityFee; maxFeePerGas = gasBaseFee! + priorityFee;
} else { } else {
// MaxFeePerGas with gasPrice // MaxFeePerGas with gasPrice
maxFeePerGas = gasPrice; maxFeePerGas = gasPrice + priorityFee;
}
adjustedGasPrice = maxFeePerGas;
// Polygon has a minimum priority fee of 25 gwei
if (isPolygon) {
int minPriorityFee = 25;
int minPriorityFeeWei =
EtherAmount.fromInt(EtherUnit.gwei, minPriorityFee).getInWei.toInt();
// Calculate user selected priority-based additional fee on top of minimum
int additionalPriorityFee = 0;
switch (priority) {
case EVMChainTransactionPriority.slow:
// We use minimum priority fee only
additionalPriorityFee = 0;
break;
case EVMChainTransactionPriority.medium:
// We add 15 gwei on top of minimum
additionalPriorityFee = EtherAmount.fromInt(EtherUnit.gwei, 15).getInWei.toInt();
break;
case EVMChainTransactionPriority.fast:
// We add 35 gwei on top of minimum
additionalPriorityFee = EtherAmount.fromInt(EtherUnit.gwei, 35).getInWei.toInt();
break;
}
int totalPriorityFee = minPriorityFeeWei + additionalPriorityFee;
adjustedGasPrice = gasPrice + totalPriorityFee;
maxFeePerGas = gasPrice + totalPriorityFee;
} }
final estimatedGas = await _client.getEstimatedGasUnitsForTransaction( final estimatedGas = await _client.getEstimatedGasUnitsForTransaction(
contractAddress: contractAddress, contractAddress: contractAddress,
senderAddress: _evmChainPrivateKey.address, senderAddress: _evmChainPrivateKey.address,
value: EtherAmount.fromBigInt(EtherUnit.wei, amount!), value: EtherAmount.fromBigInt(EtherUnit.wei, amount!),
gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice), gasPrice: EtherAmount.fromInt(EtherUnit.wei, adjustedGasPrice),
toAddress: EthereumAddress.fromHex(receivingAddressHex), toAddress: EthereumAddress.fromHex(receivingAddressHex),
maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
data: data, data: data,
); );
final totalGasFee = estimatedGas * maxFeePerGas; final totalGasFee = estimatedGas * adjustedGasPrice;
return GasParamsHandler( return GasParamsHandler(
estimatedGasUnits: estimatedGas, estimatedGasUnits: estimatedGas,
estimatedGasFee: totalGasFee, estimatedGasFee: totalGasFee,
maxFeePerGas: maxFeePerGas, maxFeePerGas: maxFeePerGas,
gasPrice: gasPrice, gasPrice: adjustedGasPrice,
); );
} }
return GasParamsHandler.zero(); return GasParamsHandler.zero();
@ -476,23 +510,20 @@ abstract class EVMChainWalletBase
contractAddress: contractAddress:
transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null, transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null,
data: hexOpReturnMemo, data: hexOpReturnMemo,
gasPrice: maxFeePerGasForTransaction,
); );
return pendingEVMChainTransaction; return pendingEVMChainTransaction;
} }
Future<PendingTransaction> createApprovalTransaction( Future<PendingTransaction> createApprovalTransaction(BigInt amount, String spender,
BigInt amount, CryptoCurrency token, EVMChainTransactionPriority priority) async {
String spender,
CryptoCurrency token,
EVMChainTransactionPriority priority) async {
final CryptoCurrency transactionCurrency = final CryptoCurrency transactionCurrency =
balance.keys.firstWhere((element) => element.title == token.title); balance.keys.firstWhere((element) => element.title == token.title);
assert(transactionCurrency is Erc20Token); assert(transactionCurrency is Erc20Token);
final data = _client.getEncodedDataForApprovalTransaction( final data = _client.getEncodedDataForApprovalTransaction(
contractAddress: EthereumAddress.fromHex( contractAddress: EthereumAddress.fromHex((transactionCurrency as Erc20Token).contractAddress),
(transactionCurrency as Erc20Token).contractAddress),
value: EtherAmount.fromBigInt(EtherUnit.wei, amount), value: EtherAmount.fromBigInt(EtherUnit.wei, amount),
toAddress: EthereumAddress.fromHex(spender), toAddress: EthereumAddress.fromHex(spender),
); );
@ -515,6 +546,7 @@ abstract class EVMChainWalletBase
estimatedGasUnits: gasFeesModel.estimatedGasUnits, estimatedGasUnits: gasFeesModel.estimatedGasUnits,
exponent: transactionCurrency.decimal, exponent: transactionCurrency.decimal,
contractAddress: transactionCurrency.contractAddress, contractAddress: transactionCurrency.contractAddress,
gasPrice: gasFeesModel.gasPrice,
); );
} }

View file

@ -84,6 +84,6 @@ class DefaultPolygonErc20Tokens {
.iconPath; .iconPath;
} catch (_) {} } catch (_) {}
return Erc20Token.copyWith(token, iconPath, 'POLY'); return Erc20Token.copyWith(token, iconPath, 'POL');
}).toList(); }).toList();
} }

View file

@ -18,13 +18,20 @@ class PolygonClient extends EVMChainClient {
EtherAmount? gasPrice, EtherAmount? gasPrice,
EtherAmount? maxFeePerGas, EtherAmount? maxFeePerGas,
}) { }) {
EtherAmount? finalGasPrice = gasPrice;
if (gasPrice == null && maxFeePerGas != null) {
// If we have EIP-1559 parameters but no legacy gasPrice, then use maxFeePerGas as gasPrice
finalGasPrice = maxFeePerGas;
}
return Transaction( return Transaction(
from: from, from: from,
to: to, to: to,
value: amount, value: amount,
// data: data, data: data,
maxGas: maxGas, maxGas: maxGas,
// gasPrice: gasPrice, gasPrice: finalGasPrice,
// maxFeePerGas: maxFeePerGas, // maxFeePerGas: maxFeePerGas,
// maxPriorityFeePerGas: maxPriorityFeePerGas, // maxPriorityFeePerGas: maxPriorityFeePerGas,
); );

View file

@ -45,7 +45,12 @@ class PolygonWallet extends EVMChainWallet {
final initialErc20Tokens = DefaultPolygonErc20Tokens().initialPolygonErc20Tokens; final initialErc20Tokens = DefaultPolygonErc20Tokens().initialPolygonErc20Tokens;
for (final token in initialErc20Tokens) { for (final token in initialErc20Tokens) {
if (!evmChainErc20TokensBox.containsKey(token.contractAddress)) { if (evmChainErc20TokensBox.containsKey(token.contractAddress)) {
final existingToken = evmChainErc20TokensBox.get(token.contractAddress);
if (existingToken?.tag != token.tag) {
evmChainErc20TokensBox.put(token.contractAddress, token);
}
} else {
if (isMigration) token.enabled = false; if (isMigration) token.enabled = false;
evmChainErc20TokensBox.put(token.contractAddress, token); evmChainErc20TokensBox.put(token.contractAddress, token);
} }