Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: detect eip7702 transactions #2814

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions _raw/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2528,6 +2528,9 @@
"description": "You're all set to use Rabby Wallet",
"button": "Done"
}
},
"eip7702": {
"alert": "EIP-7702 is not supported yet"
}
},
"component": {
Expand Down
5 changes: 4 additions & 1 deletion _raw/locales/zh-CN/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2569,6 +2569,9 @@
"metamaskModeDapps": {
"title": "MetaMask 模式",
"desc": "MetaMask 模式已为以下 Dapps 启用。您可以通过选择 MetaMask 选项连接 Rabby。"
},
"eip7702": {
"alert": "EIP-7702 尚未支持"
}
},
"component": {
Expand Down Expand Up @@ -2782,4 +2785,4 @@
},
"IMPORTED_HD_KEYRING_NEED_PASSPHRASE": "通过助记词(密码)导入"
}
}
}
36 changes: 13 additions & 23 deletions src/background/controller/provider/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ import {
import buildinProvider from 'background/utils/buildinProvider';
import BaseController from '../base';
import { Account } from 'background/service/preference';
import { validateGasPriceRange, is1559Tx } from '@/utils/transaction';
import {
validateGasPriceRange,
is1559Tx,
ApprovalRes,
is7702Tx,
} from '@/utils/transaction';
import stats from '@/stats';
import BigNumber from 'bignumber.js';
import { AddEthereumChainParams } from '@/ui/views/Approval/components/AddChain/type';
Expand Down Expand Up @@ -95,28 +100,6 @@ const convertToHex = (data: Buffer | bigint) => {
return bufferToHex(data);
};

interface ApprovalRes extends Tx {
type?: string;
address?: string;
uiRequestComponent?: string;
isSend?: boolean;
isSpeedUp?: boolean;
isCancel?: boolean;
isSwap?: boolean;
isGnosis?: boolean;
account?: Account;
extra?: Record<string, any>;
traceId?: string;
$ctx?: any;
signingTxId?: string;
pushType?: TxPushType;
lowGasDeadline?: number;
reqId?: string;
isGasLess?: boolean;
isGasAccount?: boolean;
logId?: string;
}

interface Web3WalletPermission {
// The name of the method corresponding to the permission
parentCapability: string;
Expand Down Expand Up @@ -406,6 +389,13 @@ class ProviderController extends BaseController {
delete approvalRes.isGasAccount;

let is1559 = is1559Tx(approvalRes);
const is7702 = is7702Tx(approvalRes);

if (is7702) {
// todo
throw new Error('not support 7702');
}

if (
is1559 &&
approvalRes.maxFeePerGas === approvalRes.maxPriorityFeePerGas
Expand Down
49 changes: 49 additions & 0 deletions src/ui/views/Approval/components/EIP7702Warning.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Button } from 'antd';
import clsx from 'clsx';
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import IconWarning from 'ui/assets/warning.svg';
import { useApproval } from 'ui/utils';
import Browser from 'webextension-polyfill';

export const EIP7702Warning = () => {
const [, , rejectApproval] = useApproval();
const { t } = useTranslation();

useEffect(() => {
Browser.windows.getCurrent().then((window) => {
if (window.id) {
Browser.windows.update(window.id, {
height: 390,
});
}
});
}, []);
return (
<>
<div className="approval-add-asset">
<>
<img
src={IconWarning}
className="w-[68px] h-[68px] mt-[72px] mb-[20px] mx-auto"
/>
<div className="text-r-neutral-body text-[20px] leading-[26px] w-[344px] mx-auto font-medium text-center">
{t('page.eip7702.alert')}
</div>
</>
</div>
<footer className="connect-footer p-[20px]">
<div className={clsx(['action-buttons flex mt-4', 'justify-center'])}>
<Button
type="primary"
size="large"
className="w-[200px]"
onClick={() => rejectApproval()}
>
{t('global.ok')}
</Button>
</div>
</footer>
</>
);
};
18 changes: 17 additions & 1 deletion src/ui/views/Approval/components/SignTx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ import {
ParsedTransactionActionData,
} from '@rabby-wallet/rabby-action';
import { ga4 } from '@/utils/ga4';
import { EIP7702Warning } from './EIP7702Warning';

interface BasicCoboArgusInfo {
address: string;
Expand Down Expand Up @@ -144,6 +145,12 @@ export const normalizeTxParams = (tx) => {
copy.data = `0x${tx.data}`;
}
}

if ('authorizationList' in copy) {
copy.authorizationList = copy.authorizationList.map((item) => {
return normalizeHex(item);
});
}
} catch (e) {
Sentry.captureException(
new Error(`normalizeTxParams failed, ${JSON.stringify(e)}`)
Expand Down Expand Up @@ -468,6 +475,7 @@ const SignTx = ({ params, origin }: SignTxProps) => {
const wallet = useWallet();
if (!chain) throw new Error('No support chain found');
const [support1559, setSupport1559] = useState(chain.eip['1559']);
const [support7702, setSupport7702] = useState(chain.eip['7702']);
const [isLedger, setIsLedger] = useState(false);
const { userData, rules, currentTx, tokenDetail } = useRabbySelector((s) => ({
userData: s.securityEngine.userData,
Expand Down Expand Up @@ -570,7 +578,15 @@ const SignTx = ({ params, origin }: SignTxProps) => {
isViewGnosisSafe,
reqId,
safeTxGas,
} = normalizeTxParams(params.data[0]);
authorizationList,
} = useMemo(() => {
return normalizeTxParams(params.data[0]);
}, [params.data]);

// is eip7702
if (authorizationList) {
return <EIP7702Warning />;
}

const [pushInfo, setPushInfo] = useState<{
type: TxPushType;
Expand Down
44 changes: 43 additions & 1 deletion src/utils/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,40 @@ import {
SAFE_GAS_LIMIT_BUFFER,
SAFE_GAS_LIMIT_RATIO,
} from 'consts';
import { ExplainTxResponse, GasLevel, Tx } from 'background/service/openapi';
import {
ExplainTxResponse,
GasLevel,
Tx,
TxPushType,
} from 'background/service/openapi';
import { findChain } from './chain';
import type { WalletControllerType } from '@/ui/utils';
import { Chain } from '@debank/common';
import i18n from '@/i18n';
import { Account } from 'background/service/preference';

export interface ApprovalRes extends Tx {
type?: string;
address?: string;
uiRequestComponent?: string;
isSend?: boolean;
isSpeedUp?: boolean;
isCancel?: boolean;
isSwap?: boolean;
isGnosis?: boolean;
account?: Account;
extra?: Record<string, any>;
traceId?: string;
$ctx?: any;
signingTxId?: string;
pushType?: TxPushType;
lowGasDeadline?: number;
reqId?: string;
isGasLess?: boolean;
isGasAccount?: boolean;
logId?: string;
authorizationList?: (Uint8Array | string)[];
}

export const validateGasPriceRange = (tx: Tx) => {
const chain = findChain({
Expand Down Expand Up @@ -63,6 +92,19 @@ export const is1559Tx = (tx: Tx) => {
return isHexString(tx.maxFeePerGas!) && isHexString(tx.maxPriorityFeePerGas!);
};

export const is7702Tx = (tx: ApprovalRes) => {
if ('authorizationList' in tx) {
if (
Array.isArray(tx.authorizationList) &&
tx.authorizationList.length > 0
) {
return true;
}
}

return false;
};

export function getKRCategoryByType(type?: string) {
return KEYRING_CATEGORY_MAP[type as any] || null;
}
Expand Down
Loading