From f88989365be1be2a9e7caec3d17efc547ea8e23e Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Tue, 29 Oct 2024 17:21:33 +0100 Subject: [PATCH] apply patch --- apps/remix-dapp/src/utils/txRunner.ts | 2 +- .../src/commands/hideMetaMaskPopup.ts | 2 +- apps/remix-ide-e2e/src/tests/metamask.test.ts | 188 ++++++++++++++++++ .../remix-ide-e2e/src/tests/providers.test.ts | 123 +++++++++--- .../src/app/providers/abstract-provider.tsx | 38 ++-- apps/remix-ide/src/app/tabs/web3-provider.js | 2 +- apps/remix-ide/src/app/udapp/run-tab.tsx | 57 ++++-- apps/remix-ide/src/blockchain/blockchain.tsx | 10 +- libs/remix-lib/src/execution/txRunnerWeb3.ts | 6 +- .../run-tab/src/lib/actions/deploy.ts | 11 +- 10 files changed, 367 insertions(+), 72 deletions(-) create mode 100644 apps/remix-ide-e2e/src/tests/metamask.test.ts diff --git a/apps/remix-dapp/src/utils/txRunner.ts b/apps/remix-dapp/src/utils/txRunner.ts index 6f22ca6c134..1914302c02e 100644 --- a/apps/remix-dapp/src/utils/txRunner.ts +++ b/apps/remix-dapp/src/utils/txRunner.ts @@ -267,7 +267,7 @@ export class TxRunner { }; } catch (error: any) { console.log( - `Send transaction failed: ${error.message} . if you use an injected provider, please check it is properly unlocked. ` + `Send transaction failed: ${error.message || error.error} . if you use an injected provider, please check it is properly unlocked. ` ); return { error }; } diff --git a/apps/remix-ide-e2e/src/commands/hideMetaMaskPopup.ts b/apps/remix-ide-e2e/src/commands/hideMetaMaskPopup.ts index 234a3a08cd0..16aaa699626 100644 --- a/apps/remix-ide-e2e/src/commands/hideMetaMaskPopup.ts +++ b/apps/remix-ide-e2e/src/commands/hideMetaMaskPopup.ts @@ -5,7 +5,7 @@ class HideMetaMaskPopup extends EventEmitter { command(this: NightwatchBrowser) { browser .pause(5000) - .isVisible({ + .isPresent({ selector: 'button[data-testid="popover-close"]', locateStrategy: 'css selector', suppressNotFoundErrors: true, diff --git a/apps/remix-ide-e2e/src/tests/metamask.test.ts b/apps/remix-ide-e2e/src/tests/metamask.test.ts new file mode 100644 index 00000000000..0051c57d9c5 --- /dev/null +++ b/apps/remix-ide-e2e/src/tests/metamask.test.ts @@ -0,0 +1,188 @@ +'use strict' +import { NightwatchBrowser } from 'nightwatch' +import init from '../helpers/init' + +const passphrase = process.env.account_passphrase +const password = process.env.account_password +const extension_id = 'nkbihfbeogaeaoehlefnkodbefgpgknn' +const extension_url = `chrome-extension://${extension_id}/home.html` + +const checkBrowserIsChrome = function (browser: NightwatchBrowser) { + return browser.browserName.indexOf('chrome') > -1 +} + +const checkAlerts = function (browser: NightwatchBrowser) { + browser.isVisible({ + selector: '//*[contains(.,"not have enough")]', + locateStrategy: 'xpath', + suppressNotFoundErrors: true, + timeout: 3000 + }, (okVisible) => { + if (okVisible.value) { + browser.assert.fail('Not enough ETH in test account!!') + browser.end() + } + }) +} + +const tests = { + '@disabled': true, + before: function (browser: NightwatchBrowser, done: VoidFunction) { + init(browser, done) + }, + + '@sources': function () { + return sources + }, + + 'Should connect to Sepolia Test Network using MetaMask #group1': function (browser: NightwatchBrowser) { + if (!checkBrowserIsChrome(browser)) return + browser.waitForElementPresent('*[data-id="remixIdeSidePanel"]') + .setupMetamask(passphrase, password) + .useCss().switchBrowserTab(0) + .refreshPage() + .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) + .click('*[data-id="landingPageStartSolidity"]') + .clickLaunchIcon('udapp') + .switchEnvironment('injected-MetaMask') + .waitForElementPresent('*[data-id="settingsNetworkEnv"]') + .assert.containsText('*[data-id="settingsNetworkEnv"]', 'Sepolia (11155111) network') + .pause(5000) + .switchBrowserWindow(extension_url, 'MetaMask', (browser) => { + browser + .hideMetaMaskPopup() + .waitForElementVisible('*[data-testid="page-container-footer-next"]', 60000) + .click('*[data-testid="page-container-footer-next"]') // this connects the metamask account to remix + .pause(2000) + .waitForElementVisible('*[data-testid="page-container-footer-next"]', 60000) + .click('*[data-testid="page-container-footer-next"]') + // .waitForElementVisible('*[data-testid="popover-close"]') + // .click('*[data-testid="popover-close"]') + }) + .switchBrowserTab(0) // back to remix + }, + + 'Should add a contract file #group1': function (browser: NightwatchBrowser) { + if (!checkBrowserIsChrome(browser)) return + browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]') + .clickLaunchIcon('filePanel') + .addFile('Greet.sol', sources[0]['Greet.sol']) + .clickLaunchIcon('udapp') + .waitForElementVisible('*[data-id="Deploy - transact (not payable)"]', 45000) // wait for the contract to compile + }, + + 'Should deploy contract on Sepolia Test Network using MetaMask #group1': function (browser: NightwatchBrowser) { + if (!checkBrowserIsChrome(browser)) return + browser.clearConsole().waitForElementPresent('*[data-id="runTabSelectAccount"] option', 45000) + .clickLaunchIcon('filePanel') + .openFile('Greet.sol') + .clickLaunchIcon('udapp') + .waitForElementPresent('*[data-id="Deploy - transact (not payable)"]') + .click('*[data-id="Deploy - transact (not payable)"]') + .pause(5000) + .clearConsole() + .perform((done) => { + browser.switchBrowserWindow(extension_url, 'MetaMask', (browser) => { + checkAlerts(browser) + browser + .maximizeWindow() + .hideMetaMaskPopup() + .waitForElementPresent('[data-testid="page-container-footer-next"]') + .click('[data-testid="page-container-footer-next"]') // approve the tx + .switchBrowserTab(0) // back to remix + .waitForElementContainsText('*[data-id="terminalJournal"]', 'view on etherscan', 60000) + .waitForElementContainsText('*[data-id="terminalJournal"]', 'from: 0x76a...2708f', 60000) + .perform(() => done()) + }) + }) + }, + 'Should deploy faulty contract on Sepolia Test Network using MetaMask and show error in terminal #group1': function (browser: NightwatchBrowser) { + browser + .clearConsole() + .clickLaunchIcon('filePanel') + .addFile('faulty.sol', sources[0]['faulty.sol']) + .clickLaunchIcon('udapp') + .waitForElementPresent('*[data-id="Deploy - transact (not payable)"]') + .click('*[data-id="Deploy - transact (not payable)"]') + .pause(5000) + .saveScreenshot('./reports/screenshots/metamask_7.png') + .waitForElementVisible('*[data-id="udappNotifyModalDialogModalBody-react"]', 60000) + .click('[data-id="udappNotify-modal-footer-cancel-react"]') + .saveScreenshot('./reports/screenshots/metamask_8.png') + .waitForElementVisible({ + locateStrategy: 'xpath', + selector: "//span[@class='text-log' and contains(., 'errored')]" + }) + }, + 'Should deploy contract on Sepolia Test Network using MetaMask again #group1': function (browser: NightwatchBrowser) { + if (!checkBrowserIsChrome(browser)) return + browser.clearConsole().waitForElementPresent('*[data-id="runTabSelectAccount"] option', 45000) + .clickLaunchIcon('filePanel') + .openFile('Greet.sol') + .clickLaunchIcon('udapp') + .waitForElementPresent('*[data-id="Deploy - transact (not payable)"]') + .click('*[data-id="Deploy - transact (not payable)"]') + .pause(5000) + .clearConsole() + .perform((done) => { + browser.switchBrowserWindow(extension_url, 'MetaMask', (browser) => { + checkAlerts(browser) + browser + .maximizeWindow() + .hideMetaMaskPopup() + .waitForElementPresent('[data-testid="page-container-footer-next"]') + .click('[data-testid="page-container-footer-next"]') // approve the tx + .switchBrowserTab(0) // back to remix + .waitForElementContainsText('*[data-id="terminalJournal"]', 'view on etherscan', 60000) + .waitForElementContainsText('*[data-id="terminalJournal"]', 'from: 0x76a...2708f', 60000) + .perform(() => done()) + }) + }) + } +} + +const branch = process.env.CIRCLE_BRANCH; +const isMasterBranch = (branch === 'master' || branch === 'remix_beta'); + +if (!checkBrowserIsChrome(browser)) { + module.exports = {} +} else { + module.exports = { + ...(branch ? (isMasterBranch ? tests : {}) : tests), + }; +} + + + +const sources = [ + { + 'Greet.sol': { + content: + ` + pragma solidity ^0.8.0; + contract HelloWorld { + string public message; + + fallback () external { + message = 'Hello World!'; + } + + function greet(string memory _message) public { + message = _message; + } + }` + }, + 'faulty.sol': { + content: `// SPDX-License-Identifier: GPL-3.0 + + pragma solidity >=0.8.2 <0.9.0; + + contract Test { + error O_o(uint256); + constructor() { + revert O_o(block.timestamp); + } + }` + } + } +] diff --git a/apps/remix-ide-e2e/src/tests/providers.test.ts b/apps/remix-ide-e2e/src/tests/providers.test.ts index 7fb52593e23..862fed757b6 100644 --- a/apps/remix-ide-e2e/src/tests/providers.test.ts +++ b/apps/remix-ide-e2e/src/tests/providers.test.ts @@ -3,54 +3,119 @@ import { NightwatchBrowser } from 'nightwatch' import init from '../helpers/init' module.exports = { + '@disabled': true, before: function (browser: NightwatchBrowser, done: VoidFunction) { init(browser, done, 'http://127.0.0.1:8080', false) }, - 'Should switch to ganache provider, set a custom URL and fail to connect': function (browser: NightwatchBrowser) { + 'Should switch to ganache provider, set a custom URL and fail to connect #group1': function (browser: NightwatchBrowser) { browser.waitForElementVisible('div[data-id="remixIdeIconPanel"]', 10000) .clickLaunchIcon('udapp') .switchEnvironment('ganache-provider') .waitForElementVisible('*[data-id="ganache-providerModalDialogModalBody-react"]') + .execute(() => { (document.querySelector('*[data-id="ganache-providerModalDialogModalBody-react"] input') as any).focus() - }, [], () => {}) + }, [], () => { }) .clearValue('*[data-id="ganache-providerModalDialogModalBody-react"] input') .setValue('*[data-id="ganache-providerModalDialogModalBody-react"] input', 'http://127.0.0.1:8084') .modalFooterOKClick('ganache-provider') - .waitForElementContainsText('*[data-id="ganache-providerModalDialogModalBody-react"]', 'Error while connecting to the provider') - .modalFooterOKClick('ganache-provider') - .waitForElementNotVisible('*[data-id="ganache-providerModalDialogModalBody-react"]') + .waitForElementVisible({ + locateStrategy: 'xpath', + selector: "//span[@class='text-danger' and contains(., 'missing response')]" + }) + .waitForElementPresent({ selector: `[data-id="selected-provider-ganache-provider"]`, timeout: 5000 }) .pause(1000) }, - 'Should switch to ganache provider, use the default ganache URL and succeed to connect': function (browser: NightwatchBrowser) { - browser.switchEnvironment('ganache-provider') - .waitForElementVisible('*[data-id="ganache-providerModalDialogModalBody-react"]') - .modalFooterOKClick('ganache-provider') - .waitForElementContainsText('*[data-id="settingsNetworkEnv"]', 'Custom (') + 'Should switch to ganache provider, use the default ganache URL and succeed to connect #group1': function (browser: NightwatchBrowser) { + browser + .switchEnvironment('vm-cancun') + .pause(2000) + .switchEnvironment('ganache-provider') + .waitForElementVisible('*[data-id="ganache-providerModalDialogModalBody-react"]') + .modalFooterOKClick('ganache-provider') + .waitForElementContainsText('*[data-id="settingsNetworkEnv"]', 'Custom (') + .waitForElementVisible({ selector: `[data-id="selected-provider-ganache-provider"]`, timeout: 5000 }) + }, - 'Should switch to foundry provider, set a custom URL and fail to connect': function (browser: NightwatchBrowser) { + 'Should switch to foundry provider, set a custom URL and fail to connect #group1': function (browser: NightwatchBrowser) { browser.waitForElementVisible('div[data-id="remixIdeIconPanel"]', 10000) - .switchEnvironment('foundry-provider') - .waitForElementVisible('*[data-id="foundry-providerModalDialogModalBody-react"]') - .execute(() => { - (document.querySelector('*[data-id="foundry-providerModalDialogModalBody-react"] input') as any).focus() - }, [], () => {}) - .clearValue('*[data-id="foundry-providerModalDialogModalBody-react"] input') - .setValue('*[data-id="foundry-providerModalDialogModalBody-react"] input', 'http://127.0.0.1:8084') - .modalFooterOKClick('foundry-provider') - .waitForElementContainsText('*[data-id="foundry-providerModalDialogModalBody-react"]', 'Error while connecting to the provider') - .modalFooterOKClick('foundry-provider') - .waitForElementNotVisible('*[data-id="foundry-providerModalDialogModalBody-react"]') - .pause(1000) - -}, - 'Should switch to foundry provider, use the default foundry URL and succeed to connect': function (browser: NightwatchBrowser) { + .switchEnvironment('foundry-provider') + .waitForElementVisible('*[data-id="foundry-providerModalDialogModalBody-react"]') + .execute(() => { + (document.querySelector('*[data-id="foundry-providerModalDialogModalBody-react"] input') as any).focus() + }, [], () => { }) + .clearValue('*[data-id="foundry-providerModalDialogModalBody-react"] input') + .setValue('*[data-id="foundry-providerModalDialogModalBody-react"] input', 'http://127.0.0.1:8084') + .modalFooterOKClick('foundry-provider') + .pause(1000) + + }, + 'Should switch to foundry provider, use the default foundry URL and succeed to connect #group1': !function (browser: NightwatchBrowser) { browser.switchEnvironment('foundry-provider') - .waitForElementVisible('*[data-id="foundry-providerModalDialogModalBody-react"]') - .modalFooterOKClick('foundry-provider') - .waitForElementContainsText('*[data-id="settingsNetworkEnv"]', 'Custom (') + .waitForElementVisible('*[data-id="foundry-providerModalDialogModalBody-react"]') + .modalFooterOKClick('foundry-provider') + .waitForElementContainsText('*[data-id="settingsNetworkEnv"]', 'Custom (') + }, + + 'Should switch to custom provider #group2': function (browser: NightwatchBrowser) { + browser.waitForElementVisible('div[data-id="remixIdeIconPanel"]', 10000) + .clickLaunchIcon('udapp') + .switchEnvironment('ganache-provider') + .waitForElementVisible('*[data-id="ganache-providerModalDialogModalBody-react"]') + + .execute(() => { + (document.querySelector('*[data-id="ganache-providerModalDialogModalBody-react"] input') as any).focus() + }, [], () => { }) + .clearValue('*[data-id="ganache-providerModalDialogModalBody-react"] input') + .setValue('*[data-id="ganache-providerModalDialogModalBody-react"] input', 'https://scroll-rpc.publicnode.com') + .modalFooterOKClick('ganache-provider') + .pause(100) + .waitForElementPresent({ selector: `[data-id="selected-provider-ganache-provider"]`, timeout: 5000 }) + .pause(1000) + }, + + 'execute script #group2': function (browser: NightwatchBrowser) { + browser.clickLaunchIcon('filePanel') + .addFile('testScript.ts', { content: testScript }) + .clearConsole() + .pause(10000) + .waitForElementVisible('*[data-id="play-editor"]') + .click('*[data-id="play-editor"]') + .waitForElementVisible({ + locateStrategy: 'xpath', + selector: "//span[@class='text-danger' and contains(., 'exceed maximum block range')]" + }) + .waitForElementPresent({ selector: `[data-id="selected-provider-ganache-provider"]`, timeout: 5000 }) } } + + +const testScript = ` +// Importing necessary libraries from Ethers.js for interaction with Ethereum blockchain. +import { ethers } from "hardhat"; + +// https://scroll-rpc.publicnode.com +async function main() { + // Setting up provider (RPC URL) to interact with your chosen Ethereum chain, + const [deployer] = await ethers.getSigners(); + + try{ + let provider; + if(!provider){ + provider=ethers.provider; + } + + const contractAddress = "0x2bC16Bf30435fd9B3A3E73Eb759176C77c28308D"; // Replace with your smart contract's address. + + // Retrieving all events of a specific kind from the blockchain + let logs = await provider.getLogs({address:contractAddress, fromBlock: '0x332f23',toBlock: '0x384410', topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef']}); + console.log("Got Logs ",logs) + }catch(error){ + } + +} + +main()` \ No newline at end of file diff --git a/apps/remix-ide/src/app/providers/abstract-provider.tsx b/apps/remix-ide/src/app/providers/abstract-provider.tsx index b00efc3d0a5..6c0d8662658 100644 --- a/apps/remix-ide/src/app/providers/abstract-provider.tsx +++ b/apps/remix-ide/src/app/providers/abstract-provider.tsx @@ -26,8 +26,8 @@ export type RejectRequest = (error: JsonDataResult) => void export type SuccessRequest = (data: JsonDataResult) => void export interface IProvider { - options: {[id: string]: any} - init(): Promise<{[id: string]: any}> + options: { [id: string]: any } + init(): Promise<{ [id: string]: any }> body(): JSX.Element sendAsync(data: JsonDataRequest): Promise } @@ -38,7 +38,7 @@ export abstract class AbstractProvider extends Plugin implements IProvider { defaultUrl: string connected: boolean nodeUrl: string - options: {[id: string]: any} = {} + options: { [id: string]: any } = {} constructor(profile, blockchain, defaultUrl) { super(profile) @@ -102,24 +102,16 @@ export abstract class AbstractProvider extends Plugin implements IProvider { sendAsync(data: JsonDataRequest): Promise { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { - if (!this.provider) return reject({ jsonrpc: '2.0', id: data.id, error: { message: 'provider node set', code: -32603 } } as JsonDataResult) + if (!this.provider) return reject({ jsonrpc: '2.0', id: data.id, error: { message: 'provider not set', code: -32603 } } as JsonDataResult) this.sendAsyncInternal(data, resolve, reject) }) } - private async switchAway(showError) { + private async switchAway(showError: boolean, msg: string) { if (!this.provider) return - this.provider = null - this.connected = false if (showError) { - const modalContent: AlertModal = { - id: this.profile.name, - title: this.profile.displayName, - message: `Error while connecting to the provider, provider not connected` - } - this.call('notification', 'alert', modalContent) + this.call('terminal', 'log', { type: 'error', value: 'Error while querying the provider: ' + msg }) } - await this.call('udapp', 'setEnvironmentMode', { context: 'vm-cancun' }) return } @@ -130,10 +122,22 @@ export abstract class AbstractProvider extends Plugin implements IProvider { resolve({ jsonrpc: '2.0', result, id: data.id }) } catch (error) { if (error && error.message && error.message.includes('SERVER_ERROR')) { - this.switchAway(true) + try { + // replace escaped quotes with normal quotes + const errorString = String(error.message).replace(/\\"/g, '"'); + const messageMatches = Array.from(errorString.matchAll(/"message":"(.*?)"/g)); + // Extract the message values + const messages = messageMatches.map(match => match[1]); + if (messages && messages.length > 0) { + this.switchAway(true, messages[0]) + } else { + this.switchAway(true, error.message ? error.message : error.error ? error.error : error) + } + } catch (error) { + this.switchAway(true, error.message ? error.message : error.error ? error.error : error) + } } - error.code = -32603 - reject({ jsonrpc: '2.0', error, id: data.id }) + reject({ jsonrpc: '2.0', error: { message: error.message, code: -32603 }, id: data.id }) } } else { const result = data.method === 'net_listening' ? 'canceled' : [] diff --git a/apps/remix-ide/src/app/tabs/web3-provider.js b/apps/remix-ide/src/app/tabs/web3-provider.js index 41bd9d3c27b..39e5543c2e6 100644 --- a/apps/remix-ide/src/app/tabs/web3-provider.js +++ b/apps/remix-ide/src/app/tabs/web3-provider.js @@ -86,7 +86,7 @@ export class Web3ProviderModule extends Plugin { try { resultFn(null, await provider.sendAsync(payload)) } catch (e) { - resultFn(e.error ? new Error(e.error) : new Error(e)) + resultFn(e.error ? e.error : e) } } else { reject(new Error('User denied permission')) diff --git a/apps/remix-ide/src/app/udapp/run-tab.tsx b/apps/remix-ide/src/app/udapp/run-tab.tsx index b513a76c2ee..983629cb817 100644 --- a/apps/remix-ide/src/app/udapp/run-tab.tsx +++ b/apps/remix-ide/src/app/udapp/run-tab.tsx @@ -194,22 +194,7 @@ export class RunTab extends ViewPlugin { if (options['fork']) this.fork = options['fork'] } }, - provider: { - sendAsync (payload) { - return udapp.call(name, 'sendAsync', payload) - }, - async request (payload) { - try { - const requestResult = await udapp.call(name, 'sendAsync', payload) - if (requestResult.error) { - throw new Error(requestResult.error.message) - } - return requestResult.result - } catch (err) { - throw new Error(err.message) - } - } - } + provider: new Provider(udapp, name) }) } @@ -302,3 +287,43 @@ export class RunTab extends ViewPlugin { this.addInstance(address, contractObject.abi, contractObject.name) } } + +class Provider { + udapp: RunTab + name: string + constructor(udapp, name) { + this.udapp = udapp + this.name = name + } + sendAsync (payload) { + return this.udapp.call(this.name, 'sendAsync', payload) + } + request (payload): Promise { + return new Promise((resolve, reject) => { + this.udapp.call(this.name, 'sendAsync', payload).then((response) => { + if (response.error) { + reject(response.error.message) + } else { + resolve(response) + } + }).catch((err) => { + if (typeof err === 'string') { + reject(err) + } else if (err.error && err.error.message) { + reject(err.error.message) + } else if (err.error && typeof err.error === 'string') { + reject(err.error) + } else { + let e + try { + e = JSON.stringify(err) + } catch (e) { + reject('unknown error') + return + } + reject(e) + } + }) + }) + } +} diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index 3690b3c122d..6ccbaed7aca 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -247,7 +247,7 @@ export class Blockchain extends Plugin { args, (error, data) => { if (error) { - return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`) + return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error.error ? error.error : error}`) } statusCb(`creation of ${selectedContract.name} pending...`) @@ -272,7 +272,7 @@ export class Blockchain extends Plugin { selectedContract.bytecodeLinkReferences, (error, data) => { if (error) { - return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`) + return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error.error ? error.error : error}`) } statusCb(`creation of ${selectedContract.name} pending...`) @@ -485,7 +485,7 @@ export class Blockchain extends Plugin { this.runTx({ data: data, useCall: false }, confirmationCb, continueCb, promptCb, (error, txResult, address) => { if (error) { - return finalCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`) + return finalCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error.error ? error.error : error}`) } if (txResult.receipt.status === false || txResult.receipt.status === '0x0' || txResult.receipt.status === 0) { return finalCb(`creation of ${selectedContract.name} errored: transaction execution failed`) @@ -614,7 +614,7 @@ export class Blockchain extends Plugin { callType, (error, data) => { if (error) { - return logCallback(`${logMsg} errored: ${error.message ? error.message : error}`) + return logCallback(`${logMsg} errored: ${error.message ? error.message : error.error ? error.error : error}`) } if (!lookupOnly) { logCallback(`${logMsg} pending ... `) @@ -631,7 +631,7 @@ export class Blockchain extends Plugin { const useCall = funABI.stateMutability === 'view' || funABI.stateMutability === 'pure' this.runTx({ to: address, data, useCall }, confirmationCb, continueCb, promptCb, (error, txResult, _address, returnValue) => { if (error) { - return logCallback(`${logMsg} errored: ${error.message ? error.message : error}`) + return logCallback(`${logMsg} errored: ${error.message ? error.message : error.error ? error.error : error}`) } if (lookupOnly) { outputCb(returnValue) diff --git a/libs/remix-lib/src/execution/txRunnerWeb3.ts b/libs/remix-lib/src/execution/txRunnerWeb3.ts index 0cdb0ee9783..b2c46feff45 100644 --- a/libs/remix-lib/src/execution/txRunnerWeb3.ts +++ b/libs/remix-lib/src/execution/txRunnerWeb3.ts @@ -66,7 +66,7 @@ export class TxRunnerWeb3 { const res = await (this.getWeb3() as any).eth.personal.sendTransaction({ ...tx, value }, { checkRevertBeforeSending: false, ignoreGasPricing: true }) cb(null, res.transactionHash) } catch (e) { - console.log(`Send transaction failed: ${e.message} . if you use an injected provider, please check it is properly unlocked. `) + console.log(`Send transaction failed: ${e.message || e.error} . if you use an injected provider, please check it is properly unlocked. `) // in case the receipt is available, we consider that only the execution failed but the transaction went through. // So we don't consider this to be an error. if (e.receipt) cb(null, e.receipt.transactionHash) @@ -82,6 +82,10 @@ export class TxRunnerWeb3 { const res = await this.getWeb3().eth.sendTransaction(tx, null, { checkRevertBeforeSending: false, ignoreGasPricing: true }) cb(null, res.transactionHash) } catch (e) { + if (!e.message) e.message = '' + if (e.error) { + e.message = e.message + ' ' + e.error + } console.log(`Send transaction failed: ${e.message} . if you use an injected provider, please check it is properly unlocked. `) // in case the receipt is available, we consider that only the execution failed but the transaction went through. // So we don't consider this to be an error. diff --git a/libs/remix-ui/run-tab/src/lib/actions/deploy.ts b/libs/remix-ui/run-tab/src/lib/actions/deploy.ts index dd08d62a363..2c2ee360c49 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/deploy.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/deploy.ts @@ -119,10 +119,19 @@ const getConfirmationCb = (plugin: RunTab, dispatch: React.Dispatch, confir export const continueHandler = (dispatch: React.Dispatch, gasEstimationPrompt: (msg: string) => JSX.Element, error, continueTxExecution, cancelCb) => { if (error) { - let msg = typeof error !== 'string' ? error.message : error + let msg = '' + if (typeof error === 'string') { + msg = error + } if (error && error.innerError) { msg += '\n' + error.innerError } + if (error && error.message) { + msg += '\n' + error.message + } + if (error && error.error) { + msg += '\n' + error.error + } if (msg.includes('invalid opcode')) msg += '\nThe EVM version used by the selected environment is not compatible with the compiler EVM version.'