From b2bdd7166f44df0fc9b28ac66ff75a9d31e0e90f Mon Sep 17 00:00:00 2001 From: Blazebrain Date: Fri, 20 Jun 2025 19:03:56 +0100 Subject: [PATCH] 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 --- cw_evm/lib/evm_chain_client.dart | 5 ++- cw_evm/lib/evm_chain_wallet.dart | 54 ++++++++++++++++++++++++------ cw_polygon/lib/polygon_client.dart | 11 ++++-- 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart index 8b45d5544..353ae6b44 100644 --- a/cw_evm/lib/evm_chain_client.dart +++ b/cw_evm/lib/evm_chain_client.dart @@ -109,7 +109,6 @@ abstract class EVMChainClient { sender: senderAddress, to: toAddress, value: value, - // maxFeePerGas: maxFeePerGas, ); return estimatedGas.toInt(); @@ -165,6 +164,7 @@ abstract class EVMChainClient { required int exponent, String? contractAddress, String? data, + int? gasPrice, }) async { assert(currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly || @@ -180,6 +180,7 @@ abstract class EVMChainClient { data: data != null ? hexToBytes(data) : null, maxGas: estimatedGasUnits, maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), + gasPrice: gasPrice != null ? EtherAmount.fromInt(EtherUnit.wei, gasPrice) : null, ); Uint8List signedTransaction; @@ -224,6 +225,7 @@ abstract class EVMChainClient { required EVMChainTransactionPriority priority, required int exponent, required String contractAddress, + int? gasPrice, }) async { final Transaction transaction = createTransaction( @@ -233,6 +235,7 @@ abstract class EVMChainClient { amount: EtherAmount.zero(), maxGas: estimatedGasUnits, maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), + gasPrice: gasPrice != null ? EtherAmount.fromInt(EtherUnit.wei, gasPrice) : null, ); final erc20 = ERC20( diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index 18f6e6ee5..1791258f5 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -263,31 +263,65 @@ abstract class EVMChainWalletBase final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt(); int maxFeePerGas; + int adjustedGasPrice; + + bool isPolygon = _client.chainId == 137; + if (gasBaseFee != null) { // MaxFeePerGas with EIP1559; maxFeePerGas = gasBaseFee! + priorityFee; } else { // 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( contractAddress: contractAddress, senderAddress: _evmChainPrivateKey.address, value: EtherAmount.fromBigInt(EtherUnit.wei, amount!), - gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice), + gasPrice: EtherAmount.fromInt(EtherUnit.wei, adjustedGasPrice), toAddress: EthereumAddress.fromHex(receivingAddressHex), maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), data: data, ); - final totalGasFee = estimatedGas * maxFeePerGas; + final totalGasFee = estimatedGas * adjustedGasPrice; return GasParamsHandler( estimatedGasUnits: estimatedGas, estimatedGasFee: totalGasFee, maxFeePerGas: maxFeePerGas, - gasPrice: gasPrice, + gasPrice: adjustedGasPrice, ); } return GasParamsHandler.zero(); @@ -476,23 +510,20 @@ abstract class EVMChainWalletBase contractAddress: transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null, data: hexOpReturnMemo, + gasPrice: maxFeePerGasForTransaction, ); return pendingEVMChainTransaction; } - Future createApprovalTransaction( - BigInt amount, - String spender, - CryptoCurrency token, - EVMChainTransactionPriority priority) async { + Future createApprovalTransaction(BigInt amount, String spender, + CryptoCurrency token, EVMChainTransactionPriority priority) async { final CryptoCurrency transactionCurrency = balance.keys.firstWhere((element) => element.title == token.title); assert(transactionCurrency is Erc20Token); final data = _client.getEncodedDataForApprovalTransaction( - contractAddress: EthereumAddress.fromHex( - (transactionCurrency as Erc20Token).contractAddress), + contractAddress: EthereumAddress.fromHex((transactionCurrency as Erc20Token).contractAddress), value: EtherAmount.fromBigInt(EtherUnit.wei, amount), toAddress: EthereumAddress.fromHex(spender), ); @@ -515,6 +546,7 @@ abstract class EVMChainWalletBase estimatedGasUnits: gasFeesModel.estimatedGasUnits, exponent: transactionCurrency.decimal, contractAddress: transactionCurrency.contractAddress, + gasPrice: gasFeesModel.gasPrice, ); } diff --git a/cw_polygon/lib/polygon_client.dart b/cw_polygon/lib/polygon_client.dart index 7e9e882fa..2aa6ec39a 100644 --- a/cw_polygon/lib/polygon_client.dart +++ b/cw_polygon/lib/polygon_client.dart @@ -18,13 +18,20 @@ class PolygonClient extends EVMChainClient { EtherAmount? gasPrice, 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( from: from, to: to, value: amount, - // data: data, + data: data, maxGas: maxGas, - // gasPrice: gasPrice, + gasPrice: finalGasPrice, // maxFeePerGas: maxFeePerGas, // maxPriorityFeePerGas: maxPriorityFeePerGas, );