KIP 162: Priority Fee Mechanism
Author | Ollie, Sawyer, Aidan |
---|---|
Discussions-To | https://github.com/klaytn/kips/issues/161 |
Status | Draft |
Type | Standard Track |
Category | Core |
Created | 2024-03-20 |
Simple summary
Priority fee mechanism for transaction type 2 (EthereumDynamicFee) in terms of transaction ordering.
Abstract
Activate the priority fee mechanism as defined in the EIP-1559. The maxPriorityFeePerGas field of transaction type 2 is no longer a placeholder, now it represents the priority fee the sender is willing to pay. The transactions are ordered by descending effective gas price, which is usually in the descending priority fee order. Under congested network, high priority transactions can be included to block by declaring high priority fee.
Motivation
In Klaytn, the KIP-71 dynamic base fee mechanism and the FCFS (first come first serve) policy had been introduced to alleviate the network stability and usability issue caused by transaction bursts. However, if there are enough transactions that are willing to pay the upper bound base fee (e.g. 750 ston) then the network traffic will stay contested. Under such a condition, senders may experience transaction delay even if they pay the highest fee and send the transactions as soon as possible.
Raising the base fee upper bound is undesirable solution because the users no longer be able to predict or budget their gas fee spendings. Instead, this proposal adds a reliable method for urgent transactions to be included in blocks.
Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC-2119.
Block processing
Configuration
The KIP-162 shall be activated since the DRAGON_FORK_BLOCK_NUMBER
.
config | value |
---|---|
MAGMA_FORK_BLOCK_NUMBER |
98347376 (testnet), 99841497 (mainnet) |
DRAGON_FORK_BLOCK_NUMBER |
TBD |
Effective gas price and effective priority fee per gas
The effective gas price and effective priorirty fee per gas of a transaction at given block are calculated as follows. The effective gas price is the actual price of gas fee paid by the sender. The calculation differs by whether the transaction type is 2 (EIP-1559 EthereumDynamicFee) or not.
def EffectiveGasPrice(header: Header, tx: Transaction):
if header.number >= DRAGON_FORK_BLOCK_NUMBER:
# Transaction type 2 has {maxFeePerGas, maxPriorityFeePerGas} fields
# Other transactions only have {gasPrice} field
if tx.type == 2:
maxFeePerGas = tx.maxFeePerGas
maxPriorityFeePerGas = tx.maxPriorityFeePerGas
else:
# makes EffectiveGasPrice() = tx.gasPrice
maxFeePerGas = tx.gasPrice
maxPriorityFeePerGas = tx.gasPrice
return min(header.baseFeePerGas + maxPriorityFeePerGas, maxFeePerGas)
elif header.number >= MAGMA_FORK_BLOCK_NUMBER:
return header.baseFeePerGas
else:
# Note: before Magma hardfork, transactions must satisfy
# tx.gasPrice == config.UnitPrice or tx.maxFeePerGas == config.UnitPrice.
# Therefore EffectiveGasPrice is essentially config.UnitPrice.
if tx.type == 2:
return tx.maxFeePerGas
else:
return tx.gasPrice
def EffectivePriorityFeePerGas(header: Header, tx: Transaction):
if header.number >= DRAGON_FORK_BLOCK_NUMBER:
effectiveGasPrice = EffectiveGasPrice(header, tx)
return effectiveGasPrice - header.baseFeePerGas
else:
return 0
KIP-82 reward scheme
The KIP-82 reward scheme is slightly modified. The get_total_fee
now accounts for effective gas price. Otherwise remains the same.
def get_total_fee(header: Header, txs: list[Transaction], receipts: list[Receipt]):
# Note: EffectiveGasPrice handles hardfork
totalFee = 0
for i in range(len(txs)):
totalFee += EffectiveGasPrice(header, txs[i]) * receipts[i].gasUsed
return totalFee
EVM GASPRICE opcode
The GASPRICE
(0x3a) opcode returns the effective gas price of the currently executing transaction.
Transaction pool
Transaction ordering
Block transaction ordering depends on client implementation as the ordering is not checked by block validators. However, under the KIP-82 reward scheme, a proposer should prioritize high priority fee transactions for the maximum proposer reward.
Block proposers are recommended to order transactions with descending effective gas price, and the same effective gas price are sorted by transaction arrival time. This discourages the transaction spamming where a sender sends many transactions hoping that at least one is included in the block. Instead, the sender would pay a higher priority fee to ensure the transaction be included in the block.
Txpool management
A transaction pool should not accept underpriced transactions. A transaction is underpriced if its tx.gasPrice
or tx.maxFeePerGas
field is lower than the baseFeePerGas of the pending block.
JSON-RPC API
eth_gasPrice
and klay_gasPrice
Returns suggested value for gasPrice
or maxFeePerGas
fields of a transaction.
- Parameters: none
- Result: Recommended gas price in peb. The result depends on the client implementation.
- Example
curl $RPC_URL -X POST -H 'Content-Type: application/json' --data ' {"jsonrpc":"2.0","id":1,"method":"eth_gasPrice","params":[]}' {"jsonrpc":"2.0","id":1,"result":"0xba43b7400"}
eth_maxPriorityFeePerGas
and klay_maxPriorityFeePerGas
Returns suggested value for gasPrice
or maxFeePerGas
fields of a transaction.
- Parameters: none
- Result: Recommended priority fee per gas in peb. The result depends on the client implementation.
- Example
curl $RPC_URL -X POST -H 'Content-Type: application/json' --data ' {"jsonrpc":"2.0","id":1,"method":"eth_maxPriorityFeePerGas","params":[]}' {"jsonrpc":"2.0","id":1,"result":"0x3b9aca00"}
eth_feeHistory
and klay_feeHistory
Returns historical gas information for a range of blocks.
- Parameters
blockCount
- Number of blocks in the requested range.newestBlock
- Highest block of the requested range. Can be a number or “latest”.rewardPercentiles
- (optional) A monotonically increasing list of percentile (between 0 and 100) values. For each block in the requested range, the transactions will be sorted in ascending order by effective tip per gas and sampled at the specified percentiles.
- Result
oldestBlock
- Lowest number block of returned range.baseFeePerGas
- An array of block base fee per gas. This includes the next block after the newest of the returned range, because this value can be derived from the newest block. Zeroes are returned for pre-Magma blocks.gasUsedRatio
- An array of block gas used ratios. Measures the network congestion level. These are calculated as the ratio of block gas used and KIP-71 MAX_BLOCK_GAS_USED_FOR_BASE_FEE. If the ratio is above 1, then 1 is returned.reward
- (optional) A 2D array of effective priority fees per gas.reward[n][i]
is therewardPercentiles[i]
-th percentile effective priority fees per gas among the transactions in the blockoldestBlock + n
. Only returned ifrewardPercentiles
is specified.
- Example
curl $RPC_URL -X POST -H 'Content-Type: application/json' --data ' {"jsonrpc":"2.0","id":1,"method":"eth_feeHistory","params":[ 4, "latest", [50.0, 90.0, 95.0] ]}' { "id": "1", "jsonrpc": "2.0", "result": { "oldestBlock": "0x8e0a025", "baseFeePerGas": ["0x5d21dba00", "0x5d21dba00", "0x5d21dba00", "0x61c9f3680"], "gasUsedRatio": [0.023, 0.31, 1.0, 0.88], "reward": [ ["0x3b9aca00", "0x3b9aca00", "0x9502f900"], ["0x3b9aca00", "0x3b9aca00", "0x9502f900"], ["0x3b9aca00", "0x9502f900", "0x2e90edd00"], ["0x3b9aca00", "0x9502f900", "0x30e4f9b40"], ] } }
Rationale
A KIP-71 parameter is used in place of block gas limit
The Ethereum’s eth_feeHistory
calculates gasUsedRatio as block.gasUsed/blockGasLimit
. But Klaytn does not have hard limit of block gas. Instead, Klaytn’s MAX_BLOCK_GAS_USED_FOR_BASE_FEE is analogous to Ethereum’s block gas limit.
In Ethereum, block gas limit is 30,000,000 and the base fee starts to rise when the block gas used exceeds 15,000,000 (block.gasLimit / ELASTICITY_MULTIPLIER
). Similartly, the Klaytn’s initial KIP-71 parameters stipulates that the block gas used is only accounted until 60,000,000 for the purpose of base fee calculation (MAX_BLOCK_GAS_USED_FOR_BASE_FEE
), and the base fee starts to rise when the block gas used exceeds 30,000,000 (GAS_TARGET
).
Backward compatibility
Continued use of other transaction types
Legacy (type 0) transactions, EIP-2930 AccessList (type 1) transactions, and Klaytn transaction types (types 8+) will work and be included in blocks. Those transactions have gasPrice
field but no maxFeePerGas
nor maxPriorityFeePerGas
fields. For those transaction types, their effective gas price is considered to equal to the gasPrice
. The senders pay the full price as declared in the gasPrice
. This policy is identical to EIP-1559 and the same as pre-1559 auction market. In this manner, those transaction types pay a nonzero priority fee.
baseFeePerGas | transaction | effectiveGasPrice | effectivePriorityFeePerGas |
---|---|---|---|
25 | {type: 0, gasPrice: 26} | 26 | 1 |
25 | {type: 2, maxFeePerGas: 51, maxPriorityFeePerGas: 1} | 26 | 1 |
EVM opcodes
The GASPRICE
(0x3a) opcode is backwards compatible because it had been correctly returning the effective gas price before DRAGON_FORK_BLOCK_NUMBER
. The BASEFEE
(0x48) opcode remains the same; returns the base fee per gas of the currently executing block.
References
- https://github.com/klaytn/kips/blob/main/KIPs/kip-71.md
- https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
- https://github.com/ethereum/execution-apis/blob/main/src/eth/fee_market.yaml