Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Implementation of the dynamic base fee in common architecture features. #665

Merged
merged 5 commits into from
Jun 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 48 additions & 8 deletions packages/caver-core-method/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ const buildSendRequestFunc = (defer, sendSignedTx, sendTxCallback) => (payload,
return method.requestManager.send(payload, sendTxCallback)
}

const buildSendFunc = (method, isSendTx) => (...args) => {
const buildSendFunc = (method, isSendTx) => async (...args) => {
const defer = utils.promiEvent(!isSendTx)
const payload = method.toPayload(args)

Expand All @@ -459,27 +459,67 @@ const buildSendFunc = (method, isSendTx) => (...args) => {

const isGasPriceInputMissing = isSendTx && _.isObject(payload.params[0]) && payload.params[0].gasPrice === undefined

// If gasPrice input is missing, call getGasPrice rpc
if (!isGasPriceInputMissing) {
// The TxTypeEthereumDynamicFee transaction does not use the gasPrice field,
// so we need to check `maxPriorityFeePerGas` and `maxFeePerGas` field instead of `gasPrice`.
const isDynamicFeeTx = isSendTx && payload.params[0].type === TX_TYPE_STRING.TxTypeEthereumDynamicFee
const filledDynamicGasFeeTx =
isDynamicFeeTx && payload.params[0].maxPriorityFeePerGas !== undefined && payload.params[0].maxFeePerGas !== undefined

// gasPrice is already set so it is ok to send transaction.
if (!isGasPriceInputMissing || filledDynamicGasFeeTx) {
sendRequest(payload, method)
return defer.eventEmitter
}

// gasPrice is missing, have to fill gasPrice field before sending tx
const getHeader = new Method({
jimni1222 marked this conversation as resolved.
Show resolved Hide resolved
name: 'getHeader',
call: 'klay_getHeaderByNumber',
params: 1,
}).createFunction(method.requestManager)

const getGasPrice = new Method({
name: 'getGasPrice',
call: 'klay_gasPrice',
params: 0,
}).createFunction(method.requestManager)

getGasPrice((err, gasPrice) => {
const getMaxPriorityFeePerGas = new Method({
name: 'getMaxPriorityFeePerGas',
call: 'klay_maxPriorityFeePerGas',
params: 0,
}).createFunction(method.requestManager)

const header = await getHeader('latest')
const bf = utils.hexToNumber(header.baseFeePerGas || '0x0')

// The baseFeePerGas is bigger than 0 means that Klaytn uses dynamic gas price.
if (bf > 0) {
if (!isDynamicFeeTx) {
payload.params[0].gasPrice = bf * 2
} else {
// If maxFeePerGas is undefined, set maxFeePerGas with `baseFee * 2`.
payload.params[0].maxFeePerGas = payload.params[0].maxFeePerGas || bf * 2
// If maxPriorityFeePerGas is undefined, call `klay_maxPriorityFeePerGas`.
if (payload.params[0].maxPriorityFeePerGas === undefined) {
const maxPriorityFeePerGas = await getMaxPriorityFeePerGas()
payload.params[0].maxPriorityFeePerGas = maxPriorityFeePerGas
}
}
} else {
// If baseFeePerGas is not defined or 0, we need to use unit price for the `gasPrice` field.
const gp = await getGasPrice()
// The TxTypeEthereumDynamicFee transaction does not use the gasPrice field,
// so the gas price default is not set for TxTypeEthereumDynamicFee.
if (payload.params[0].type !== TX_TYPE_STRING.TxTypeEthereumDynamicFee) {
payload.params[0].gasPrice = gasPrice || payload.params[0].gasPrice
if (!isDynamicFeeTx) {
payload.params[0].gasPrice = payload.params[0].gasPrice || gp
} else {
payload.params[0].maxPriorityFeePerGas = payload.params[0].maxPriorityFeePerGas || gp
payload.params[0].maxFeePerGas = payload.params[0].maxFeePerGas || gp
}
sendRequest(payload, method)
})
}

sendRequest(payload, method)
/**
* attaching `.on('receipt')` is possible by returning defer.eventEmitter
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class AbstractTransaction {
* Calls `klay_chainID` klay rpc call.
*
* @example
* const result = tx.getChainId()
* const result = await tx.getChainId()
*
* @return {string} chain id
*/
Expand All @@ -166,11 +166,40 @@ class AbstractTransaction {
return chainId
}

/**
* Returns a suggested gas price to use in the transaction.
* If `baseFee` is bigger than `0` in the header,
* then returns `baseFee * 2`.
* If not, calls `klay_gasPrice` to return unit price of the gas.
*
* @example
* const result = await tx.getSuggestedGasPrice()
*
* @return {string} gas price
*/
async getSuggestedGasPrice() {
const bfStr = await this.getBaseFee()
const baseFee = utils.hexToNumber(bfStr)

let suggestedGasPrice
if (baseFee > 0) {
// After hard KIP-71 fork, set gasPrice (or maxFeePerGas) with baseFee * 2
suggestedGasPrice = baseFee * 2
suggestedGasPrice = utils.toHex(suggestedGasPrice)
} else {
// Before hard KIP-71 fork, set gasPrice (or maxFeePerGas) with gas unit price
suggestedGasPrice = await this.klaytnCall.getGasPrice()
}
return suggestedGasPrice
}

/**
* Calls `klay_gasPrice` klay rpc call.
* Note that when Klaytn network use dynamic gas fee,
* you need to use `tx.getSuggestedGasPrice` function in the gasPrice field.
*
* @example
* const result = tx.getGasPrice()
* const result = await tx.getGasPrice()
*
* @return {string} gas price
*/
Expand All @@ -183,7 +212,7 @@ class AbstractTransaction {
* Calls `klay_getTransactionCount` klay rpc call.
*
* @example
* const result = tx.getNonce('0x{from address}')
* const result = await tx.getNonce('0x{from address}')
*
* @return {string} nonce
*/
Expand All @@ -194,22 +223,23 @@ class AbstractTransaction {

/**
* Calls `klay_getHeaderByNumber` klay rpc call to get `baseFeePerGas` in header.
* If `baseFeePerGas` is not existed, returns '0x0'.
*
* @example
* const result = tx.getBaseFee()
* const result = await tx.getBaseFee()
*
* @return {string} base fee
*/
async getBaseFee() {
const header = await this.klaytnCall.getHeaderByNumber('latest')
return header.baseFeePerGas
return header.baseFeePerGas || '0x0'
}

/**
* Calls `klay_maxPriorityFeePerGas` klay rpc call.
*
* @example
* const result = tx.getMaxPriorityFeePerGas()
* const result = await tx.getMaxPriorityFeePerGas()
*
* @return {string} suggested max priority fee per gas
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class AccountUpdate extends AbstractTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class FeeDelegatedAccountUpdate extends AbstractFeeDelegatedTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ class FeeDelegatedAccountUpdateWithRatio extends AbstractFeeDelegatedWithRatioTr
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class Cancel extends AbstractTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ class FeeDelegatedCancel extends AbstractFeeDelegatedTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class FeeDelegatedCancelWithRatio extends AbstractFeeDelegatedWithRatioTransacti
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class ChainDataAnchoring extends AbstractTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ class FeeDelegatedChainDataAnchoring extends AbstractFeeDelegatedTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class FeeDelegatedChainDataAnchoringWithRatio extends AbstractFeeDelegatedWithRa
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ class EthereumAccessList extends AbstractTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,21 +390,17 @@ class EthereumDynamicFee extends AbstractTransaction {
async fillTransaction() {
const isNotMaxPriorityFeePerGas = isNot(this.maxPriorityFeePerGas)
const isNotMaxFeePerGas = isNot(this.maxFeePerGas)
const [chainId, maxPriorityFeePerGas, nonce, baseFee] = await Promise.all([
const [chainId, maxPriorityFeePerGas, nonce, maxFeePerGas] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNotMaxPriorityFeePerGas ? this.getMaxPriorityFeePerGas() : this.maxPriorityFeePerGas,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
isNotMaxPriorityFeePerGas || isNotMaxFeePerGas ? this.getBaseFee() : undefined,
isNotMaxFeePerGas ? this.getSuggestedGasPrice() : this.maxFeePerGas,
])

this.chainId = chainId
this.nonce = nonce
this.maxPriorityFeePerGas = maxPriorityFeePerGas

// Set maxFeePerGas with `block.baseFeePerGas.mul(2).add(maxPriorityFeePerGas)`
if (isNotMaxFeePerGas) {
this.maxFeePerGas = utils.hexToNumber(baseFee) * 2 + utils.hexToNumber(this.maxPriorityFeePerGas)
}
this.maxFeePerGas = maxFeePerGas
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ class LegacyTransaction extends AbstractTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ class FeeDelegatedSmartContractDeploy extends AbstractFeeDelegatedTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ class FeeDelegatedSmartContractDeployWithRatio extends AbstractFeeDelegatedWithR
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ class SmartContractDeploy extends AbstractTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ class FeeDelegatedSmartContractExecution extends AbstractFeeDelegatedTransaction
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ class FeeDelegatedSmartContractExecutionWithRatio extends AbstractFeeDelegatedWi
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class SmartContractExecution extends AbstractTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ class FeeDelegatedValueTransfer extends AbstractFeeDelegatedTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class FeeDelegatedValueTransferWithRatio extends AbstractFeeDelegatedWithRatioTr
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ class ValueTransfer extends AbstractTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ class FeeDelegatedValueTransferMemo extends AbstractFeeDelegatedTransaction {
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ class FeeDelegatedValueTransferMemoWithRatio extends AbstractFeeDelegatedWithRat
async fillTransaction() {
const [chainId, gasPrice, nonce] = await Promise.all([
isNot(this.chainId) ? this.getChainId() : this.chainId,
isNot(this.gasPrice) ? this.getGasPrice() : this.gasPrice,
isNot(this.gasPrice) ? this.getSuggestedGasPrice() : this.gasPrice,
isNot(this.nonce) ? this.getNonce(this.from) : this.nonce,
])

Expand Down
Loading