From 80e97e51630edaab0cd1d1303023c45c8b7640c4 Mon Sep 17 00:00:00 2001 From: Ben Kremer Date: Mon, 21 Mar 2022 12:40:54 +0100 Subject: [PATCH] feat: adds sig verification for `eth_signTransaction` --- dapps/react-dapp-v2-with-ethers/package.json | 1 + dapps/react-dapp-v2-with-ethers/src/App.tsx | 12 ++++--- dapps/react-dapp-v2-with-ethers/yarn.lock | 36 ++++++++++++++++++- dapps/react-dapp-v2-with-web3js/package.json | 1 + dapps/react-dapp-v2-with-web3js/src/App.tsx | 12 ++++--- dapps/react-dapp-v2-with-web3js/yarn.lock | 2 +- dapps/react-dapp-v2/package.json | 1 + .../src/contexts/JsonRpcContext.tsx | 19 +++++++--- dapps/react-dapp-v2/yarn.lock | 36 ++++++++++++++++++- 9 files changed, 102 insertions(+), 18 deletions(-) diff --git a/dapps/react-dapp-v2-with-ethers/package.json b/dapps/react-dapp-v2-with-ethers/package.json index 6e30779..cf965ef 100644 --- a/dapps/react-dapp-v2-with-ethers/package.json +++ b/dapps/react-dapp-v2-with-ethers/package.json @@ -28,6 +28,7 @@ "react-error-overlay": "6.0.9" }, "dependencies": { + "@ethereumjs/tx": "^3.5.0", "@walletconnect/client": "2.0.0-beta.23", "@walletconnect/ethereum-provider": "2.0.0-beta.23", "@walletconnect/qrcode-modal": "^1.7.1", diff --git a/dapps/react-dapp-v2-with-ethers/src/App.tsx b/dapps/react-dapp-v2-with-ethers/src/App.tsx index ec27975..9a62877 100644 --- a/dapps/react-dapp-v2-with-ethers/src/App.tsx +++ b/dapps/react-dapp-v2-with-ethers/src/App.tsx @@ -1,6 +1,9 @@ import React, { useState } from "react"; import { version } from "@walletconnect/client/package.json"; import * as encoding from "@walletconnect/encoding"; +import { BigNumber, utils } from "ethers"; +import { TypedDataField } from "@ethersproject/abstract-signer"; +import { Transaction } from "@ethereumjs/tx"; import Banner from "./components/Banner"; import Blockchain from "./components/Blockchain"; @@ -28,8 +31,6 @@ import { SToggleContainer, } from "./components/app"; import { useWalletConnectClient } from "./contexts/ClientContext"; -import { BigNumber, utils } from "ethers"; -import { TypedDataField } from "@ethersproject/abstract-signer"; interface IFormattedRpcResponse { method: string; @@ -130,13 +131,14 @@ export default function App() { const [address] = await web3Provider.listAccounts(); const tx = await formatTestTransaction("eip155:" + chainId + ":" + address); + const signedTx = await web3Provider.send("eth_signTransaction", [tx]); + const valid = Transaction.fromSerializedTx(signedTx as any).verifySignature(); - const signature = await web3Provider.send("eth_signTransaction", [tx]); return { method: "eth_signTransaction", address, - valid: true, - result: signature, + valid, + result: signedTx, }; }; diff --git a/dapps/react-dapp-v2-with-ethers/yarn.lock b/dapps/react-dapp-v2-with-ethers/yarn.lock index dbf38d6..dc6befd 100644 --- a/dapps/react-dapp-v2-with-ethers/yarn.lock +++ b/dapps/react-dapp-v2-with-ethers/yarn.lock @@ -1199,6 +1199,22 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@ethereumjs/common@^2.6.1": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.2.tgz#eb006c9329c75c80f634f340dc1719a5258244df" + integrity sha512-vDwye5v0SVeuDky4MtKsu+ogkH2oFUV8pBKzH/eNBzT8oI91pKa8WyzDuYuxOQsgNgv5R34LfFDh2aaw3H4HbQ== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.4" + +"@ethereumjs/tx@^3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.0.tgz#783b0aeb08518b9991b23f5155763bbaf930a037" + integrity sha512-/+ZNbnJhQhXC83Xuvy6I9k4jT5sXiV0tMR9C+AzSSpcCV64+NB8dTE1m3x98RYMqb8+TLYWA+HML4F5lfXTlJw== + dependencies: + "@ethereumjs/common" "^2.6.1" + ethereumjs-util "^7.1.4" + "@ethersproject/abi@5.5.0", "@ethersproject/abi@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.5.0.tgz#fb52820e22e50b854ff15ce1647cc508d6660613" @@ -4582,6 +4598,14 @@ cosmos-wallet@^1.1.0: "@cosmjs/amino" "^0.25.4" "@cosmjs/proto-signing" "^0.25.4" +crc-32@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.1.tgz#436d2bcaad27bcb6bd073a2587139d3024a16460" + integrity sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w== + dependencies: + exit-on-epipe "~1.0.1" + printj "~1.3.1" + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -5865,7 +5889,7 @@ ethereumjs-util@^6.0.0: ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^7.0.6: +ethereumjs-util@^7.0.6, ethereumjs-util@^7.1.4: version "7.1.4" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz#a6885bcdd92045b06f596c7626c3e89ab3312458" integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A== @@ -5978,6 +6002,11 @@ execa@^4.0.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +exit-on-epipe@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" + integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -10301,6 +10330,11 @@ pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.4.6: ansi-styles "^5.0.0" react-is "^17.0.1" +printj@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/printj/-/printj-1.3.1.tgz#9af6b1d55647a1587ac44f4c1654a4b95b8e12cb" + integrity sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" diff --git a/dapps/react-dapp-v2-with-web3js/package.json b/dapps/react-dapp-v2-with-web3js/package.json index 0913283..aedca9b 100644 --- a/dapps/react-dapp-v2-with-web3js/package.json +++ b/dapps/react-dapp-v2-with-web3js/package.json @@ -28,6 +28,7 @@ "react-error-overlay": "6.0.9" }, "dependencies": { + "@ethereumjs/tx": "^3.5.0", "@walletconnect/client": "2.0.0-beta.23", "@walletconnect/ethereum-provider": "2.0.0-beta.23", "@walletconnect/qrcode-modal": "^1.7.1", diff --git a/dapps/react-dapp-v2-with-web3js/src/App.tsx b/dapps/react-dapp-v2-with-web3js/src/App.tsx index b8a7362..d0cb8ff 100644 --- a/dapps/react-dapp-v2-with-web3js/src/App.tsx +++ b/dapps/react-dapp-v2-with-web3js/src/App.tsx @@ -1,6 +1,9 @@ import React, { useState } from "react"; import { version } from "@walletconnect/client/package.json"; import * as encoding from "@walletconnect/encoding"; +import { utils } from "ethers"; +import { TypedDataField } from "@ethersproject/abstract-signer"; +import { Transaction } from "@ethereumjs/tx"; import Banner from "./components/Banner"; import Blockchain from "./components/Blockchain"; @@ -27,8 +30,6 @@ import { SToggleContainer, } from "./components/app"; import { useWalletConnectClient } from "./contexts/ClientContext"; -import { utils } from "ethers"; -import { TypedDataField } from "@ethersproject/abstract-signer"; interface IFormattedRpcResponse { method: string; @@ -129,13 +130,14 @@ export default function App() { }; // The return signature here is `RLPEncodedTransaction` but it actually returns as string (?). - const result = (await web3Provider.eth.signTransaction(tx)) as unknown as string; + const signedTx = (await web3Provider.eth.signTransaction(tx)) as unknown as string; + const valid = Transaction.fromSerializedTx(signedTx as any).verifySignature(); return { method: "eth_signTransaction", address, - valid: true, - result, + valid, + result: signedTx, }; }; diff --git a/dapps/react-dapp-v2-with-web3js/yarn.lock b/dapps/react-dapp-v2-with-web3js/yarn.lock index a1c6b0d..c6a0492 100644 --- a/dapps/react-dapp-v2-with-web3js/yarn.lock +++ b/dapps/react-dapp-v2-with-web3js/yarn.lock @@ -1207,7 +1207,7 @@ crc-32 "^1.2.0" ethereumjs-util "^7.1.4" -"@ethereumjs/tx@^3.3.2": +"@ethereumjs/tx@^3.3.2", "@ethereumjs/tx@^3.5.0": version "3.5.0" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.0.tgz#783b0aeb08518b9991b23f5155763bbaf930a037" integrity sha512-/+ZNbnJhQhXC83Xuvy6I9k4jT5sXiV0tMR9C+AzSSpcCV64+NB8dTE1m3x98RYMqb8+TLYWA+HML4F5lfXTlJw== diff --git a/dapps/react-dapp-v2/package.json b/dapps/react-dapp-v2/package.json index 9b2d9e8..8bda522 100644 --- a/dapps/react-dapp-v2/package.json +++ b/dapps/react-dapp-v2/package.json @@ -28,6 +28,7 @@ "react-error-overlay": "6.0.9" }, "dependencies": { + "@ethereumjs/tx": "^3.5.0", "@solana/web3.js": "^1.36.0", "@walletconnect/client": "2.0.0-beta.23", "@walletconnect/legacy-modal": "2.0.0-beta.23", diff --git a/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx b/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx index 5977319..aec95a4 100644 --- a/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx +++ b/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx @@ -2,10 +2,17 @@ import { BigNumber, utils } from "ethers"; import { createContext, ReactNode, useContext, useState } from "react"; import * as encoding from "@walletconnect/encoding"; import { TypedDataField } from "@ethersproject/abstract-signer"; +import { Transaction as EthTransaction } from "@ethereumjs/tx"; import { formatDirectSignDoc, stringifySignDocValues } from "cosmos-wallet"; import bs58 from "bs58"; import { verifyMessageSignature } from "solana-wallet"; -import { clusterApiUrl, Connection, Keypair, SystemProgram, Transaction } from "@solana/web3.js"; +import { + clusterApiUrl, + Connection, + Keypair, + SystemProgram, + Transaction as SolanaTransaction, +} from "@solana/web3.js"; import { eip712, formatTestTransaction, getLocalStorageTestnetFlag } from "../helpers"; import { useWalletConnectClient } from "./ClientContext"; @@ -172,7 +179,7 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea const tx = await formatTestTransaction(account); - const result: string = await client!.request({ + const signedTx: string = await client!.request({ topic: session!.topic, chainId, request: { @@ -181,11 +188,13 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea }, }); + const valid = EthTransaction.fromSerializedTx(signedTx as any).verifySignature(); + return { method: DEFAULT_EIP155_METHODS.ETH_SIGN_TRANSACTION, address, - valid: true, - result, + valid, + result: signedTx, }; }), testSignPersonalMessage: _createJsonRpcRequestHandler( @@ -432,7 +441,7 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea // cluster only seems to support `connection.getRecentBlockhash` currently. const { blockhash } = await connection.getRecentBlockhash(); - const transaction = new Transaction({ + const transaction = new SolanaTransaction({ feePayer: senderPublicKey, recentBlockhash: blockhash, }).add( diff --git a/dapps/react-dapp-v2/yarn.lock b/dapps/react-dapp-v2/yarn.lock index b6ffc0b..f7699e6 100644 --- a/dapps/react-dapp-v2/yarn.lock +++ b/dapps/react-dapp-v2/yarn.lock @@ -1206,6 +1206,22 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@ethereumjs/common@^2.6.1": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.2.tgz#eb006c9329c75c80f634f340dc1719a5258244df" + integrity sha512-vDwye5v0SVeuDky4MtKsu+ogkH2oFUV8pBKzH/eNBzT8oI91pKa8WyzDuYuxOQsgNgv5R34LfFDh2aaw3H4HbQ== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.4" + +"@ethereumjs/tx@^3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.0.tgz#783b0aeb08518b9991b23f5155763bbaf930a037" + integrity sha512-/+ZNbnJhQhXC83Xuvy6I9k4jT5sXiV0tMR9C+AzSSpcCV64+NB8dTE1m3x98RYMqb8+TLYWA+HML4F5lfXTlJw== + dependencies: + "@ethereumjs/common" "^2.6.1" + ethereumjs-util "^7.1.4" + "@ethersproject/abi@5.5.0", "@ethersproject/abi@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.5.0.tgz#fb52820e22e50b854ff15ce1647cc508d6660613" @@ -4651,6 +4667,14 @@ cosmos-wallet@^1.1.0: "@cosmjs/amino" "^0.25.4" "@cosmjs/proto-signing" "^0.25.4" +crc-32@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.1.tgz#436d2bcaad27bcb6bd073a2587139d3024a16460" + integrity sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w== + dependencies: + exit-on-epipe "~1.0.1" + printj "~1.3.1" + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -5944,7 +5968,7 @@ ethereumjs-util@^6.0.0: ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^7.0.6: +ethereumjs-util@^7.0.6, ethereumjs-util@^7.1.4: version "7.1.4" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz#a6885bcdd92045b06f596c7626c3e89ab3312458" integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A== @@ -6057,6 +6081,11 @@ execa@^4.0.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +exit-on-epipe@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" + integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -10421,6 +10450,11 @@ pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.4.6: ansi-styles "^5.0.0" react-is "^17.0.1" +printj@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/printj/-/printj-1.3.1.tgz#9af6b1d55647a1587ac44f4c1654a4b95b8e12cb" + integrity sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"