From ecffe456da1de7fabcb53ba268a8e24ecd2f448f Mon Sep 17 00:00:00 2001 From: rowan Date: Thu, 23 Jan 2025 23:19:04 +0900 Subject: [PATCH 1/7] Identify whether the evm fee data is provided by external caller --- apps/extension/src/pages/sign/ethereum/view.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/extension/src/pages/sign/ethereum/view.tsx b/apps/extension/src/pages/sign/ethereum/view.tsx index 067a287013..562e15c16f 100644 --- a/apps/extension/src/pages/sign/ethereum/view.tsx +++ b/apps/extension/src/pages/sign/ethereum/view.tsx @@ -108,6 +108,7 @@ export const EthereumSigningView: FunctionComponent<{ ); const [signingDataBuff, setSigningDataBuff] = useState(Buffer.from(message)); + const [preferNoSetFee, setPreferNoSetFee] = useState(false); const isTxSigning = signType === EthSignType.TRANSACTION; const gasSimulator = useGasSimulator( @@ -195,6 +196,10 @@ export const EthereumSigningView: FunctionComponent<{ ) ); } + + // 만약 사이트에서 제공된 gasLimit 또는 gasPrice가 있으면, + // 사용자가 수동으로 설정하는 것을 지양하기 위해 preferNoSetFee를 true로 설정 + setPreferNoSetFee(gasLimitFromTx > 0 || gasPriceFromTx > 0); } } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -742,6 +747,7 @@ export const EthereumSigningView: FunctionComponent<{ senderConfig={senderConfig} gasConfig={gasConfig} gasSimulator={gasSimulator} + disableAutomaticFeeSet={preferNoSetFee} isForEVMTx /> ); From 353cbdbfef92f4aeb1f08384d775ac31f6d78259 Mon Sep 17 00:00:00 2001 From: rowan Date: Thu, 23 Jan 2025 23:19:56 +0900 Subject: [PATCH 2/7] Enable to update the evm tx data when user manually changes fee options --- .../src/pages/sign/ethereum/view.tsx | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/apps/extension/src/pages/sign/ethereum/view.tsx b/apps/extension/src/pages/sign/ethereum/view.tsx index 562e15c16f..7f688431cb 100644 --- a/apps/extension/src/pages/sign/ethereum/view.tsx +++ b/apps/extension/src/pages/sign/ethereum/view.tsx @@ -48,7 +48,7 @@ import { import { handleExternalInteractionWithNoProceedNext } from "../../../utils"; import { EthTxBase } from "../components/eth-tx/render/tx-base"; import { MemoryKVStore } from "@keplr-wallet/common"; -import { CoinPretty, Dec, Int } from "@keplr-wallet/unit"; +import { CoinPretty, Dec } from "@keplr-wallet/unit"; import { Image } from "../../../components/image"; import { Column, Columns } from "../../../components/column"; import { useNavigate } from "react-router"; @@ -209,34 +209,26 @@ export const EthereumSigningView: FunctionComponent<{ if (isTxSigning && !interactionData.isInternal) { const unsignedTx = JSON.parse(Buffer.from(message).toString("utf8")); + // 수수료 옵션을 사이트에서 제공하는 경우, 수수료 옵션을 사용하지 않음 + if (feeConfig.type === "manual") { + return; + } + if (gasConfig.gas > 0) { unsignedTx.gasLimit = `0x${gasConfig.gas.toString(16)}`; + } - if (!unsignedTx.maxFeePerGas && !unsignedTx.gasPrice) { - unsignedTx.maxFeePerGas = `0x${new Int( - feeConfig.getFeePrimitive()[0].amount - ) - .div(new Int(gasConfig.gas)) - .toBigNumber() - .toString(16)}`; - } + // EIP-1559 우선 적용 + if (maxFeePerGas) { + unsignedTx.gasPrice = undefined; + unsignedTx.maxFeePerGas = maxFeePerGas; } - if ( - !unsignedTx.maxPriorityFeePerGas && - !unsignedTx.gasPrice && - maxPriorityFeePerGas - ) { - unsignedTx.maxPriorityFeePerGas = - unsignedTx.maxPriorityFeePerGas ?? maxPriorityFeePerGas; + if (unsignedTx.maxFeePerGas && maxPriorityFeePerGas) { + unsignedTx.maxPriorityFeePerGas = maxPriorityFeePerGas; } - if ( - !unsignedTx.gasPrice && - !unsignedTx.maxFeePerGas && - !unsignedTx.maxPriorityFeePerGas && - gasPrice - ) { + if (!maxFeePerGas && !maxPriorityFeePerGas && gasPrice) { unsignedTx.gasPrice = gasPrice; } @@ -252,6 +244,7 @@ export const EthereumSigningView: FunctionComponent<{ gasSimulator, gasConfig, feeConfig, + feeConfig.type, interactionData.isInternal, ]); From 5d01123089902a9af1403cb68ffc960c46f3e194 Mon Sep 17 00:00:00 2001 From: rowan Date: Fri, 24 Jan 2025 00:58:00 +0900 Subject: [PATCH 3/7] Disable approve button on evm tx sign page when some config is not proper --- apps/extension/src/pages/sign/ethereum/view.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/extension/src/pages/sign/ethereum/view.tsx b/apps/extension/src/pages/sign/ethereum/view.tsx index 7f688431cb..929d35faa3 100644 --- a/apps/extension/src/pages/sign/ethereum/view.tsx +++ b/apps/extension/src/pages/sign/ethereum/view.tsx @@ -43,6 +43,7 @@ import { useFeeConfig, useGasSimulator, useSenderConfig, + useTxConfigsValidate, useZeroAllowedGasConfig, } from "@keplr-wallet/hooks"; import { handleExternalInteractionWithNoProceedNext } from "../../../utils"; @@ -355,6 +356,12 @@ export const EthereumSigningView: FunctionComponent<{ const [isUnknownContractExecution, setIsUnknownContractExecution] = useState(false); + const txConfigsValidate = useTxConfigsValidate({ + senderConfig, + gasConfig, + feeConfig, + }); + const isLoading = signEthereumInteractionStore.isObsoleteInteractionApproved( interactionData.id @@ -362,6 +369,8 @@ export const EthereumSigningView: FunctionComponent<{ isLedgerInteracting || isKeystoneInteracting; + const buttonDisabled = txConfigsValidate.interactionBlocked; + return ( , + disabled: buttonDisabled, isLoading, onClick: async () => { try { From e2e5938208433649bc922dfe9f4177ab0e6592de Mon Sep 17 00:00:00 2001 From: rowan Date: Fri, 24 Jan 2025 01:03:06 +0900 Subject: [PATCH 4/7] Display right fee data on evm tx sign page and fee modal --- .../components/input/fee-control/index.tsx | 56 ++- .../components/input/fee-control/modal.tsx | 474 ++++++++++-------- 2 files changed, 318 insertions(+), 212 deletions(-) diff --git a/apps/extension/src/components/input/fee-control/index.tsx b/apps/extension/src/components/input/fee-control/index.tsx index 931454963f..e82a8ee624 100644 --- a/apps/extension/src/components/input/fee-control/index.tsx +++ b/apps/extension/src/components/input/fee-control/index.tsx @@ -215,7 +215,15 @@ export const FeeControl: FunctionComponent<{ const [isModalOpen, setIsModalOpen] = useState(false); - const isShowingEstimatedFee = isForEVMTx && !!gasSimulator?.gasEstimated; + // EVM 트랜잭션의 경우, 외부에서 fee를 설정한 경우를 구분하기 위해서 사용 + const isFeeSetByUser = isForEVMTx && feeConfig.type !== "manual"; + + // gasAdjustment와 gasEstimated를 사용해 계산된 값을 보여주는 경우 + const isShowingFeeWithGasAdjustment = + isForEVMTx && + gasSimulator?.enabled && + !!gasSimulator?.gasEstimated && + isFeeSetByUser; return ( @@ -274,18 +282,40 @@ export const FeeControl: FunctionComponent<{ })() .map((fee) => fee + .sub( + new Dec(feeConfig.l1DataFee?.toString() || "0") + ) .quo( new Dec( - isShowingEstimatedFee ? gasConfig?.gas || 1 : 1 + isShowingFeeWithGasAdjustment + ? gasConfig?.gas || 1 + : 1 ) ) .mul( new Dec( - isShowingEstimatedFee + isShowingFeeWithGasAdjustment ? gasSimulator?.gasEstimated || 1 : 1 ) ) + .mul( + new Dec( + isShowingFeeWithGasAdjustment + ? gasSimulator?.gasAdjustment || 1 + : 1 + ) + ) + .add( + new Dec(feeConfig.l1DataFee?.toString() || "0") + ) + .add( + isFeeSetByUser + ? new Dec(0) + : new Dec( + feeConfig.l1DataFee?.toString() || "0" + ) // evm fee가 외부에서 설정된 경우, fee = gasLimit * gasPrice이므로 l1DataFee를 더해줘야 함 + ) .maxDecimals(6) .inequalitySymbol(true) .trim(true) @@ -320,18 +350,34 @@ export const FeeControl: FunctionComponent<{ } else { const price = priceStore.calculatePrice( fee + .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) .quo( new Dec( - isShowingEstimatedFee ? gasConfig?.gas || 1 : 1 + isShowingFeeWithGasAdjustment + ? gasConfig?.gas || 1 + : 1 ) ) .mul( new Dec( - isShowingEstimatedFee + isShowingFeeWithGasAdjustment ? gasSimulator?.gasEstimated || 1 : 1 ) ) + .mul( + new Dec( + isShowingFeeWithGasAdjustment + ? gasSimulator?.gasAdjustment || 1 + : 1 + ) + ) + .add(new Dec(feeConfig.l1DataFee?.toString() || "0")) + .add( + isFeeSetByUser + ? new Dec(0) + : new Dec(feeConfig.l1DataFee?.toString() || "0") + ) ); if (price) { if (!total) { diff --git a/apps/extension/src/components/input/fee-control/modal.tsx b/apps/extension/src/components/input/fee-control/modal.tsx index 9a91a85a79..7bf76ba071 100644 --- a/apps/extension/src/components/input/fee-control/modal.tsx +++ b/apps/extension/src/components/input/fee-control/modal.tsx @@ -143,7 +143,10 @@ export const TransactionFeeModal: FunctionComponent<{ isGasSimulatorEnabled, ]); - const isShowingMaxFee = isForEVMTx && !!gasSimulator?.gasEstimated; + const isShowingMaxFee = isForEVMTx; + const isFeeSetByUser = isForEVMTx && feeConfig.type !== "manual"; + const isShowingGasEstimated = + isForEVMTx && !!isGasSimulatorEnabled && !!gasSimulator?.gasEstimated; return ( @@ -207,7 +210,7 @@ export const TransactionFeeModal: FunctionComponent<{ feeConfig={feeConfig} gasConfig={gasConfig} gasSimulator={gasSimulator} - isForEVMTx={isForEVMTx} + isShowingGasEstimated={isShowingGasEstimated} /> @@ -226,6 +229,11 @@ export const TransactionFeeModal: FunctionComponent<{ {`: ${feeConfig.fees[0] + .sub( + isFeeSetByUser + ? new Dec(feeConfig.l1DataFee?.toString() || "0") + : new Dec(0) + ) .maxDecimals(6) .inequalitySymbol(true) .trim(true) @@ -246,7 +254,11 @@ export const TransactionFeeModal: FunctionComponent<{ {` ${(() => { let total: PricePretty | undefined; let hasUnknown = false; - const maxFee = feeConfig.fees[0]; + const maxFee = feeConfig.fees[0].sub( + isFeeSetByUser + ? new Dec(feeConfig.l1DataFee?.toString() || "0") + : new Dec(0) + ); if (!maxFee.currency.coinGeckoId) { hasUnknown = true; } else { @@ -500,222 +512,270 @@ const FeeSelector: FunctionComponent<{ feeConfig: IFeeConfig; gasConfig?: IGasConfig; gasSimulator?: IGasSimulator; - isForEVMTx?: boolean; -}> = observer(({ feeConfig, gasConfig, gasSimulator, isForEVMTx }) => { - const { priceStore } = useStore(); - const theme = useTheme(); + isShowingGasEstimated?: boolean; +}> = observer( + ({ feeConfig, gasConfig, gasSimulator, isShowingGasEstimated }) => { + const { priceStore } = useStore(); + const theme = useTheme(); - const feeCurrency = - feeConfig.fees.length > 0 - ? feeConfig.fees[0].currency - : feeConfig.selectableFeeCurrencies[0]; + const feeCurrency = + feeConfig.fees.length > 0 + ? feeConfig.fees[0].currency + : feeConfig.selectableFeeCurrencies[0]; - if (!feeCurrency) { - return null; - } + if (!feeCurrency) { + return null; + } - const isShowingGasEstimatedOnly = isForEVMTx && !!gasSimulator?.gasEstimated; - - return ( - - - { - feeConfig.setFee({ - type: "low", - currency: feeCurrency, - }); - }} - selected={feeConfig.type === "low"} - > - {/* 텍스트의 길이 등에 의해서 레이아웃이 변하는걸 막기 위해서 가라로 1px의 너비르 가지는 Box로 감싸준다. */} - - - - - {feeCurrency.coinGeckoId ? ( - - {priceStore - .calculatePrice( - feeConfig - .getFeeTypePrettyForFeeCurrency(feeCurrency, "low") - .quo( - new Dec( - isShowingGasEstimatedOnly ? gasConfig?.gas || 1 : 1 + return ( + + + { + feeConfig.setFee({ + type: "low", + currency: feeCurrency, + }); + }} + selected={feeConfig.type === "low"} + > + {/* 텍스트의 길이 등에 의해서 레이아웃이 변하는걸 막기 위해서 가라로 1px의 너비르 가지는 Box로 감싸준다. */} + + + + + {feeCurrency.coinGeckoId ? ( + + {priceStore + .calculatePrice( + feeConfig + .getFeeTypePrettyForFeeCurrency(feeCurrency, "low") + .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) + .quo( + new Dec( + isShowingGasEstimated ? gasConfig?.gas || 1 : 1 + ) + ) + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasAdjustment || 1 + : 1 + ) ) - ) - .mul( - new Dec( - isShowingGasEstimatedOnly - ? gasSimulator?.gasEstimated || 1 - : 1 + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasEstimated || 1 + : 1 + ) ) - ) + .add(new Dec(feeConfig.l1DataFee?.toString() || "0")) + ) + ?.toString() || "-"} + + ) : null} + + {feeConfig + .getFeeTypePrettyForFeeCurrency(feeCurrency, "low") + .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) + .quo(new Dec(isShowingGasEstimated ? gasConfig?.gas || 1 : 1)) + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasAdjustment || 1 + : 1 + ) ) - ?.toString() || "-"} - - ) : null} - - {feeConfig - .getFeeTypePrettyForFeeCurrency(feeCurrency, "low") - .quo( - new Dec(isShowingGasEstimatedOnly ? gasConfig?.gas || 1 : 1) - ) - .mul( - new Dec( - isShowingGasEstimatedOnly - ? gasSimulator?.gasEstimated || 1 - : 1 + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasEstimated || 1 + : 1 + ) ) - ) - .maxDecimals(6) - .inequalitySymbol(true) - .trim(true) - .shrink(true) - .hideIBCMetadata(true) - .toString()} - - - - - - - { - feeConfig.setFee({ - type: "average", - currency: feeCurrency, - }); - }} - selected={feeConfig.type === "average"} - > - {/* 텍스트의 길이 등에 의해서 레이아웃이 변하는걸 막기 위해서 가라로 1px의 너비르 가지는 Box로 감싸준다. */} - - - - - {feeCurrency.coinGeckoId ? ( - - {priceStore - .calculatePrice( - feeConfig - .getFeeTypePrettyForFeeCurrency(feeCurrency, "average") - .quo( - new Dec( - isShowingGasEstimatedOnly ? gasConfig?.gas || 1 : 1 + .add(new Dec(feeConfig.l1DataFee?.toString() || "0")) + .maxDecimals(6) + .inequalitySymbol(true) + .trim(true) + .shrink(true) + .hideIBCMetadata(true) + .toString()} + + + + + + + { + feeConfig.setFee({ + type: "average", + currency: feeCurrency, + }); + }} + selected={feeConfig.type === "average"} + > + {/* 텍스트의 길이 등에 의해서 레이아웃이 변하는걸 막기 위해서 가라로 1px의 너비르 가지는 Box로 감싸준다. */} + + + + + {feeCurrency.coinGeckoId ? ( + + {priceStore + .calculatePrice( + feeConfig + .getFeeTypePrettyForFeeCurrency(feeCurrency, "average") + .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) + .quo( + new Dec( + isShowingGasEstimated ? gasConfig?.gas || 1 : 1 + ) + ) + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasAdjustment || 1 + : 1 + ) ) - ) - .mul( - new Dec( - isShowingGasEstimatedOnly - ? gasSimulator?.gasEstimated || 1 - : 1 + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasEstimated || 1 + : 1 + ) ) - ) + .add(new Dec(feeConfig.l1DataFee?.toString() || "0")) + ) + ?.toString() || "-"} + + ) : null} + + {feeConfig + .getFeeTypePrettyForFeeCurrency(feeCurrency, "average") + .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) + .quo(new Dec(isShowingGasEstimated ? gasConfig?.gas || 1 : 1)) + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasAdjustment || 1 + : 1 + ) ) - ?.toString() || "-"} - - ) : null} - - {feeConfig - .getFeeTypePrettyForFeeCurrency(feeCurrency, "average") - .quo( - new Dec(isShowingGasEstimatedOnly ? gasConfig?.gas || 1 : 1) - ) - .mul( - new Dec( - isShowingGasEstimatedOnly - ? gasSimulator?.gasEstimated || 1 - : 1 + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasEstimated || 1 + : 1 + ) ) - ) - .maxDecimals(6) - .inequalitySymbol(true) - .trim(true) - .shrink(true) - .hideIBCMetadata(true) - .toString()} - - - - - - - { - feeConfig.setFee({ - type: "high", - currency: feeCurrency, - }); - }} - selected={feeConfig.type === "high"} - > - {/* 텍스트의 길이 등에 의해서 레이아웃이 변하는걸 막기 위해서 가라로 1px의 너비르 가지는 Box로 감싸준다. */} - - - - - {feeCurrency.coinGeckoId ? ( - - {priceStore - .calculatePrice( - feeConfig - .getFeeTypePrettyForFeeCurrency(feeCurrency, "high") - .quo( - new Dec( - isShowingGasEstimatedOnly ? gasConfig?.gas || 1 : 1 + .add(new Dec(feeConfig.l1DataFee?.toString() || "0")) + .maxDecimals(6) + .inequalitySymbol(true) + .trim(true) + .shrink(true) + .hideIBCMetadata(true) + .toString()} + + + + + + + { + feeConfig.setFee({ + type: "high", + currency: feeCurrency, + }); + }} + selected={feeConfig.type === "high"} + > + {/* 텍스트의 길이 등에 의해서 레이아웃이 변하는걸 막기 위해서 가라로 1px의 너비르 가지는 Box로 감싸준다. */} + + + + + {feeCurrency.coinGeckoId ? ( + + {priceStore + .calculatePrice( + feeConfig + .getFeeTypePrettyForFeeCurrency(feeCurrency, "high") + .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) + .quo( + new Dec( + isShowingGasEstimated ? gasConfig?.gas || 1 : 1 + ) ) - ) - .mul( - new Dec( - isShowingGasEstimatedOnly - ? gasSimulator?.gasEstimated || 1 - : 1 + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasAdjustment || 1 + : 1 + ) ) - ) + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasEstimated || 1 + : 1 + ) + ) + .add(new Dec(feeConfig.l1DataFee?.toString() || "0")) + ) + ?.toString() || "-"} + + ) : null} + + {feeConfig + .getFeeTypePrettyForFeeCurrency(feeCurrency, "high") + .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) + .quo(new Dec(isShowingGasEstimated ? gasConfig?.gas || 1 : 1)) + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasAdjustment || 1 + : 1 + ) ) - ?.toString() || "-"} - - ) : null} - - {feeConfig - .getFeeTypePrettyForFeeCurrency(feeCurrency, "high") - .quo( - new Dec(isShowingGasEstimatedOnly ? gasConfig?.gas || 1 : 1) - ) - .mul( - new Dec( - isShowingGasEstimatedOnly - ? gasSimulator?.gasEstimated || 1 - : 1 + .mul( + new Dec( + isShowingGasEstimated + ? gasSimulator?.gasEstimated || 1 + : 1 + ) ) - ) - .maxDecimals(6) - .inequalitySymbol(true) - .trim(true) - .shrink(true) - .hideIBCMetadata(true) - .toString()} - - - - - - ); -}); + .add(new Dec(feeConfig.l1DataFee?.toString() || "0")) + .maxDecimals(6) + .inequalitySymbol(true) + .trim(true) + .shrink(true) + .hideIBCMetadata(true) + .toString()} + + + + + + ); + } +); From c4d0fbe7467d289ca3db19fdfc372944fedf1ded Mon Sep 17 00:00:00 2001 From: rowan Date: Fri, 24 Jan 2025 12:08:19 +0900 Subject: [PATCH 5/7] Refactor evm fee option changes --- .../components/input/fee-control/index.tsx | 19 +++--- .../components/input/fee-control/modal.tsx | 64 ++++++++++++------- .../src/pages/sign/ethereum/view.tsx | 8 +-- 3 files changed, 53 insertions(+), 38 deletions(-) diff --git a/apps/extension/src/components/input/fee-control/index.tsx b/apps/extension/src/components/input/fee-control/index.tsx index e82a8ee624..2e06375740 100644 --- a/apps/extension/src/components/input/fee-control/index.tsx +++ b/apps/extension/src/components/input/fee-control/index.tsx @@ -219,11 +219,8 @@ export const FeeControl: FunctionComponent<{ const isFeeSetByUser = isForEVMTx && feeConfig.type !== "manual"; // gasAdjustment와 gasEstimated를 사용해 계산된 값을 보여주는 경우 - const isShowingFeeWithGasAdjustment = - isForEVMTx && - gasSimulator?.enabled && - !!gasSimulator?.gasEstimated && - isFeeSetByUser; + const isShowingFeeWithGasEstimated = + !!gasSimulator?.enabled && !!gasSimulator?.gasEstimated && isFeeSetByUser; return ( @@ -287,21 +284,21 @@ export const FeeControl: FunctionComponent<{ ) .quo( new Dec( - isShowingFeeWithGasAdjustment + isShowingFeeWithGasEstimated ? gasConfig?.gas || 1 : 1 ) ) .mul( new Dec( - isShowingFeeWithGasAdjustment + isShowingFeeWithGasEstimated ? gasSimulator?.gasEstimated || 1 : 1 ) ) .mul( new Dec( - isShowingFeeWithGasAdjustment + isShowingFeeWithGasEstimated ? gasSimulator?.gasAdjustment || 1 : 1 ) @@ -353,21 +350,21 @@ export const FeeControl: FunctionComponent<{ .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) .quo( new Dec( - isShowingFeeWithGasAdjustment + isShowingFeeWithGasEstimated ? gasConfig?.gas || 1 : 1 ) ) .mul( new Dec( - isShowingFeeWithGasAdjustment + isShowingFeeWithGasEstimated ? gasSimulator?.gasEstimated || 1 : 1 ) ) .mul( new Dec( - isShowingFeeWithGasAdjustment + isShowingFeeWithGasEstimated ? gasSimulator?.gasAdjustment || 1 : 1 ) diff --git a/apps/extension/src/components/input/fee-control/modal.tsx b/apps/extension/src/components/input/fee-control/modal.tsx index 7bf76ba071..55af844cf3 100644 --- a/apps/extension/src/components/input/fee-control/modal.tsx +++ b/apps/extension/src/components/input/fee-control/modal.tsx @@ -145,8 +145,8 @@ export const TransactionFeeModal: FunctionComponent<{ const isShowingMaxFee = isForEVMTx; const isFeeSetByUser = isForEVMTx && feeConfig.type !== "manual"; - const isShowingGasEstimated = - isForEVMTx && !!isGasSimulatorEnabled && !!gasSimulator?.gasEstimated; + const isShowingFeeWithGasEstimated = + !!isGasSimulatorEnabled && !!gasSimulator?.gasEstimated && isFeeSetByUser; return ( @@ -210,7 +210,7 @@ export const TransactionFeeModal: FunctionComponent<{ feeConfig={feeConfig} gasConfig={gasConfig} gasSimulator={gasSimulator} - isShowingGasEstimated={isShowingGasEstimated} + isShowingFeeWithGasEstimated={isShowingFeeWithGasEstimated} /> @@ -512,9 +512,9 @@ const FeeSelector: FunctionComponent<{ feeConfig: IFeeConfig; gasConfig?: IGasConfig; gasSimulator?: IGasSimulator; - isShowingGasEstimated?: boolean; + isShowingFeeWithGasEstimated?: boolean; }> = observer( - ({ feeConfig, gasConfig, gasSimulator, isShowingGasEstimated }) => { + ({ feeConfig, gasConfig, gasSimulator, isShowingFeeWithGasEstimated }) => { const { priceStore } = useStore(); const theme = useTheme(); @@ -561,19 +561,21 @@ const FeeSelector: FunctionComponent<{ .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) .quo( new Dec( - isShowingGasEstimated ? gasConfig?.gas || 1 : 1 + isShowingFeeWithGasEstimated + ? gasConfig?.gas || 1 + : 1 ) ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasAdjustment || 1 : 1 ) ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasEstimated || 1 : 1 ) @@ -587,17 +589,21 @@ const FeeSelector: FunctionComponent<{ {feeConfig .getFeeTypePrettyForFeeCurrency(feeCurrency, "low") .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) - .quo(new Dec(isShowingGasEstimated ? gasConfig?.gas || 1 : 1)) + .quo( + new Dec( + isShowingFeeWithGasEstimated ? gasConfig?.gas || 1 : 1 + ) + ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasAdjustment || 1 : 1 ) ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasEstimated || 1 : 1 ) @@ -638,19 +644,21 @@ const FeeSelector: FunctionComponent<{ .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) .quo( new Dec( - isShowingGasEstimated ? gasConfig?.gas || 1 : 1 + isShowingFeeWithGasEstimated + ? gasConfig?.gas || 1 + : 1 ) ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasAdjustment || 1 : 1 ) ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasEstimated || 1 : 1 ) @@ -664,17 +672,21 @@ const FeeSelector: FunctionComponent<{ {feeConfig .getFeeTypePrettyForFeeCurrency(feeCurrency, "average") .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) - .quo(new Dec(isShowingGasEstimated ? gasConfig?.gas || 1 : 1)) + .quo( + new Dec( + isShowingFeeWithGasEstimated ? gasConfig?.gas || 1 : 1 + ) + ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasAdjustment || 1 : 1 ) ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasEstimated || 1 : 1 ) @@ -723,19 +735,21 @@ const FeeSelector: FunctionComponent<{ .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) .quo( new Dec( - isShowingGasEstimated ? gasConfig?.gas || 1 : 1 + isShowingFeeWithGasEstimated + ? gasConfig?.gas || 1 + : 1 ) ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasAdjustment || 1 : 1 ) ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasEstimated || 1 : 1 ) @@ -749,17 +763,21 @@ const FeeSelector: FunctionComponent<{ {feeConfig .getFeeTypePrettyForFeeCurrency(feeCurrency, "high") .sub(new Dec(feeConfig.l1DataFee?.toString() || "0")) - .quo(new Dec(isShowingGasEstimated ? gasConfig?.gas || 1 : 1)) + .quo( + new Dec( + isShowingFeeWithGasEstimated ? gasConfig?.gas || 1 : 1 + ) + ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasAdjustment || 1 : 1 ) ) .mul( new Dec( - isShowingGasEstimated + isShowingFeeWithGasEstimated ? gasSimulator?.gasEstimated || 1 : 1 ) diff --git a/apps/extension/src/pages/sign/ethereum/view.tsx b/apps/extension/src/pages/sign/ethereum/view.tsx index 929d35faa3..39828e9813 100644 --- a/apps/extension/src/pages/sign/ethereum/view.tsx +++ b/apps/extension/src/pages/sign/ethereum/view.tsx @@ -190,17 +190,17 @@ export const EthereumSigningView: FunctionComponent<{ unsignedTx.maxFeePerGas ?? unsignedTx.gasPrice ?? 0 ); if (gasPriceFromTx > 0) { + // 사이트에서 제공된 수수료를 사용하는 경우, fee type이 manual로 설정되며, + // 사용자가 수동으로 설정하는 것을 지양하기 위해 preferNoSetFee를 true로 설정 feeConfig.setFee( new CoinPretty( chainInfo.currencies[0], new Dec(gasConfig.gas).mul(new Dec(gasPriceFromTx)) ) ); - } - // 만약 사이트에서 제공된 gasLimit 또는 gasPrice가 있으면, - // 사용자가 수동으로 설정하는 것을 지양하기 위해 preferNoSetFee를 true로 설정 - setPreferNoSetFee(gasLimitFromTx > 0 || gasPriceFromTx > 0); + setPreferNoSetFee(!interactionData.isInternal); + } } } // eslint-disable-next-line react-hooks/exhaustive-deps From 3c771c8bca6b5d2c7761588d0e01a72f8de42f2a Mon Sep 17 00:00:00 2001 From: rowan Date: Fri, 24 Jan 2025 12:08:34 +0900 Subject: [PATCH 6/7] Display proper fee and price for evm on `FeeSummary` component --- .../sign/components/fee-summary/index.tsx | 27 ++----------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/apps/extension/src/pages/sign/components/fee-summary/index.tsx b/apps/extension/src/pages/sign/components/fee-summary/index.tsx index c149cb76fa..f8d48f0574 100644 --- a/apps/extension/src/pages/sign/components/fee-summary/index.tsx +++ b/apps/extension/src/pages/sign/components/fee-summary/index.tsx @@ -29,8 +29,6 @@ export const FeeSummary: FunctionComponent<{ const theme = useTheme(); - const isShowingGasEstimatedOnly = isForEVMTx && !!gasSimulator?.gasEstimated; - return ( fee - .quo( - new Dec(isShowingGasEstimatedOnly ? gasConfig?.gas || 1 : 1) - ) - .mul( - new Dec( - isShowingGasEstimatedOnly - ? gasSimulator?.gasEstimated || 1 - : 1 - ) - ) + .add(new Dec(feeConfig.l1DataFee?.toString() || "0")) .maxDecimals(6) .inequalitySymbol(true) .trim(true) @@ -134,19 +123,7 @@ export const FeeSummary: FunctionComponent<{ break; } else { const price = priceStore.calculatePrice( - fee - .quo( - new Dec( - isShowingGasEstimatedOnly ? gasConfig?.gas || 1 : 1 - ) - ) - .mul( - new Dec( - isShowingGasEstimatedOnly - ? gasSimulator?.gasEstimated || 1 - : 1 - ) - ) + fee.add(new Dec(feeConfig.l1DataFee?.toString() || "0")) ); if (price) { if (!total) { From ded4acb42db202dc411a3914ffffdf6e4917dd23 Mon Sep 17 00:00:00 2001 From: rowan Date: Fri, 24 Jan 2025 16:01:58 +0900 Subject: [PATCH 7/7] Fix to call the proxy contract directly when retrieving op stack l1 data fee --- packages/stores-eth/src/account/base.ts | 34 +++---------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/packages/stores-eth/src/account/base.ts b/packages/stores-eth/src/account/base.ts index 8c608a25e6..686d72beb8 100644 --- a/packages/stores-eth/src/account/base.ts +++ b/packages/stores-eth/src/account/base.ts @@ -21,22 +21,7 @@ import { Interface } from "@ethersproject/abi"; const opStackGasPriceOracleProxyAddress = "0x420000000000000000000000000000000000000F"; -const opStackGasPriceOracleProxyABI = new Interface([ - { - constant: true, - inputs: [], - name: "implementation", - outputs: [ - { - name: "", - type: "address", - }, - ], - payable: false, - stateMutability: "view", - type: "function", - }, -]); + const opStackGasPriceOracleABI = new Interface([ { inputs: [{ internalType: "bytes", name: "_data", type: "bytes" }], @@ -153,30 +138,17 @@ export class EthereumAccountBase { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const keplr = (await this.getKeplr())!; - const implementationAddress = await keplr.ethereum.request({ - method: "eth_call", - params: [ - { - to: opStackGasPriceOracleProxyAddress, - data: opStackGasPriceOracleProxyABI.encodeFunctionData( - "implementation" - ), - }, - ], - chainId: this.chainId, - }); - const gasPriceOracleContractAddress = - "0x" + implementationAddress.slice(26); const l1Fee = await keplr.ethereum.request({ method: "eth_call", params: [ { - to: gasPriceOracleContractAddress, + to: opStackGasPriceOracleProxyAddress, data: opStackGasPriceOracleABI.encodeFunctionData("getL1Fee", [ serialize(unsignedTx), ]), }, + "latest", ], chainId: this.chainId, });