diff --git a/examples/ethereum_pool.json b/examples/ethereum_pool.json index 2949a351c..730816cf5 100644 --- a/examples/ethereum_pool.json +++ b/examples/ethereum_pool.json @@ -109,14 +109,16 @@ } ], "paymentProcessing": { - "enabled": true, - "minimumPayment": 1, - "payoutScheme": "PPLNS", - "payoutSchemeConfig": { - "factor": 0.5 - }, - "keepUncles": false, - "keepTransactionFees": false + "enabled": true, + "minimumPayment": 1, + "payoutScheme": "PPLNS", + "payoutSchemeConfig": { + "factor": 0.5 + }, + "gas": 21000, + "maxFeePerGas": 50000000000, + "keepUncles": false, + "keepTransactionFees": false } } ] diff --git a/src/Miningcore/Blockchain/Ethereum/Configuration/EthereumPoolPaymentProcessingConfigExtra.cs b/src/Miningcore/Blockchain/Ethereum/Configuration/EthereumPoolPaymentProcessingConfigExtra.cs index 77065ccfa..d99e32725 100644 --- a/src/Miningcore/Blockchain/Ethereum/Configuration/EthereumPoolPaymentProcessingConfigExtra.cs +++ b/src/Miningcore/Blockchain/Ethereum/Configuration/EthereumPoolPaymentProcessingConfigExtra.cs @@ -11,5 +11,15 @@ public class EthereumPoolPaymentProcessingConfigExtra /// True to exempt uncle rewards from miner rewards /// public bool KeepUncles { get; set; } + + /// + /// Gas amount for payout tx (advanced users only) + /// + public ulong Gas { get; set; } + + /// + /// maximum amount you’re willing to pay + /// + public ulong MaxFeePerGas { get; set; } } } diff --git a/src/Miningcore/Blockchain/Ethereum/DaemonRequests/SendTransactionRequest.cs b/src/Miningcore/Blockchain/Ethereum/DaemonRequests/SendTransactionRequest.cs index fcaa1968b..22d3eb87c 100644 --- a/src/Miningcore/Blockchain/Ethereum/DaemonRequests/SendTransactionRequest.cs +++ b/src/Miningcore/Blockchain/Ethereum/DaemonRequests/SendTransactionRequest.cs @@ -41,5 +41,17 @@ public class SendTransactionRequest /// [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string Data { get; set; } + + /// + /// Maximum fee per gas the sender is willing to pay to miners in wei. + /// + [JsonConverter(typeof(HexToIntegralTypeJsonConverter))] + public ulong MaxPriorityFeePerGas { get; set; } + + /// + /// The maximum total fee per gas the sender is willing to pay(includes the network / base fee and miner / priority fee) in wei + /// + [JsonConverter(typeof(HexToIntegralTypeJsonConverter))] + public ulong MaxFeePerGas { get; set; } } } diff --git a/src/Miningcore/Blockchain/Ethereum/DaemonResponses/GetBlockResponse.cs b/src/Miningcore/Blockchain/Ethereum/DaemonResponses/GetBlockResponse.cs index fd5ce61a9..49985ba85 100644 --- a/src/Miningcore/Blockchain/Ethereum/DaemonResponses/GetBlockResponse.cs +++ b/src/Miningcore/Blockchain/Ethereum/DaemonResponses/GetBlockResponse.cs @@ -177,5 +177,11 @@ public class Block /// Array of uncle hashes. /// public string[] Uncles { get; set; } + + /// + /// Base fee per gas. + /// + [JsonConverter(typeof(HexToIntegralTypeJsonConverter))] + public ulong BaseFeePerGas { get; set; } } } diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs b/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs index 39bcc9e0b..07aed05e7 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs @@ -85,5 +85,6 @@ public static class EthCommands public const string SendTx = "eth_sendTransaction"; public const string UnlockAccount = "personal_unlockAccount"; public const string Subscribe = "eth_subscribe"; + public const string MaxPriorityFeePerGas = "eth_maxPriorityFeePerGas"; } } diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs b/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs index 9ffaae492..8dca14dce 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs @@ -126,6 +126,12 @@ public async Task ClassifyBlocksAsync(IMiningPool pool, Block[] blocks, var blockHashResponse = await rpcClient.ExecuteAsync(logger, EC.GetBlockByNumber, ct, new[] { (object) block.BlockHeight.ToStringHexWithPrefix(), true }); var blockHash = blockHashResponse.Response.Hash; + var baseGas = blockHashResponse.Response.BaseFeePerGas; + var gasUsed = blockHashResponse.Response.GasUsed; + + var burnedFee = (decimal) 0; + if(extraPoolConfig?.ChainTypeOverride == "Ethereum") + burnedFee = (baseGas * gasUsed / EthereumConstants.Wei); block.Hash = blockHash; block.Status = BlockStatus.Confirmed; @@ -138,7 +144,7 @@ public async Task ClassifyBlocksAsync(IMiningPool pool, Block[] blocks, block.Reward += blockInfo.Uncles.Length * (block.Reward / 32); // uncle rewards if(extraConfig?.KeepTransactionFees == false && blockInfo.Transactions?.Length > 0) - block.Reward += await GetTxRewardAsync(blockInfo, ct); // tx fees + block.Reward += await GetTxRewardAsync(blockInfo, ct) - burnedFee; logger.Info(() => $"[{LogCategory}] Unlocked block {block.BlockHeight} worth {FormatAmount(block.Reward)}"); @@ -396,6 +402,14 @@ private async Task PayoutAsync(Balance balance, CancellationToken ct) Value = amount.ToString("x").TrimStart('0'), }; + if(extraPoolConfig?.ChainTypeOverride == "Ethereum") + { + var maxPriorityFeePerGas = await rpcClient.ExecuteAsync(logger, EC.MaxPriorityFeePerGas, ct); + request.Gas = extraConfig.Gas; + request.MaxPriorityFeePerGas = maxPriorityFeePerGas.Response.IntegralFromHex(); + request.MaxFeePerGas = extraConfig.MaxFeePerGas; + } + var response = await rpcClient.ExecuteAsync(logger, EC.SendTx, ct, new[] { request }); if(response.Error != null)