diff --git a/apps/debugger/src/app/debugger.ts b/apps/debugger/src/app/debugger.ts index c2c138e7e6c..d9856a69055 100644 --- a/apps/debugger/src/app/debugger.ts +++ b/apps/debugger/src/app/debugger.ts @@ -23,7 +23,7 @@ export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) { fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise getFile: (path: string) => Promise setFile: (path: string, content: string) => Promise - getDebugWeb3: () => any // returns an instance of web3.js, if applicable (mainet, goerli, ...) it returns a reference to a node from devops (so we are sure debug endpoint is available) + getDebugProvider: () => any // returns an instance of web3.js, if applicable (mainnet, goerli, ...) it returns a reference to a node from devops (so we are sure debug endpoint is available) web3: () => any // returns an instance of web3.js onStartDebugging: (debuggerBackend: any) => void // called when debug starts onStopDebugging: () => void // called when debug stops diff --git a/apps/remix-dapp/src/actions/index.ts b/apps/remix-dapp/src/actions/index.ts index f559f72aa17..7cd2b3bcdae 100644 --- a/apps/remix-dapp/src/actions/index.ts +++ b/apps/remix-dapp/src/actions/index.ts @@ -1,6 +1,5 @@ import axios from 'axios'; -import Web3 from 'web3'; -import { AbiCoder } from 'ethers'; +import { AbiCoder, parseUnits } from 'ethers'; import BN from 'bn.js'; import { execution } from '@remix-project/remix-lib'; import { toBytes, addHexPrefix } from '@ethereumjs/util'; @@ -126,7 +125,7 @@ export const runTransactions = async (payload: any) => { console.log(payload); const { sendValue, sendUnit, gasLimit, selectedAccount } = state.settings; const { address, decodedResponse, name } = state.instance; - const value = Web3.utils.toWei(sendValue, sendUnit); + const value = parseUnits(sendValue, sendUnit); const tx = { to: address, diff --git a/apps/remix-dapp/src/utils/txRunner.ts b/apps/remix-dapp/src/utils/txRunner.ts index 358b2ef5a6c..98eafadac47 100644 --- a/apps/remix-dapp/src/utils/txRunner.ts +++ b/apps/remix-dapp/src/utils/txRunner.ts @@ -1,16 +1,9 @@ -import Web3, { - FMT_NUMBER, - type EthExecutionAPI, - type SupportedProviders, - FMT_BYTES, - type Bytes, -} from 'web3'; import { addHexPrefix, toBytes } from '@ethereumjs/util'; import { execution } from '@remix-project/remix-lib'; -import { toBigInt } from 'web3-utils'; import { saveSettings } from '../actions'; +import { BrowserProvider, ethers, formatUnits, toNumber, TransactionReceipt, TransactionResponse } from 'ethers' -const web3 = new Web3(); +const provider = ethers.getDefaultProvider() export const shortenAddress = (address: string, etherBalance?: string) => { const len = address.length; @@ -29,12 +22,9 @@ async function pause() { }); } -async function tryTillReceiptAvailable(txhash: Bytes) { +async function tryTillReceiptAvailable(txhash) { try { - const receipt = await web3.eth.getTransactionReceipt(txhash, { - number: FMT_NUMBER.NUMBER, - bytes: FMT_BYTES.HEX, - }); + const receipt: TransactionReceipt = await provider.getTransactionReceipt(txhash); if (receipt) { if (!receipt.to && !receipt.contractAddress) { // this is a contract creation and the receipt doesn't contain a contract address. we have to keep polling... @@ -52,12 +42,9 @@ async function tryTillReceiptAvailable(txhash: Bytes) { return await tryTillReceiptAvailable(txhash); } -async function tryTillTxAvailable(txhash: Bytes) { +async function tryTillTxAvailable(txhash) { try { - const tx = await web3.eth.getTransaction(txhash, { - number: FMT_NUMBER.NUMBER, - bytes: FMT_BYTES.HEX, - }); + const tx: TransactionResponse = await provider.getTransaction(txhash, ); if (tx?.blockHash) return tx; return tx; } catch (e) { @@ -90,16 +77,13 @@ export class TxRunner { }, 30000); } - setProvider( - provider: string | SupportedProviders | undefined - ) { - web3.setProvider(provider); + setProvider(provider) { + new ethers.BrowserProvider(provider) } getAccounts() { saveSettings({ isRequesting: true }); - void web3.eth - .getAccounts() + (provider as any).send("eth_requestAccounts", []) .then(async (accounts) => { const loadedAccounts: any = {}; for (const account of accounts) { @@ -115,17 +99,18 @@ export class TxRunner { } async getBalanceInEther(address: string) { - const balance = await web3.eth.getBalance(address); - return Web3.utils.fromWei(balance.toString(10), 'ether'); + const balance = await provider.getBalance(address); + return formatUnits(balance.toString(10), 'ether'); } async getGasPrice() { - return await web3.eth.getGasPrice(); + const { gasPrice } = await provider.getFeeData() + return gasPrice; } async runTx(tx: any, gasLimit: any, useCall: boolean) { if (useCall) { - const returnValue = await web3.eth.call({ ...tx, gas: gasLimit }); + const returnValue = await provider.call({ ...tx, gasLimit }); return toBytes(addHexPrefix(returnValue)); } @@ -147,8 +132,8 @@ export class TxRunner { txCopy.maxFeePerGas = Math.ceil( Number( ( - toBigInt(network.lastBlock.baseFeePerGas) + - toBigInt(network.lastBlock.baseFeePerGas) / BigInt(3) + BigInt(network.lastBlock.baseFeePerGas) + + BigInt(network.lastBlock.baseFeePerGas) / BigInt(3) ).toString() ) ); @@ -159,8 +144,8 @@ export class TxRunner { } try { - const gasEstimation = await web3.eth.estimateGas(txCopy); - tx.gas = !gasEstimation ? gasLimit : gasEstimation; + const gasEstimation = await provider.estimateGas(txCopy); + tx.gasLimit = !gasEstimation ? gasLimit : gasEstimation; return await this._executeTx(tx, network); } catch (error) { console.log(error); @@ -169,7 +154,8 @@ export class TxRunner { } async detectNetwork() { - const id = Number(await web3.eth.net.getId()); + const { chainId} = await provider.getNetwork() + const id = Number(chainId) let name = ''; if (id === 1) name = 'Main'; else if (id === 3) name = 'Ropsten'; @@ -180,7 +166,7 @@ export class TxRunner { else name = 'Custom'; if (id === 1) { - const block = await web3.eth.getBlock(0); + const block = await provider.getBlock(0); if (block && block.hash !== this.mainNetGenesisHash) name = 'Custom'; return { id, @@ -205,18 +191,18 @@ export class TxRunner { async _updateChainContext() { try { - const block = await web3.eth.getBlock('latest'); + const block = await provider.getBlock('latest'); // we can't use the blockGasLimit cause the next blocks could have a lower limit : https://github.com/ethereum/remix/issues/506 this.blockGasLimit = block?.gasLimit ? Math.floor( - Number(web3.utils.toNumber(block.gasLimit)) - - (5 * Number(web3.utils.toNumber(block.gasLimit))) / 1024 + Number(toNumber(block.gasLimit)) - + (5 * Number(toNumber(block.gasLimit))) / 1024 ) - : web3.utils.toNumber(this.blockGasLimitDefault); + : toNumber(this.blockGasLimitDefault); this.lastBlock = block; try { this.currentFork = execution.forkAt( - await web3.eth.net.getId(), + (await provider.getNetwork()).chainId, block.number ); } catch (e) { @@ -247,19 +233,16 @@ export class TxRunner { let currentDateTime = new Date(); try { - const { transactionHash } = await web3.eth.sendTransaction( - tx, - undefined, - { checkRevertBeforeSending: false, ignoreGasPricing: true } - ); - const receipt = await tryTillReceiptAvailable(transactionHash); - tx = await tryTillTxAvailable(transactionHash); + const signer = await (provider as BrowserProvider).getSigner(); + const { hash } = await signer.sendTransaction(tx); + const receipt = await tryTillReceiptAvailable(hash); + tx = await tryTillTxAvailable(hash); currentDateTime = new Date(); return { receipt, tx, - transactionHash: receipt ? receipt.transactionHash : null, + transactionHash: receipt ? receipt.hash : null, }; } catch (error: any) { console.log( diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index 5727eb14018..ac8323fb447 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -34,7 +34,7 @@ module.exports = { .clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } }) }, @@ -87,7 +87,7 @@ module.exports = { .clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' }) .testFunction('last', { - status: '0x0 Transaction mined but execution failed', + status: '0 Transaction mined but execution failed', 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } }) }, diff --git a/apps/remix-ide-e2e/src/tests/ballot_0_4_14.test.ts b/apps/remix-ide-e2e/src/tests/ballot_0_4_14.test.ts index 6d654629b67..24184ed7095 100644 --- a/apps/remix-ide-e2e/src/tests/ballot_0_4_14.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot_0_4_14.test.ts @@ -43,7 +43,7 @@ module.exports = { .clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } }) }, @@ -82,7 +82,7 @@ module.exports = { .clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } }) }, diff --git a/apps/remix-ide-e2e/src/tests/compile_run_widget.test.ts b/apps/remix-ide-e2e/src/tests/compile_run_widget.test.ts index f9496639fbd..1d0acdc972d 100644 --- a/apps/remix-ide-e2e/src/tests/compile_run_widget.test.ts +++ b/apps/remix-ide-e2e/src/tests/compile_run_widget.test.ts @@ -22,7 +22,7 @@ module.exports = { 'Run script using the widget #group2': function (browser: NightwatchBrowser) { browser - .openFile('scripts/deploy_with_web3.ts') + .openFile('scripts/deploy_with_ethers.ts') .click('[data-id="compile-action"]') .waitForElementVisible('[data-id="compile_group"] i.fa-check', 10000) }, diff --git a/apps/remix-ide-e2e/src/tests/eip1153.test.ts b/apps/remix-ide-e2e/src/tests/eip1153.test.ts index 89bf3a8f37c..1f1eeb9849a 100644 --- a/apps/remix-ide-e2e/src/tests/eip1153.test.ts +++ b/apps/remix-ide-e2e/src/tests/eip1153.test.ts @@ -25,7 +25,7 @@ module.exports = { .clickFunction('useTransientStorage - transact (not payable)') .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { 0: 'uint256: out1 14', 1: 'uint256: out2 15' diff --git a/apps/remix-ide-e2e/src/tests/erc721.test.ts b/apps/remix-ide-e2e/src/tests/erc721.test.ts index 917d38283b1..9f24075bb6d 100644 --- a/apps/remix-ide-e2e/src/tests/erc721.test.ts +++ b/apps/remix-ide-e2e/src/tests/erc721.test.ts @@ -42,7 +42,7 @@ module.exports = { .createContract('') .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': {} }).end() } diff --git a/apps/remix-ide-e2e/src/tests/metamask.test.ts b/apps/remix-ide-e2e/src/tests/metamask.test.ts index a0692b37931..ad9ca520bdf 100644 --- a/apps/remix-ide-e2e/src/tests/metamask.test.ts +++ b/apps/remix-ide-e2e/src/tests/metamask.test.ts @@ -207,7 +207,7 @@ const tests = { .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } }) }, diff --git a/apps/remix-ide-e2e/src/tests/pinned_contracts.test.ts b/apps/remix-ide-e2e/src/tests/pinned_contracts.test.ts index f014d05d687..aca6c2f6797 100644 --- a/apps/remix-ide-e2e/src/tests/pinned_contracts.test.ts +++ b/apps/remix-ide-e2e/src/tests/pinned_contracts.test.ts @@ -78,7 +78,7 @@ module.exports = { .clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '35' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { "uint256 num": "35" } }) .clickFunction('retrieve - call') @@ -102,7 +102,7 @@ module.exports = { .clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '55' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { "uint256 num": "55" } }) .clickFunction('retrieve - call') diff --git a/apps/remix-ide-e2e/src/tests/plugin_api.ts b/apps/remix-ide-e2e/src/tests/plugin_api.ts index 6192a42d28e..8f2267fe3b5 100644 --- a/apps/remix-ide-e2e/src/tests/plugin_api.ts +++ b/apps/remix-ide-e2e/src/tests/plugin_api.ts @@ -330,14 +330,14 @@ module.exports = { // DGIT 'Should have changes on new workspace #group3': async function (browser: NightwatchBrowser) { await clickAndCheckLog(browser, 'filePanel-createWorkspace', null, null, 'dgit') - await clickAndCheckLog(browser, 'dgitApi-status', [[".prettierrc.json",0,2,0], ["README.txt",0,2,0],["contracts/1_Storage.sol",0,2,0],["contracts/2_Owner.sol",0,2,0],["contracts/3_Ballot.sol",0,2,0],["remix.config.json",0,2,0],["scripts/deploy_with_ethers.ts",0,2,0],["scripts/deploy_with_web3.ts",0,2,0],["scripts/ethers-lib.ts",0,2,0],["scripts/web3-lib.ts",0,2,0],["tests/Ballot_test.sol",0,2,0],["tests/storage.test.js",0,2,0]], null, null) + await clickAndCheckLog(browser, 'dgitApi-status', [[".prettierrc.json",0,2,0], ["README.txt",0,2,0],["contracts/1_Storage.sol",0,2,0],["contracts/2_Owner.sol",0,2,0],["contracts/3_Ballot.sol",0,2,0],["remix.config.json",0,2,0],["scripts/deploy_with_ethers.ts",0,2,0],["scripts/ethers-lib.ts",0,2,0],["tests/Ballot_test.sol",0,2,0],["tests/storage.test.js",0,2,0]], null, null) }, 'Should stage contract #group3': async function (browser: NightwatchBrowser) { await clickAndCheckLog(browser, 'dgitApi-add', null, null, { filepath: 'contracts/1_Storage.sol' }) - await clickAndCheckLog(browser, 'dgitApi-status', [[".prettierrc.json",0,2,0],["README.txt",0,2,0],["contracts/1_Storage.sol",0,2,2],["contracts/2_Owner.sol",0,2,0],["contracts/3_Ballot.sol",0,2,0],["remix.config.json",0,2,0],["scripts/deploy_with_ethers.ts",0,2,0],["scripts/deploy_with_web3.ts",0,2,0],["scripts/ethers-lib.ts",0,2,0],["scripts/web3-lib.ts",0,2,0],["tests/Ballot_test.sol",0,2,0],["tests/storage.test.js",0,2,0]], null, null) + await clickAndCheckLog(browser, 'dgitApi-status', [[".prettierrc.json",0,2,0],["README.txt",0,2,0],["contracts/1_Storage.sol",0,2,2],["contracts/2_Owner.sol",0,2,0],["contracts/3_Ballot.sol",0,2,0],["remix.config.json",0,2,0],["scripts/deploy_with_ethers.ts",0,2,0],["scripts/ethers-lib.ts",0,2,0],["tests/Ballot_test.sol",0,2,0],["tests/storage.test.js",0,2,0]], null, null) }, 'Should commit changes #group3': async function (browser: NightwatchBrowser) { await clickAndCheckLog(browser, 'dgitApi-commit', null, null, { author: { name: 'Remix', email: 'Remix' }, message: 'commit-message' }) diff --git a/apps/remix-ide-e2e/src/tests/recorder.test.ts b/apps/remix-ide-e2e/src/tests/recorder.test.ts index 0d7b038b26d..c15a43b600a 100644 --- a/apps/remix-ide-e2e/src/tests/recorder.test.ts +++ b/apps/remix-ide-e2e/src/tests/recorder.test.ts @@ -96,7 +96,7 @@ module.exports = { .pause(1000) .clickFunction('set2 - transact (not payable)', { types: 'uint256 _po', values: '10' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { 'uint256 _po': '10' } }) }, diff --git a/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts b/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts index 84878d5a734..7b415292d9a 100644 --- a/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts +++ b/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts @@ -57,7 +57,7 @@ module.exports = { .click('*[data-id="Deploy - transact (not payable)"]') .pause(5000) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed' + status: '1 Transaction mined and execution succeed' }) }, @@ -102,7 +102,7 @@ module.exports = { .click('*[data-id="pluginManagerSettingsDeployAndRunLLTxSendTransaction"]') .pause(5000) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed' + status: '1 Transaction mined and execution succeed' }) // When this is removed and tests are running by connecting to metamask // Consider adding tests to check return value of contract call @@ -153,7 +153,7 @@ module.exports = { .waitForElementContainsText('[data-id="treeViewLi0"]', 'uint256: 10') }, - 'Should save state after running web3 script #group4': function (browser: NightwatchBrowser) { + 'Should save state after running ethers script #group4': function (browser: NightwatchBrowser) { browser .waitForElementVisible('*[data-id="topbar-settingsIcon"]') .click('*[data-id="topbar-settingsIcon"]') @@ -168,8 +168,8 @@ module.exports = { .clickLaunchIcon('filePanel') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') .click('*[data-id="treeViewLitreeViewItemscripts"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - .openFile('scripts/deploy_with_web3.ts') + .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') + .openFile('scripts/deploy_with_ethers.ts') .click('[data-id="compile-action"]') .waitForElementContainsText('*[data-id="terminalJournal"]', 'address:') .openFile('.states/vm-london/state.json') diff --git a/apps/remix-ide-e2e/src/tests/templates.test.ts b/apps/remix-ide-e2e/src/tests/templates.test.ts index 952e45d5fc5..5b6c13eb237 100644 --- a/apps/remix-ide-e2e/src/tests/templates.test.ts +++ b/apps/remix-ide-e2e/src/tests/templates.test.ts @@ -9,7 +9,7 @@ const templatesToCheck = [ displayName: "Basic", checkSelectors: [ '*[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]', - '*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]' + '*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]' ] }, { diff --git a/apps/remix-ide-e2e/src/tests/transactionExecution.test.ts b/apps/remix-ide-e2e/src/tests/transactionExecution.test.ts index 730839f3b31..52138672175 100644 --- a/apps/remix-ide-e2e/src/tests/transactionExecution.test.ts +++ b/apps/remix-ide-e2e/src/tests/transactionExecution.test.ts @@ -25,13 +25,13 @@ module.exports = { .clickFunction('f - transact (not payable)') .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { 0: 'uint256: 8' } }) .clickFunction('g - transact (not payable)') .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { 0: 'uint256: 345', 1: 'string: comment_comment_', @@ -50,7 +50,7 @@ module.exports = { .clickFunction('returnValues1 - transact (not payable)') .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { 0: 'bool: _b true', 1: 'uint256: _u 345', @@ -61,7 +61,7 @@ module.exports = { .clickFunction('returnValues2 - transact (not payable)') .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { 0: 'bytes1: _b 0x12', 1: 'bytes2: _b2 0x1223', @@ -78,7 +78,7 @@ module.exports = { .clickFunction('returnValues3 - transact (not payable)') .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { 0: 'uint8: _en 2', 1: 'int256[5][]: _a1 1,-45,-78,56,60,-1,42,334,-45455,-446,1,10,-5435,45,-7' @@ -94,7 +94,7 @@ module.exports = { .clickFunction('inputValue1 - transact (not payable)', { types: 'uint256 _u, int256 _i, string _str', values: '"2343242", "-4324324", "string _ string _ string _ string _ string _ string _ string _ string _ string _ string _"' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { 0: 'uint256: _uret 2343242', 1: 'int256: _iret -4324324', @@ -104,7 +104,7 @@ module.exports = { .pause(500) .clickFunction('inputValue2 - transact (not payable)', { types: 'uint256[3] _n, bytes8[4] _b8', values: '[1,2,3], ["0x1234000000000000", "0x1234000000000000","0x1234000000000000","0x1234000000000000"]' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { 0: 'uint256[3]: _nret 1,2,3', 1: 'bytes8[4]: _b8ret 0x1234000000000000,0x1234000000000000,0x1234000000000000,0x1234000000000000' @@ -237,7 +237,7 @@ module.exports = { .clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '24' }) .testFunction('last', // we check if the contract is actually reachable. { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { 'uint256 num': '24' } @@ -369,7 +369,7 @@ module.exports = { .perform((done) => { browser.testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { '0':'bool: true' } }).perform(() => done()) }) @@ -378,7 +378,7 @@ module.exports = { .perform((done) => { browser.testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { '0':'bool: true' } }).perform(() => done()) }) @@ -387,7 +387,7 @@ module.exports = { .perform((done) => { browser.testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { '0':'bool: true' } }).perform(() => done()) }) @@ -419,7 +419,7 @@ module.exports = { .perform((done) => { browser.testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { '0':'bool: true' } }).perform(() => done()) }) @@ -428,7 +428,7 @@ module.exports = { .perform((done) => { browser.testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { '0':'bool: true' } }).perform(() => done()) }) @@ -452,7 +452,7 @@ module.exports = { .perform((done) => { browser.testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { '0':'bool: true' } }).perform(() => done()) }) @@ -461,7 +461,7 @@ module.exports = { .perform((done) => { browser.testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { '0':'bool: true' } }).perform(() => done()) }) @@ -475,7 +475,7 @@ module.exports = { .perform((done) => { browser.testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { '0':'bool: true' } }).perform(() => done()) }) @@ -487,7 +487,7 @@ module.exports = { .perform((done) => { browser.testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded output': { '0':'bool: true' } }).perform(() => done()) }) diff --git a/apps/remix-ide-e2e/src/tests/txListener.test.ts b/apps/remix-ide-e2e/src/tests/txListener.test.ts index 2bc0b6e391a..4de76e90ad1 100644 --- a/apps/remix-ide-e2e/src/tests/txListener.test.ts +++ b/apps/remix-ide-e2e/src/tests/txListener.test.ts @@ -31,7 +31,7 @@ module.exports = { .clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } }) .clickLaunchIcon('solidity') @@ -40,7 +40,7 @@ module.exports = { .clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' }) .testFunction('last', { - status: '0x0 Transaction mined but execution failed', + status: '0 Transaction mined but execution failed', 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } }) .end() diff --git a/apps/remix-ide-e2e/src/tests/vm_state.test.ts b/apps/remix-ide-e2e/src/tests/vm_state.test.ts index 9eda86e07fb..ad9cbca4a17 100644 --- a/apps/remix-ide-e2e/src/tests/vm_state.test.ts +++ b/apps/remix-ide-e2e/src/tests/vm_state.test.ts @@ -57,7 +57,7 @@ const tests = { .clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '"55"' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { 'uint256 num': '55' } }) .clickFunction('retrieve - call') @@ -114,7 +114,7 @@ const tests = { .clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '"57"' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'decoded input': { 'uint256 num': '57' } }) .clearConsole() @@ -194,7 +194,7 @@ const tests = { .clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '"555"' }) .testFunction('last', { - status: '0x1 Transaction mined and execution succeed', + status: '1 Transaction mined and execution succeed', 'block number': '5', 'decoded input': { 'uint256 num': '555' } }) diff --git a/apps/remix-ide-e2e/src/tests/workspace.test.ts b/apps/remix-ide-e2e/src/tests/workspace.test.ts index 09ba4adfe0e..b266bfb781d 100644 --- a/apps/remix-ide-e2e/src/tests/workspace.test.ts +++ b/apps/remix-ide-e2e/src/tests/workspace.test.ts @@ -54,17 +54,6 @@ module.exports = { .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - // check js and ts files are not transformed - .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - .waitForElementPresent({ - selector: "//div[contains(@class, 'view-line') and contains(.//span, './web3-lib')]", - locateStrategy: 'xpath' - }) - .getEditorValue((content) => { - browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1, - 'Incorrect content') - }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .waitForElementPresent({ @@ -75,16 +64,6 @@ module.exports = { browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1, 'Incorrect content') }) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') - .click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') - .waitForElementPresent({ - selector: "//div[contains(@class, 'view-line') and contains(.//span, 'web3.eth.getAccounts')]", - locateStrategy: 'xpath' - }) - .getEditorValue((content) => { - browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array, from?: string, gas?: number): Promise => {`) !== -1, - 'Incorrect content') - }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .waitForElementPresent({ @@ -157,17 +136,7 @@ module.exports = { .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - // check js and ts files are not transformed - .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - .waitForElementPresent({ - selector: "//div[contains(@class, 'view-line') and contains(.//span, './web3-lib')]", - locateStrategy: 'xpath', - }) - .getEditorValue((content) => { - browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1, - 'Incorrect content') - }) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .waitForElementPresent({ @@ -178,16 +147,6 @@ module.exports = { browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1, 'Incorrect content') }) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') - .click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') - .waitForElementPresent({ - selector: "//div[contains(@class, 'view-line') and contains(.//span, 'web3.eth.getAccounts')]", - locateStrategy: 'xpath' - }) - .getEditorValue((content) => { - browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array, from?: string, gas?: number): Promise => {`) !== -1, - 'Incorrect content') - }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .waitForElementPresent({ @@ -221,17 +180,7 @@ module.exports = { .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - // check js and ts files are not transformed - .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - .waitForElementPresent({ - selector: "//div[contains(@class, 'view-line') and contains(.//span, './web3-lib')]", - locateStrategy: 'xpath' - }) - .getEditorValue((content) => { - browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1, - 'Incorrect content') - }) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .waitForElementPresent({ @@ -242,16 +191,6 @@ module.exports = { browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1, 'Incorrect content') }) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') - .click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') - .waitForElementPresent({ - selector: "//div[contains(@class, 'view-line') and contains(.//span, 'web3.eth.getAccounts')]", - locateStrategy: 'xpath' - }) - .getEditorValue((content) => { - browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array, from?: string, gas?: number): Promise => {`) !== -1, - 'Incorrect content') - }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .waitForElementPresent({ @@ -284,17 +223,6 @@ module.exports = { .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - // check js and ts files are not transformed - .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - .waitForElementPresent({ - selector: "//div[contains(@class, 'view-line') and contains(.//span, './web3-lib')]", - locateStrategy: 'xpath' - }) - .getEditorValue((content) => { - browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1, - 'Incorrect content') - }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .waitForElementPresent({ @@ -305,16 +233,6 @@ module.exports = { browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1, 'Incorrect content') }) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') - .click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') - .waitForElementPresent({ - selector: "//div[contains(@class, 'view-line') and contains(.//span, 'web3.eth.getAccounts')]", - locateStrategy: 'xpath' - }) - .getEditorValue((content) => { - browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array, from?: string, gas?: number): Promise => {`) !== -1, - 'Incorrect content') - }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .waitForElementPresent({ @@ -355,17 +273,6 @@ module.exports = { 'Incorrect content') }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - // check js and ts files are not transformed - .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') - .waitForElementPresent({ - selector: "//div[contains(@class, 'view-line') and contains(.//span, './web3-lib')]", - locateStrategy: 'xpath' - }) - .getEditorValue((content) => { - browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1, - 'Incorrect content') - }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]') .waitForElementPresent({ @@ -376,18 +283,6 @@ module.exports = { browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1, 'Incorrect content') }) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') - .click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]') - .waitForElementPresent({ - selector: "//div[contains(@class, 'view-line') and contains(.//span, 'web3.eth.getAccounts')]", - locateStrategy: 'xpath' - }) - .getEditorValue((content) => { - browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array, from?: string, gas?: number): Promise => {`) !== -1, - 'Incorrect content') - browser.assert.ok(content.indexOf(`gas: gas || 3600000`) !== -1, - 'Incorrect gas cost') - }) .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]') .waitForElementPresent({ diff --git a/apps/remix-ide/src/app/plugins/solidity-script.tsx b/apps/remix-ide/src/app/plugins/solidity-script.tsx index 93fae6dbe92..fe6f257af82 100644 --- a/apps/remix-ide/src/app/plugins/solidity-script.tsx +++ b/apps/remix-ide/src/app/plugins/solidity-script.tsx @@ -2,7 +2,6 @@ import React from 'react' // eslint-disable-line import { format } from 'util' import { Plugin } from '@remixproject/engine' import { compile, CompilerSettings } from '@remix-project/remix-solidity' -import { Transaction } from 'web3-types' import { trackMatomoEvent } from '@remix-api' const profile = { @@ -82,13 +81,13 @@ export class SolidityScript extends Plugin { } // deploy the contract - let tx: Transaction = { + let tx: any = { from: accounts[0], data: bytecode } let receipt try { - receipt = await web3.eth.sendTransaction(tx, null, { checkRevertBeforeSending: false, ignoreGasPricing: true }) + receipt = await web3.sendTransaction(tx) } catch (e) { this.call('terminal', 'logHtml', e.message) return @@ -102,13 +101,13 @@ export class SolidityScript extends Plugin { let receiptCall try { - receiptCall = await web3.eth.sendTransaction(tx, null, { checkRevertBeforeSending: false, ignoreGasPricing: true }) + receiptCall = await web3.sendTransaction(tx) } catch (e) { this.call('terminal', 'logHtml', e.message) return } - const hhlogs = await web3.remix.getHHLogsForTx(receiptCall.transactionHash) + const hhlogs = await web3.remix.getHHLogsForTx(receiptCall.hash) if (hhlogs && hhlogs.length) { const finalLogs = ( diff --git a/apps/remix-ide/src/app/providers/injected-custom-provider.tsx b/apps/remix-ide/src/app/providers/injected-custom-provider.tsx index bacc4236785..be7da0b5268 100644 --- a/apps/remix-ide/src/app/providers/injected-custom-provider.tsx +++ b/apps/remix-ide/src/app/providers/injected-custom-provider.tsx @@ -1,4 +1,4 @@ -import { Web3 } from 'web3' +import { ethers } from 'ethers' import { InjectedProviderDefault } from './injected-provider-default' export class InjectedCustomProvider extends InjectedProviderDefault { @@ -28,7 +28,7 @@ export class InjectedCustomProvider extends InjectedProviderDefault { async init() { if (!this.chainId && this.rpcUrls.length > 0) { - const chainId = await new Web3(this.rpcUrls[0]).eth.getChainId() + const { chainId } = await new ethers.JsonRpcProvider(this.rpcUrls[0]).getNetwork() this.chainId = `0x${chainId.toString(16)}` } await super.init() diff --git a/apps/remix-ide/src/app/tabs/debugger-tab.js b/apps/remix-ide/src/app/tabs/debugger-tab.js index 0e30f19b2ff..d7cedf5c737 100644 --- a/apps/remix-ide/src/app/tabs/debugger-tab.js +++ b/apps/remix-ide/src/app/tabs/debugger-tab.js @@ -1,4 +1,3 @@ -import { Web3 } from 'web3' import { DebuggerUI } from '@remix-ui/debugger-ui' // eslint-disable-line import { DebuggerApiMixin } from '@remix-ui/debugger-ui' import { ViewPlugin } from '@remixproject/engine-web' @@ -86,7 +85,7 @@ export default class DebuggerTab extends DebuggerApiMixin(ViewPlugin) { 'timestamp': block.timestamp, } if (block.baseFeePerGas) { - blockContext['basefee'] = Web3.utils.toBigInt(block.baseFeePerGas).toString(10) + ` Wei (${block.baseFeePerGas})` + blockContext['basefee'] = BigInt(block.baseFeePerGas).toString(10) + ` Wei (${block.baseFeePerGas})` } const msg = { 'sender': tx.from, diff --git a/apps/remix-ide/src/app/tabs/network-module.js b/apps/remix-ide/src/app/tabs/network-module.js index 768b56140e4..a7c5537a494 100644 --- a/apps/remix-ide/src/app/tabs/network-module.js +++ b/apps/remix-ide/src/app/tabs/network-module.js @@ -1,7 +1,6 @@ import { Plugin } from '@remixproject/engine' import * as packageJson from '../../../../../package.json' -import { Web3 } from 'web3' -import IpcProvider from 'web3-providers-ipc' +import { ethers } from 'ethers' export const profile = { name: 'network', @@ -56,7 +55,7 @@ export class NetworkModule extends Plugin { /** Add a custom network to the list of available networks */ addNetwork (network) { // { name, url } - const provider = network.url === 'ipc' ? new IpcProvider() : new Web3.providers.HttpProvider(network.url) + const provider = network.url === 'ipc' ? new ethers.IpcProvider() : new ethers.JsonRpcProvider(network.url) this.blockchain.addProvider({ name: network.name, provider }) } diff --git a/apps/remix-ide/src/app/tabs/web3-provider.js b/apps/remix-ide/src/app/tabs/web3-provider.js index eaf52b87ab4..f97d02a3f3f 100644 --- a/apps/remix-ide/src/app/tabs/web3-provider.js +++ b/apps/remix-ide/src/app/tabs/web3-provider.js @@ -1,6 +1,5 @@ import { Plugin } from '@remixproject/engine' import * as packageJson from '../../../../../package.json' -import {isBigInt} from 'web3-validator' import { addressToString } from "@remix-ui/helper" export const profile = { @@ -13,7 +12,7 @@ export const profile = { } const replacer = (key, value) => { - if (isBigInt(value)) value = value.toString() + if (typeof value === 'bigint') value = value.toString() return value } @@ -33,7 +32,7 @@ export class Web3ProviderModule extends Plugin { this.askUserPermission('sendAsync', `Calling ${payload.method} with parameters ${JSON.stringify(payload.params, replacer, '\t')}`).then( async (result) => { if (result) { - const provider = this.blockchain.web3().currentProvider + const provider = this.blockchain.web3() const resultFn = async (error, message) => { if (error) { // Handle 'The method "debug_traceTransaction" does not exist / is not available.' error @@ -84,7 +83,7 @@ export class Web3ProviderModule extends Plugin { resolve(message) } try { - resultFn(null, await provider.sendAsync(payload)) + resultFn(null, await provider.send(payload.method, payload.params)) } catch (e) { resultFn(e.error ? e.error : e) } diff --git a/apps/remix-ide/src/app/udapp/make-udapp.js b/apps/remix-ide/src/app/udapp/make-udapp.js index da76944ce98..da23f2678eb 100644 --- a/apps/remix-ide/src/app/udapp/make-udapp.js +++ b/apps/remix-ide/src/app/udapp/make-udapp.js @@ -10,7 +10,7 @@ export function makeUdapp (blockchain, compilersArtefacts, logHtmlCallback) { if (_transactionReceipts[tx.hash]) { return cb(null, _transactionReceipts[tx.hash]) } - let res = blockchain.web3().eth.getTransactionReceipt(tx.hash, (error, receipt) => { + let res = blockchain.web3().getTransactionReceipt(tx.hash, (error, receipt) => { if (error) { return cb(error) } diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index 473e4801b23..f3c5162ac0e 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -1,5 +1,4 @@ import React from 'react' // eslint-disable-line -import { fromWei, toBigInt, toWei } from 'web3-utils' import { Plugin } from '@remixproject/engine' import { trackMatomoEvent } from '@remix-api' import { toBytes, addHexPrefix } from '@ethereumjs/util' @@ -19,6 +18,7 @@ const { txFormat, txExecution, typeConversion, txListener: Txlistener, TxRunner, const { txResultHelper } = helpers const { resultToRemixTx } = txResultHelper import * as packageJson from '../../../../package.json' +import { formatUnits, parseUnits } from 'ethers' const profile = { name: 'blockchain', @@ -573,17 +573,17 @@ export class Blockchain extends Plugin { fromWei(value, doTypeConversion, unit) { if (doTypeConversion) { - return fromWei(typeConversion.toInt(value), unit || 'ether') + return formatUnits(typeConversion.toInt(value), unit || 'ether') } - return fromWei(value.toString(10), unit || 'ether') + return formatUnits(value.toString(10), unit || 'ether') } toWei(value, unit) { - return toWei(value, unit || 'gwei') + return (parseUnits(value, unit || 'gwei')).toString() } calculateFee(gas, gasPrice, unit?) { - return toBigInt(gas) * toBigInt(toWei(gasPrice.toString(10) as string, unit || 'gwei')) + return BigInt(gas) * BigInt(parseUnits(gasPrice.toString(10) as string, unit || 'gwei')) } determineGasFees(tx) { @@ -877,11 +877,11 @@ export class Blockchain extends Plugin { } async getCode(address) { - return await this.web3().eth.getCode(address) + return await this.web3().getCode(address) } async getTransactionReceipt(hash) { - return await this.web3().eth.getTransactionReceipt(hash) + return await this.web3().getTransactionReceipt(hash) } /** diff --git a/apps/remix-ide/src/blockchain/execution-context.js b/apps/remix-ide/src/blockchain/execution-context.js index 1ed1d4ebec7..c3799f4d3b2 100644 --- a/apps/remix-ide/src/blockchain/execution-context.js +++ b/apps/remix-ide/src/blockchain/execution-context.js @@ -1,12 +1,11 @@ /* global ethereum */ 'use strict' -import { Web3 } from 'web3' +import { ethers, toNumber } from 'ethers' import { execution } from '@remix-project/remix-lib' import EventManager from '../lib/events' import { bytesToHex } from '@ethereumjs/util' - -let web3 +let provider // Helper function to track events using MatomoManager function track(event) { @@ -19,15 +18,12 @@ function track(event) { console.debug('Tracking error:', error) } } - -const config = { defaultTransactionType: '0x0' } if (typeof window !== 'undefined' && typeof window.ethereum !== 'undefined') { var injectedProvider = window.ethereum - web3 = new Web3(injectedProvider) + provider = new ethers.BrowserProvider(injectedProvider) } else { - web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) + provider = new ethers.JsonRpcProvider('http://localhost:8545') } -web3.eth.setConfig(config) /* trigger contextChanged, web3EndpointChanged @@ -71,13 +67,12 @@ export class ExecutionContext { } setWeb3 (context, web3) { - web3.setConfig(config) this.customWeb3[context] = web3 } web3 () { if (this.customWeb3[this.executionContext]) return this.customWeb3[this.executionContext] - return web3 + return provider } detectNetwork (callback) { @@ -86,7 +81,7 @@ export class ExecutionContext { callback && callback(null, { id: '-', name: 'VM' }) return resolve({ id: '-', name: 'VM' }) } else { - if (!web3.currentProvider) { + if (!provider) { callback && callback('No provider set') return reject('No provider set') } @@ -120,7 +115,7 @@ export class ExecutionContext { } if (id === 1) { - web3.eth.getBlock(0).then((block) => { + provider.getBlock(0).then((block) => { if (block && block.hash !== this.mainNetGenesisHash) name = 'Custom' callback && callback(err, { id, name, lastBlock: this.lastBlock, currentFork: this.currentFork, networkNativeCurrency }) return resolve({ id, name, lastBlock: this.lastBlock, currentFork: this.currentFork, networkNativeCurrency }) @@ -134,7 +129,7 @@ export class ExecutionContext { return resolve({ id, name, lastBlock: this.lastBlock, currentFork: this.currentFork, networkNativeCurrency }) } } - web3.eth.net.getId().then(async (id) => await cb(null, parseInt(id))).catch(err => cb(err)) + provider.getNetwork().then(async (network) => await cb(null, parseInt(network.chainId))).catch(err => cb(err)) } }) } @@ -158,7 +153,7 @@ export class ExecutionContext { } internalWeb3 () { - return web3 + return provider } setContext (context, endPointUrl, confirmCb, infoCb) { @@ -185,7 +180,7 @@ export class ExecutionContext { await network.init() this.currentFork = network.config.fork // injected - web3.setProvider(network.provider) + provider = new ethers.BrowserProvider(network.provider) this.executionContext = context this.isConnected = await this._updateChainContext() this.event.trigger('contextChanged', [context]) @@ -209,12 +204,12 @@ export class ExecutionContext { async _updateChainContext () { if (!this.isVM()) { try { - const block = await web3.eth.getBlock('latest') + const block = await provider.getBlock('latest') // we can't use the blockGasLimit cause the next blocks could have a lower limit : https://github.com/ethereum/remix/issues/506 - this.blockGasLimit = (block && block.gasLimit) ? Math.floor(web3.utils.toNumber(block.gasLimit) - (5 * web3.utils.toNumber(block.gasLimit) / 1024)) : web3.utils.toNumber(this.blockGasLimitDefault) + this.blockGasLimit = (block && block.gasLimit) ? Math.floor(toNumber(block.gasLimit) - (5 * toNumber(block.gasLimit) / 1024)) : toNumber(this.blockGasLimitDefault) this.lastBlock = block try { - this.currentFork = execution.forkAt(await web3.eth.net.getId(), block.number) + this.currentFork = execution.forkAt((await provider.getNetwork()).chainId, block.number) } catch (e) { this.currentFork = 'prague' console.log(`unable to detect fork, defaulting to ${this.currentFork}..`) diff --git a/apps/remix-ide/src/blockchain/providers/injected.ts b/apps/remix-ide/src/blockchain/providers/injected.ts index cb460af13c5..dfc0473e0aa 100644 --- a/apps/remix-ide/src/blockchain/providers/injected.ts +++ b/apps/remix-ide/src/blockchain/providers/injected.ts @@ -1,7 +1,6 @@ -import { Web3 } from 'web3' import { hashPersonalMessage, isHexString, bytesToHex } from '@ethereumjs/util' -import { Personal } from 'web3-eth-personal' import { ExecutionContext } from '../execution-context' +import { formatUnits, hexlify, toUtf8Bytes } from 'ethers' export class InjectedProvider { executionContext: ExecutionContext @@ -11,7 +10,7 @@ export class InjectedProvider { } getAccounts (cb) { - return this.executionContext.web3().eth.getAccounts() + return this.executionContext.web3().send("eth_requestAccounts", []) .then(accounts => cb(null, accounts)) .catch(err => { cb(err.message) @@ -19,9 +18,10 @@ export class InjectedProvider { } newAccount (passwordPromptCb, cb) { - passwordPromptCb((passphrase) => { - this.executionContext.web3().eth.personal.newAccount(passphrase).then((result) => cb(null, result)).catch(error => cb(error)) - }) + /* Do nothing. On UI too, this feature is not supported*/ + // passwordPromptCb((passphrase) => { + // this.executionContext.web3().eth.personal.newAccount(passphrase).then((result) => cb(null, result)).catch(error => cb(error)) + // }) } async resetEnvironment () { @@ -29,24 +29,25 @@ export class InjectedProvider { } async getBalanceInEther (address) { - const balance = await this.executionContext.web3().eth.getBalance(address) + const balance = await this.executionContext.web3().getBalance(address) const balInString = balance.toString(10) - return balInString === '0' ? balInString : Web3.utils.fromWei(balInString, 'ether') + return balInString === '0' ? balInString : formatUnits(balInString, 'ether') } getGasPrice (cb) { - this.executionContext.web3().eth.getGasPrice().then((result => cb(null, result))) + this.executionContext.web3().getFeeData().then((result => cb(null, result.gasPrice))) } signMessage (message, account, _passphrase, cb) { const messageHash = hashPersonalMessage(Buffer.from(message)) try { - const personal = new Personal(this.executionContext.web3().currentProvider) - message = isHexString(message) ? message : Web3.utils.utf8ToHex(message) + this.executionContext.web3().getSigner(account).then((signer) => { + message = isHexString(message) ? message : hexlify(toUtf8Bytes(message)) // see https://docs.metamask.io/wallet/reference/json-rpc-methods/personal_sign/ - personal.sign(message, account, '') + signer.signMessage(message) .then(signedData => cb(undefined, bytesToHex(messageHash), signedData)) .catch(error => cb(error, bytesToHex(messageHash), undefined)) + }) } catch (e) { cb(e.message) } diff --git a/apps/remix-ide/src/blockchain/providers/node.ts b/apps/remix-ide/src/blockchain/providers/node.ts index 7cedd65ec93..2b04e651557 100644 --- a/apps/remix-ide/src/blockchain/providers/node.ts +++ b/apps/remix-ide/src/blockchain/providers/node.ts @@ -1,8 +1,7 @@ -import { Web3 } from 'web3' import { hashPersonalMessage, isHexString, bytesToHex } from '@ethereumjs/util' -import { Personal } from 'web3-eth-personal' import { ExecutionContext } from '../execution-context' import Config from '../../config' +import { formatUnits, hexlify, toUtf8Bytes, ethers } from 'ethers' export class NodeProvider { executionContext: ExecutionContext @@ -17,11 +16,7 @@ export class NodeProvider { if (!this.executionContext.isConnected) { return cb('Not connected to a node') } - if (this.config.get('settings/personal-mode')) { - this.executionContext.web3().eth.personal.getAccounts().then(res => cb(null, res)).catch(err => cb(err)) - return - } - this.executionContext.web3().eth.getAccounts().then(res => cb(null, res)).catch(err => cb(err)) + this.executionContext.web3().send("eth_accounts", []).then(res => cb(null, res)).catch(err => cb(err)) } newAccount (passwordPromptCb, cb) { @@ -32,7 +27,8 @@ export class NodeProvider { return cb('Not running in personal mode') } passwordPromptCb((passphrase) => { - this.executionContext.web3().eth.personal.newAccount(passphrase).then(res => cb(null, res)).catch(err => cb(err)) + const wallet = ethers.Wallet.createRandom(this.executionContext.web3()) + wallet.encrypt(passphrase).then(jsonWallet => cb(null, wallet.address)).catch(err => cb(err)) }) } @@ -41,13 +37,13 @@ export class NodeProvider { } async getBalanceInEther (address) { - const balance = await this.executionContext.web3().eth.getBalance(address) + const balance = await this.executionContext.web3().getBalance(address) const balInString = balance.toString(10) - return balInString === '0' ? balInString : Web3.utils.fromWei(balInString, 'ether') + return balInString === '0' ? balInString : formatUnits(balInString, 'ether') } getGasPrice (cb) { - this.executionContext.web3().eth.getGasPrice().then(res => cb(null, res)).catch(err => cb(err)) + this.executionContext.web3().getFeeData().then((result => cb(null, result.gasPrice))).catch(err => cb(err)) } signMessage (message, account, passphrase, cb) { @@ -56,11 +52,13 @@ export class NodeProvider { } const messageHash = hashPersonalMessage(Buffer.from(message)) try { - const personal = new Personal(this.executionContext.web3().currentProvider) - message = isHexString(message) ? message : Web3.utils.utf8ToHex(message) - personal.sign(message, account, passphrase || '') - .then(signedData => cb(undefined, bytesToHex(messageHash), signedData)) - .catch(error => cb(error, bytesToHex(messageHash), undefined)) + this.executionContext.web3().getSigner(account).then((signer) => { + message = isHexString(message) ? message : hexlify(toUtf8Bytes(message)) + signer.sign(message, passphrase || '') + .then(signedData => cb(undefined, bytesToHex(messageHash), signedData)) + .catch(error => cb(error, bytesToHex(messageHash), undefined)) + }) + } catch (e) { cb(e.message) } diff --git a/apps/remix-ide/src/blockchain/providers/vm.ts b/apps/remix-ide/src/blockchain/providers/vm.ts index b32a3be6acd..f93cc09ab86 100644 --- a/apps/remix-ide/src/blockchain/providers/vm.ts +++ b/apps/remix-ide/src/blockchain/providers/vm.ts @@ -1,12 +1,11 @@ -import { Web3, FMT_BYTES, FMT_NUMBER, LegacySendAsyncProvider, LegacyRequestProvider } from 'web3' -import { fromWei, toBigInt } from 'web3-utils' import { privateToAddress, hashPersonalMessage, isHexString, bytesToHex } from '@ethereumjs/util' -import { extend, JSONRPCRequestPayload, JSONRPCResponseCallback } from '@remix-project/remix-simulator' +import { extendProvider, JSONRPCRequestPayload, JSONRPCResponseCallback } from '@remix-project/remix-simulator' import { ExecutionContext } from '../execution-context' +import { BrowserProvider, formatUnits, hexlify, toUtf8Bytes, ethers } from 'ethers' export class VMProvider { executionContext: ExecutionContext - web3: Web3 + web3: BrowserProvider worker: Worker provider: { sendAsync: (query: JSONRPCRequestPayload, callback: JSONRPCResponseCallback) => void @@ -21,7 +20,7 @@ export class VMProvider { } getAccounts (cb) { - this.web3.eth.getAccounts() + this.web3.send("eth_requestAccounts", []) .then(accounts => cb(null, accounts)) .catch(err => { cb('No accounts?') @@ -74,9 +73,8 @@ export class VMProvider { }) } } - this.web3 = new Web3(this.provider as (LegacySendAsyncProvider | LegacyRequestProvider)) - this.web3.setConfig({ defaultTransactionType: '0x0' }) - extend(this.web3) + this.web3 = new ethers.BrowserProvider(this.provider) + extendProvider(this.web3) this.executionContext.setWeb3(this.executionContext.getProvider(), this.web3) resolve({}) } else { @@ -123,7 +121,7 @@ export class VMProvider { createVMAccount (newAccount) { const { privateKey, balance } = newAccount this.worker.postMessage({ cmd: 'addAccount', privateKey: privateKey, balance }) - const privKey = Buffer.from(privateKey, 'hex') + const privKey: any = Buffer.from(privateKey, 'hex') return bytesToHex(privateToAddress(privKey)) } @@ -134,20 +132,22 @@ export class VMProvider { } async getBalanceInEther (address) { - const balance = await this.web3.eth.getBalance(address, undefined, { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX }) - const balInString = toBigInt(balance).toString(10) - return balInString === '0' ? balInString : fromWei(balInString, 'ether') + const balance = await this.web3.getBalance(address) + const balInString = BigInt(balance).toString(10) + return balInString === '0' ? balInString : formatUnits(balInString, 'ether') } getGasPrice (cb) { - this.web3.eth.getGasPrice().then((result => cb(null, result))).catch((error) => cb(error)) + this.web3.getFeeData().then((result => cb(null, result.gasPrice))) } signMessage (message, account, _passphrase, cb) { const messageHash = hashPersonalMessage(Buffer.from(message)) - message = isHexString(message) ? message : Web3.utils.utf8ToHex(message) - this.web3.eth.sign(message, account) - .then(signedData => cb(null, bytesToHex(messageHash), signedData)) - .catch(error => cb(error)) + this.web3.getSigner(account).then((signer) => { + message = isHexString(message) ? message : hexlify(toUtf8Bytes(message)) + signer.signMessage(message) + .then(signedData => cb(null, bytesToHex(messageHash), signedData)) + .catch(error => cb(error)) + }) } } diff --git a/libs/ghaction-helper/package.json b/libs/ghaction-helper/package.json index 8e5f4fb86e9..52e78d87bef 100644 --- a/libs/ghaction-helper/package.json +++ b/libs/ghaction-helper/package.json @@ -27,8 +27,7 @@ "@ethereum-waffle/chai": "^3.4.4", "@remix-project/remix-simulator": "^0.2.80", "chai": "^4.3.7", - "ethers": "^6.14.0", - "web3": "^4.1.1" + "ethers": "^6.14.0" }, "types": "./src/index.d.ts", "gitHead": "4dac681834150631b0ea67e1bef7ee6bd85df9ee" diff --git a/libs/ghaction-helper/src/methods.ts b/libs/ghaction-helper/src/methods.ts index 019f30358c6..cb20ae301e5 100644 --- a/libs/ghaction-helper/src/methods.ts +++ b/libs/ghaction-helper/src/methods.ts @@ -2,7 +2,6 @@ import { BrowserProvider, Contract, InterfaceAbi } from "ethers" import { Provider } from '@remix-project/remix-simulator' import { getArtifactsByContractName } from './artifacts-helper' -import { Web3 } from "web3" const providerConfig = { fork: global.fork || null, @@ -16,8 +15,6 @@ global.remixProvider.init() global.web3Provider = new BrowserProvider(global.remixProvider) global.provider = global.web3Provider global.ethereum = global.web3Provider -global.web3 = new Web3(global.web3Provider) -global.web3.eth.setConfig(config) const isFactoryOptions = (signerOrOptions: any) => { if (!signerOrOptions || signerOrOptions === undefined || typeof(signerOrOptions.connect) === 'function') return false diff --git a/libs/remix-analyzer/package.json b/libs/remix-analyzer/package.json index 1c5af042af5..ae6f2a7ac5a 100644 --- a/libs/remix-analyzer/package.json +++ b/libs/remix-analyzer/package.json @@ -30,8 +30,7 @@ "async": "^2.6.2", "ethers": "^6.14.0", "ethjs-util": "^0.1.6", - "string-similarity": "^4.0.4", - "web3": "^4.1.1" + "string-similarity": "^4.0.4" }, "publishConfig": { "access": "public" diff --git a/libs/remix-astwalker/package.json b/libs/remix-astwalker/package.json index 443d024b533..667de45a611 100644 --- a/libs/remix-astwalker/package.json +++ b/libs/remix-astwalker/package.json @@ -46,8 +46,7 @@ "string-similarity": "^4.0.4", "tape": "^4.10.1", "ts-node": "^8.0.3", - "typescript": "^3.4.3", - "web3": "^4.1.1" + "typescript": "^3.4.3" }, "devDependencies": { "tap-spec": "^5.0.0" diff --git a/libs/remix-debug/package.json b/libs/remix-debug/package.json index 07d2f683958..f898371eaf3 100644 --- a/libs/remix-debug/package.json +++ b/libs/remix-debug/package.json @@ -41,8 +41,7 @@ "express-ws": "^4.0.0", "merge": "^2.1.1", "string-similarity": "^4.0.4", - "time-stamp": "^2.2.0", - "web3": "^4.1.1" + "time-stamp": "^2.2.0" }, "devDependencies": { "@babel/core": "^7.4.5", diff --git a/libs/remix-debug/src/Ethdebugger.ts b/libs/remix-debug/src/Ethdebugger.ts index 6dc4be709ca..9fc82d39792 100644 --- a/libs/remix-debug/src/Ethdebugger.ts +++ b/libs/remix-debug/src/Ethdebugger.ts @@ -7,7 +7,6 @@ import { CodeManager } from './code/codeManager' import { contractCreationToken } from './trace/traceHelper' import { EventManager } from './eventManager' import { SolidityProxy, stateDecoder, localDecoder, InternalCallTree } from './solidity-decoder' -import { extractStateVariables } from './solidity-decoder/stateDecoder' /** * Ethdebugger is a wrapper around a few classes that helps debug a transaction diff --git a/libs/remix-debug/src/cmdline/index.ts b/libs/remix-debug/src/cmdline/index.ts index da56ba00b94..c53c15a093b 100644 --- a/libs/remix-debug/src/cmdline/index.ts +++ b/libs/remix-debug/src/cmdline/index.ts @@ -1,4 +1,4 @@ -import { Web3 } from 'web3' +import { ethers } from 'ethers' import { Debugger } from '../debugger/debugger' import { EventEmitter } from 'events' @@ -22,7 +22,7 @@ export class CmdLine { connect (providerType, url) { if (providerType !== 'http') throw new Error('unsupported provider type') - this.web3 = new Web3(new Web3.providers.HttpProvider(url)) + this.web3 = new ethers.JsonRpcProvider(url) } loadCompilationData (inputJson, outputJson) { diff --git a/libs/remix-debug/src/code/codeManager.ts b/libs/remix-debug/src/code/codeManager.ts index 1c8b4eacd7d..a3841908ef7 100644 --- a/libs/remix-debug/src/code/codeManager.ts +++ b/libs/remix-debug/src/code/codeManager.ts @@ -26,7 +26,7 @@ export class CodeManager { this.codeResolver = new CodeResolver({ getCode: async (address) => { return new Promise((resolve, reject) => { - this.traceManager.web3.eth.getCode(address) + this.traceManager.web3.getCode(address) .then(code => resolve(code)) .catch(error => reject(error)) }) diff --git a/libs/remix-debug/src/debugger/debugger.ts b/libs/remix-debug/src/debugger/debugger.ts index 643a3917192..8d50df8a75b 100644 --- a/libs/remix-debug/src/debugger/debugger.ts +++ b/libs/remix-debug/src/debugger/debugger.ts @@ -144,10 +144,10 @@ export class Debugger { } if (txNumber.indexOf('0x') !== -1) { - tx = await web3.eth.getTransaction(txNumber) + tx = await web3.getTransaction(txNumber) if (!tx) throw new Error('cannot find transaction ' + txNumber) } else { - tx = await web3.eth.getTransactionFromBlock(blockNumber, txNumber) + tx = await web3.getTransactionFromBlock(blockNumber, txNumber) if (!tx) throw new Error('cannot find transaction ' + blockNumber + ' ' + txNumber) } return await this.debugTx(tx, loadingCb) diff --git a/libs/remix-debug/src/init.ts b/libs/remix-debug/src/init.ts index a84f58a59de..0e9f58fb4e2 100644 --- a/libs/remix-debug/src/init.ts +++ b/libs/remix-debug/src/init.ts @@ -1,23 +1,10 @@ 'use strict' -import { Web3, Web3PluginBase } from 'web3' -import { toNumber } from 'web3-utils' +import { toNumber, ethers } from 'ethers' -export function extendWeb3 (web3) { - if (!web3.debug){ - web3.registerPlugin(new Web3DebugPlugin()) - } -} - -export function loadWeb3 (url) { - if (!url) url = 'http://localhost:8545' - const web3 = new Web3() - web3.setProvider(new Web3.providers.HttpProvider(url)) - extendWeb3(web3) - return web3 -} - -export function setProvider (web3, url) { - web3.setProvider(new web3.providers.HttpProvider(url)) +export function loadWeb3 (url = 'http://localhost:8545') { + const provider = new ethers.JsonRpcProvider(url) + extendProvider(provider) + return provider } export function web3DebugNode (network) { @@ -31,32 +18,24 @@ export function web3DebugNode (network) { return null } -class Web3DebugPlugin extends Web3PluginBase { - public pluginNamespace = 'debug' +export function extendProvider (provider) { // Provider should be ethers.js provider + + if (!provider.debug) provider.debug = {} - public preimage(key, cb) { - this.requestManager.send({ - method: 'debug_preimage', - params: [key] - }) + provider.debug.preimage = (key, cb) => { + provider.send('debug_preimage', [key]) .then(result => cb(null, result)) .catch(error => cb(error)) } - public traceTransaction(txHash, options, cb) { - this.requestManager.send({ - method: 'debug_traceTransaction', - params: [txHash, options] - }) + provider.debug.traceTransaction = (txHash, options, cb) => { + provider.send('debug_traceTransaction', [txHash, options]) .then(result => cb(null, result)) .catch(error => cb(error)) } - public storageRangeAt(txBlockHash, txIndex, address, start, maxSize, cb) { - this.requestManager.send({ - method: 'debug_storageRangeAt', - params: [txBlockHash, toNumber(txIndex), address, start, maxSize] - }) + provider.debug.storageRangeAt = (txBlockHash, txIndex, address, start, maxSize, cb) => { + provider.send('debug_storageRangeAt', [txBlockHash, toNumber(txIndex), address, start, maxSize]) .then(result => cb(null, result)) .catch(error => cb(error)) } diff --git a/libs/remix-debug/src/storage/storageResolver.ts b/libs/remix-debug/src/storage/storageResolver.ts index f6606b86a08..b0400a40efe 100644 --- a/libs/remix-debug/src/storage/storageResolver.ts +++ b/libs/remix-debug/src/storage/storageResolver.ts @@ -133,7 +133,7 @@ export class StorageResolver { resolve([{}, null]) } else { this.web3.debug.storageRangeAt( - tx.blockHash, tx.transactionIndex, + tx.blockHash, tx.index, address, start, maxSize, diff --git a/libs/remix-debug/src/trace/traceAnalyser.ts b/libs/remix-debug/src/trace/traceAnalyser.ts index d8ec2ac345b..9c4b5fb72b4 100644 --- a/libs/remix-debug/src/trace/traceAnalyser.ts +++ b/libs/remix-debug/src/trace/traceAnalyser.ts @@ -24,7 +24,7 @@ export class TraceAnalyser { const callStack = [tx.to] this.traceCache.pushCall(trace[0], 0, callStack[0], callStack.slice(0)) if (traceHelper.isContractCreation(tx.to)) { - this.traceCache.pushContractCreation(tx.to, tx.input) + this.traceCache.pushContractCreation(tx.to, tx.data) } this.buildCalldata(0, this.trace[0], tx, true) for (let k = 0; k < this.trace.length; k++) { diff --git a/libs/remix-debug/src/trace/traceManager.ts b/libs/remix-debug/src/trace/traceManager.ts index d4926269567..d9ee973647d 100644 --- a/libs/remix-debug/src/trace/traceManager.ts +++ b/libs/remix-debug/src/trace/traceManager.ts @@ -37,7 +37,7 @@ export class TraceManager { this.trace = result['structLogs'] try { - const networkId = await this.web3.eth.net.getId() + const networkId = (await this.web3.getNetwork()).chainId this.fork = execution.forkAt(networkId, tx.blockNumber) } catch (e) { this.fork = 'prague' diff --git a/libs/remix-debug/test.ts b/libs/remix-debug/test.ts index 0fe8ab5edb0..298ca386493 100644 --- a/libs/remix-debug/test.ts +++ b/libs/remix-debug/test.ts @@ -45,21 +45,6 @@ const cmdLine = new CmdLine() cmdLine.connect('http', 'http://localhost:8545') cmdLine.loadCompilationResult(compilation) cmdLine.initDebugger() - -// var deployContract = function (cb) { -// let _web3 = cmdLine.debugger.debugger.web3 -// -// let blockNumber = null -// let txNumber = null -// let tx = null -// -// let code = compilation.data.contracts[shortFilename].SimpleStorage.evm.bytecode.object -// console.dir('deploying...') -// console.dir(code) -// _web3.eth.sendTransaction({data: '0x' + code, from: _web3.eth.accounts[0], gas: 800000}, cb) -// } - -// let _web3 = cmdLine.debugger.debugger.web3 const tx = '0xf510c4f0b1d9ee262d7b9e9e87b4262f275fe029c2c733feef7dfa1e2b1e32aa' // deployContract((err, tx) => { diff --git a/libs/remix-debug/test/codeManager.ts b/libs/remix-debug/test/codeManager.ts index 449562afeb2..611c356e5f7 100644 --- a/libs/remix-debug/test/codeManager.ts +++ b/libs/remix-debug/test/codeManager.ts @@ -7,9 +7,9 @@ const web3Test = require('./resources/testWeb3.ts') tape('CodeManager', function (t) { const traceManager = new TraceManager({ web3: web3Test }) const codeManager = new CodeManager(traceManager) - const contractCode = web3Test.eth.getCode('0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5') + const contractCode = web3Test.getCode('0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5') codeManager.codeResolver.cacheExecutingCode('0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5', contractCode) // so a call to web3 is not necessary - const tx = web3Test.eth.getTransaction('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') + const tx = web3Test.getTransaction('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') traceManager.resolveTrace(tx).then(() => { continueTesting(t, codeManager) }).catch(() => { @@ -46,7 +46,7 @@ function continueTesting (t, codeManager) { } } }) - const tx = web3Test.eth.getTransaction('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') + const tx = web3Test.getTransaction('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') codeManager.resolveStep(0, tx) codeManager.resolveStep(70, tx) }) diff --git a/libs/remix-debug/test/debugger.ts b/libs/remix-debug/test/debugger.ts index e1389cdc498..4750fa1d82d 100644 --- a/libs/remix-debug/test/debugger.ts +++ b/libs/remix-debug/test/debugger.ts @@ -161,7 +161,7 @@ contract Ballot { if (error) { throw error } else { - web3.eth.getTransaction(hash) + web3.getTransaction(hash) .then(tx => { const sources = { target: 'test.sol', diff --git a/libs/remix-debug/test/decoder/localsTests/calldata.ts b/libs/remix-debug/test/decoder/localsTests/calldata.ts index de2932ea0f6..a2ef0bc9c2c 100644 --- a/libs/remix-debug/test/decoder/localsTests/calldata.ts +++ b/libs/remix-debug/test/decoder/localsTests/calldata.ts @@ -16,7 +16,7 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe try { web3 = await (vmCall as any).getWeb3() const hash = await (vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, undefined, 0, contractBytecode) - const receipt = await web3.eth.getTransactionReceipt(hash) + const receipt = await web3.getTransactionReceipt(hash) const to = receipt.contractAddress console.log('to', to) // call to level11 @@ -25,7 +25,7 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe return st.fail(e) } return new Promise((resolve) => { - web3.eth.getTransaction(txHash) + web3.getTransaction(txHash) .then(tx => { const traceManager = new TraceManager({ web3 }) const codeManager = new CodeManager(traceManager) diff --git a/libs/remix-debug/test/decoder/localsTests/int.ts b/libs/remix-debug/test/decoder/localsTests/int.ts index ca1a3e1d88c..acfab151468 100644 --- a/libs/remix-debug/test/decoder/localsTests/int.ts +++ b/libs/remix-debug/test/decoder/localsTests/int.ts @@ -18,7 +18,7 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult, if (error) { return st.fail(error) } - web3.eth.getTransaction(hash) + web3.getTransaction(hash) .then(tx => { tx.to = contractCreationToken('0') const traceManager = new TraceManager({ web3 }) diff --git a/libs/remix-debug/test/decoder/localsTests/misc.ts b/libs/remix-debug/test/decoder/localsTests/misc.ts index 1c76b42499f..bb6a06323e4 100644 --- a/libs/remix-debug/test/decoder/localsTests/misc.ts +++ b/libs/remix-debug/test/decoder/localsTests/misc.ts @@ -17,7 +17,7 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult, if (error) { return st.fail(error) } - web3.eth.getTransaction(hash) + web3.getTransaction(hash) .then(tx => { tx.to = contractCreationToken('0') const traceManager = new TraceManager({ web3 }) diff --git a/libs/remix-debug/test/decoder/localsTests/misc2.ts b/libs/remix-debug/test/decoder/localsTests/misc2.ts index c10dfacd461..419703a153e 100644 --- a/libs/remix-debug/test/decoder/localsTests/misc2.ts +++ b/libs/remix-debug/test/decoder/localsTests/misc2.ts @@ -17,7 +17,7 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult, if (error) { return st.fail(error) } - web3.eth.getTransaction(hash) + web3.getTransaction(hash) .then(tx => { tx.to = contractCreationToken('0') const traceManager = new TraceManager({ web3 }) diff --git a/libs/remix-debug/test/decoder/localsTests/structArray.ts b/libs/remix-debug/test/decoder/localsTests/structArray.ts index e10061fc701..8750750636f 100644 --- a/libs/remix-debug/test/decoder/localsTests/structArray.ts +++ b/libs/remix-debug/test/decoder/localsTests/structArray.ts @@ -17,7 +17,7 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult,c if (error) { return st.fail(error) } - web3.eth.getTransaction(hash) + web3.getTransaction(hash) .then(tx => { tx.to = contractCreationToken('0') const traceManager = new TraceManager({ web3 }) diff --git a/libs/remix-debug/test/decoder/stateTests/mapping.ts b/libs/remix-debug/test/decoder/stateTests/mapping.ts index 5a2af966900..e24ccaedcd0 100644 --- a/libs/remix-debug/test/decoder/stateTests/mapping.ts +++ b/libs/remix-debug/test/decoder/stateTests/mapping.ts @@ -28,7 +28,7 @@ module.exports = async function testMappingStorage (st, cb) { console.log(error) st.end(error) } else { - web3.eth.getTransactionReceipt(hash) + web3.getTransactionReceipt(hash) .then(tx => { // const storage = await this.vm.stateManager.dumpStorage(data.to) // web3.eth.getCode(tx.contractAddress).then((code) => console.log('code:---', code)) @@ -51,7 +51,7 @@ function testMapping (st, privateKey, contractAddress, output, compilationResult console.log(error) st.end(error) } else { - web3.eth.getTransaction(hash) + web3.getTransaction(hash) .then(tx => { const traceManager = new TraceManager({ web3 }) const codeManager = new CodeManager(traceManager) diff --git a/libs/remix-debug/test/decoder/stateTests/revert-state-sub-call.ts b/libs/remix-debug/test/decoder/stateTests/revert-state-sub-call.ts index 4d5e6bd2196..c9f53f66f56 100644 --- a/libs/remix-debug/test/decoder/stateTests/revert-state-sub-call.ts +++ b/libs/remix-debug/test/decoder/stateTests/revert-state-sub-call.ts @@ -27,7 +27,7 @@ module.exports = async function testMappingStorage (st, cb) { console.log(error) st.end(error) } else { - web3.eth.getTransactionReceipt(hash) + web3.getTransactionReceipt(hash) .then(tx => { // const storage = await this.vm.stateManager.dumpStorage(data.to) // web3.eth.getCode(tx.contractAddress).then((code) => console.log('code:---', code)) @@ -51,7 +51,7 @@ function testRevertStateSubCall (st, privateKey, contractAddress, output, compil console.log(error) st.end(error) } else { - web3.eth.getTransaction(hash) + web3.getTransaction(hash) .then(tx => { const traceManager = new TraceManager({ web3 }) const codeManager = new CodeManager(traceManager) diff --git a/libs/remix-debug/test/decoder/stateTests/revert-state.ts b/libs/remix-debug/test/decoder/stateTests/revert-state.ts index 97662bd5bb6..47ff83413e7 100644 --- a/libs/remix-debug/test/decoder/stateTests/revert-state.ts +++ b/libs/remix-debug/test/decoder/stateTests/revert-state.ts @@ -28,7 +28,7 @@ module.exports = async function testMappingStorage (st, cb) { console.log(error) st.end(error) } else { - web3.eth.getTransactionReceipt(hash) + web3.getTransactionReceipt(hash) .then(tx => { // const storage = await this.vm.stateManager.dumpStorage(data.to) // web3.eth.getCode(tx.contractAddress).then((code) => console.log('code:---', code)) @@ -52,7 +52,7 @@ function testRevertState (st, privateKey, contractAddress, output, compilationRe console.log(error) st.end(error) } else { - web3.eth.getTransaction(hash) + web3.getTransaction(hash) .then(tx => { const traceManager = new TraceManager({ web3 }) const codeManager = new CodeManager(traceManager) diff --git a/libs/remix-debug/test/init.ts b/libs/remix-debug/test/init.ts index 547d5e1d6e0..e4df1b88a71 100644 --- a/libs/remix-debug/test/init.ts +++ b/libs/remix-debug/test/init.ts @@ -1,11 +1,11 @@ export const init = { overrideWeb3: function (web3, web3Override) { - web3.eth.getCode = web3Override.getCode + web3.getCode = web3Override.getCode web3.debug.traceTransaction = web3Override.traceTransaction web3.debug.storageRangeAt = web3Override.storageRangeAt - web3.eth.getTransaction = web3Override.getTransaction - web3.eth.getTransactionFromBlock = web3Override.getTransactionFromBlock - web3.eth.getBlockNumber = web3Override.getBlockNumber + web3.getTransaction = web3Override.getTransaction + web3.getTransactionFromBlock = web3Override.getTransactionFromBlock + web3.getBlockNumber = web3Override.getBlockNumber }, readFile: function (filename, callback) { diff --git a/libs/remix-debug/test/resources/testWeb3.ts b/libs/remix-debug/test/resources/testWeb3.ts index 60bf50eae66..3999e0561bb 100644 --- a/libs/remix-debug/test/resources/testWeb3.ts +++ b/libs/remix-debug/test/resources/testWeb3.ts @@ -1,7 +1,6 @@ 'use strict' import { init } from '../init' -const web3Override: Record> = {} -web3Override.eth = {} +const web3Override: any = {} web3Override.debug = {} let data = init.readFile(require('path').resolve(__dirname, 'testWeb3.json'), null) data = JSON.parse(data) @@ -10,7 +9,7 @@ let traceWithABIEncoder = init.readFile(require('path').resolve(__dirname, 'trac traceWithABIEncoder = data.testTraces['0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd53'] = JSON.parse(traceWithABIEncoder) -web3Override.eth.getCode = function (address, callback) { +web3Override.getCode = function (address, callback) { if (callback) { callback(null, data.testCodes[address]) } else { @@ -26,7 +25,7 @@ web3Override.debug.storageRangeAt = function (blockNumber, txIndex, address, sta callback(null, { storage: {}, complete: true }) } -web3Override.eth.getTransaction = function (txHash, callback) { +web3Override.getTransaction = function (txHash, callback) { if (callback) { callback(null, data.testTxs[txHash]) } else { @@ -34,7 +33,7 @@ web3Override.eth.getTransaction = function (txHash, callback) { } } -web3Override.eth.getTransactionFromBlock = function (blockNumber, txIndex, callback) { +web3Override.getTransactionFromBlock = function (blockNumber, txIndex, callback) { if (callback) { callback(null, data.testTxsByBlock[blockNumber + '-' + txIndex]) } else { @@ -42,13 +41,13 @@ web3Override.eth.getTransactionFromBlock = function (blockNumber, txIndex, callb } } -web3Override.eth.getBlockNumber = function (callback) { callback('web3 modified testing purposes :)') } +web3Override.getBlockNumber = function (callback) { callback('web3 modified testing purposes :)') } -web3Override.eth.setProvider = function (provider) {} +web3Override.setProvider = function (provider) {} -web3Override.eth.providers = { 'HttpProvider': function (url) {} } +web3Override.providers = { 'HttpProvider': function (url) {} } -web3Override.eth.currentProvider = { 'host': 'test provider' } +web3Override.currentProvider = { 'host': 'test provider' } if (typeof (module) !== 'undefined' && typeof (module.exports) !== 'undefined') { module.exports = web3Override diff --git a/libs/remix-debug/test/sourceLocationTracker.ts b/libs/remix-debug/test/sourceLocationTracker.ts index 991fd001933..26e7aef3be3 100644 --- a/libs/remix-debug/test/sourceLocationTracker.ts +++ b/libs/remix-debug/test/sourceLocationTracker.ts @@ -19,7 +19,7 @@ tape('SourceLocationTracker', function (t) { codeManager.codeResolver.cacheExecutingCode('0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5', '0x' + output.contracts['test.sol']['test'].evm.deployedBytecode.object) - const tx = web3Test.eth.getTransaction('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd52') + const tx = web3Test.getTransaction('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd52') traceManager.resolveTrace(tx).then(async () => { @@ -50,7 +50,7 @@ tape('SourceLocationTracker', function (t) { codeManager.codeResolver.cacheExecutingCode('0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5', '0x' + output.contracts['test.sol']['test'].evm.deployedBytecode.object) - const tx = web3Test.eth.getTransaction('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd53') + const tx = web3Test.getTransaction('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd53') traceManager.resolveTrace(tx).then(async () => { diff --git a/libs/remix-debug/test/traceManager.ts b/libs/remix-debug/test/traceManager.ts index 523d0d49279..f4ddf8073e7 100644 --- a/libs/remix-debug/test/traceManager.ts +++ b/libs/remix-debug/test/traceManager.ts @@ -12,7 +12,7 @@ tape('TraceManager', function (t) { }) t.test('TraceManager.resolveTrace', function (st) { - const tx = web3Test.eth.getTransaction('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') + const tx = web3Test.getTransaction('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51') traceManager.resolveTrace(tx).then(() => { st.end() }).catch(() => { diff --git a/libs/remix-debug/test/vmCall.ts b/libs/remix-debug/test/vmCall.ts index 53db1197db1..66a2c45d2e2 100644 --- a/libs/remix-debug/test/vmCall.ts +++ b/libs/remix-debug/test/vmCall.ts @@ -1,30 +1,31 @@ 'use strict' -import { extendWeb3 } from '../src/init' +import { extendProvider } from '../src/init' import { createAddressFromPrivateKey } from '@ethereumjs/util' -import { Web3 } from 'web3'; -const { Provider } = require('@remix-project/remix-simulator') +import { Provider } from '@remix-project/remix-simulator' +import { ethers } from 'ethers' async function getWeb3 () { const remixSimulatorProvider = new Provider({ fork: 'cancun' }) await remixSimulatorProvider.init() await remixSimulatorProvider.Accounts.resetAccounts() - const web3 = new Web3(remixSimulatorProvider) - extendWeb3(web3) - return web3 + const provider = new ethers.BrowserProvider(remixSimulatorProvider as any) + extendProvider(provider) + return provider } -async function sendTx (web3, from, to, value, data, cb) { +async function sendTx (provider, from, to, value, data, cb) { try { cb = cb || (() => {}) - const receipt = await web3.eth.sendTransaction({ + const signer = await provider.getSigner() + const receipt = await signer.sendTransaction({ from: createAddressFromPrivateKey(from.privateKey).toString(), to, value, data, gas: 7000000 - }, null, { checkRevertBeforeSending: false, ignoreGasPricing: true }) - cb(null, receipt.transactionHash) - return receipt.transactionHash + }) + cb(null, receipt.hash) + return receipt.hash } catch (e) { cb(e) } diff --git a/libs/remix-lib/package.json b/libs/remix-lib/package.json index d7a11948995..f57a6be7442 100644 --- a/libs/remix-lib/package.json +++ b/libs/remix-lib/package.json @@ -29,9 +29,7 @@ "rlp": "^3.0.0", "solc": "0.8.26", "string-similarity": "^4.0.4", - "viem": "2.22.3", - "web3": "^4.1.1", - "web3-validator": "^2.0.0" + "viem": "2.22.3" }, "devDependencies": { "@babel/core": "^7.4.5", diff --git a/libs/remix-lib/src/execution/logsManager.ts b/libs/remix-lib/src/execution/logsManager.ts index 0beefd5b642..a694d3b0788 100644 --- a/libs/remix-lib/src/execution/logsManager.ts +++ b/libs/remix-lib/src/execution/logsManager.ts @@ -20,7 +20,7 @@ export class LogsManager { checkBlock (blockNumber, block, web3) { eachOf(block.transactions, (tx: any, i, next) => { const txHash = bytesToHex(tx.hash()) - web3.eth.getTransactionReceipt(txHash, (_error, receipt) => { + web3.getTransactionReceipt(txHash, (_error, receipt) => { if (!receipt) return next() for (const log of receipt.logs) { this.oldLogs.push({ type: 'block', blockNumber, block, tx, log, txNumber: i, receipt }) diff --git a/libs/remix-lib/src/execution/txListener.ts b/libs/remix-lib/src/execution/txListener.ts index 78915bb13dd..c6bfcf63ff4 100644 --- a/libs/remix-lib/src/execution/txListener.ts +++ b/libs/remix-lib/src/execution/txListener.ts @@ -94,7 +94,7 @@ export class TxListener { // in web3 mode && listen remix txs only if (!this._isListening) return // we don't listen if (this._loopId) return // we seems to already listen on a "web3" network - this.executionContext.web3().eth.getTransaction(txResult.transactionHash).then(async tx=>{ + this.executionContext.web3().getTransaction(txResult.transactionHash).then(async tx=>{ let execResult if (this.executionContext.isVM()) { execResult = await this.executionContext.web3().remix.getExecutionResultFromSimulator(txResult.transactionHash) @@ -203,7 +203,7 @@ export class TxListener { async _manageBlock (blockNumber) { try { - const result = await this.executionContext.web3().eth.getBlock(blockNumber, true) + const result = await this.executionContext.web3().getBlock(blockNumber, true) return await this._newBlock(Object.assign({ type: 'web3' }, result)) } catch (e) {} } @@ -269,7 +269,7 @@ export class TxListener { // contract creation / resolve using the creation bytes code // if web3: we have to call getTransactionReceipt to get the created address // if VM: created address already included - const code = tx.input + const code = tx.data contract = this._tryResolveContract(code, contracts, true) if (contract) { const address = receipt.contractAddress @@ -285,7 +285,7 @@ export class TxListener { // first check known contract, resolve against the `runtimeBytecode` if not known contract = this._resolvedContracts[tx.to] if (!contract) { - this.executionContext.web3().eth.getCode(tx.to).then(code=>{ + this.executionContext.web3().getCode(tx.to).then(code=>{ if (code) { const contract = this._tryResolveContract(code, contracts, false) if (contract) { @@ -312,7 +312,8 @@ export class TxListener { return } const abi = contract.object.abi - const inputData = tx.input.replace('0x', '') + const txInput = tx.data || tx.input + const inputData = txInput.replace('0x', '') if (!isCtor) { const methodIdentifiers = contract.object.evm.methodIdentifiers for (const fn in methodIdentifiers) { diff --git a/libs/remix-lib/src/execution/txRunnerVM.ts b/libs/remix-lib/src/execution/txRunnerVM.ts index c3a41dce8f1..a6c8cdcc43b 100644 --- a/libs/remix-lib/src/execution/txRunnerVM.ts +++ b/libs/remix-lib/src/execution/txRunnerVM.ts @@ -206,7 +206,7 @@ export class TxRunnerVM { runTx(vm, { tx, skipNonce: true, skipBalance: false }).then((result: RunTxResult) => { callback(null, { result, - transactionHash: bytesToHex(Buffer.from(tx.hash())), + transactionHash: bytesToHex((tx.hash())), block, tx }) @@ -221,7 +221,7 @@ export class TxRunnerVM { const result: RunTxResult = results.results[0] callback(null, { result, - transactionHash: tx ? bytesToHex(Buffer.from(tx.hash())) : null, + transactionHash: tx ? bytesToHex(tx.hash()) : null, block, tx }) diff --git a/libs/remix-lib/src/execution/txRunnerWeb3.ts b/libs/remix-lib/src/execution/txRunnerWeb3.ts index 0e44cab042c..a35bcb2b06f 100644 --- a/libs/remix-lib/src/execution/txRunnerWeb3.ts +++ b/libs/remix-lib/src/execution/txRunnerWeb3.ts @@ -1,14 +1,12 @@ 'use strict' import { EventManager } from '../eventManager' import type { Transaction as InternalTransaction } from './txRunner' -import { Web3 } from 'web3' -import { BrowserProvider } from 'ethers' +import { BrowserProvider, getAddress, parseUnits } from 'ethers' import { normalizeHexAddress } from '../helpers/uiHelper' import { aaSupportedNetworks, aaLocalStorageKey, getPimlicoBundlerURL, aaDeterminiticProxyAddress } from '../helpers/aaConstants' -import { toBigInt, toHex, toChecksumAddress } from 'web3-utils' import { randomBytes } from 'crypto' import "viem/window" -import { custom, http, createWalletClient, createPublicClient, encodePacked, getContractAddress } from "viem" +import { custom, http, createWalletClient, createPublicClient, encodePacked, getContractAddress, toHex } from "viem" import * as chains from "viem/chains" import { entryPoint07Address } from "viem/account-abstraction" const { createSmartAccountClient } = require("permissionless") @@ -18,7 +16,7 @@ const { createPimlicoClient } = require("permissionless/clients/pimlico") export class TxRunnerWeb3 { event _api - getWeb3: () => Web3 + getWeb3: () => BrowserProvider currentblockGasLimit: () => number constructor (api, getWeb3, currentblockGasLimit) { @@ -38,11 +36,11 @@ export class TxRunnerWeb3 { } if (txFee) { if (txFee.baseFeePerGas) { - tx.maxPriorityFeePerGas = toHex(BigInt(this.getWeb3().utils.toWei(txFee.maxPriorityFee, 'gwei'))) - tx.maxFeePerGas = toHex(BigInt(this.getWeb3().utils.toWei(txFee.maxFee, 'gwei'))) + tx.maxPriorityFeePerGas = toHex(BigInt(parseUnits(txFee.maxPriorityFee, 'gwei'))) + tx.maxFeePerGas = toHex(BigInt(parseUnits(txFee.maxFee, 'gwei'))) tx.type = '0x2' } else { - tx.gasPrice = toHex(BigInt(this.getWeb3().utils.toWei(txFee.gasPrice, 'gwei'))) + tx.gasPrice = toHex(BigInt(parseUnits(txFee.gasPrice, 'gwei'))) // tx.type = '0x1' } if (tx.authorizationList) { @@ -70,7 +68,7 @@ export class TxRunnerWeb3 { if (receipt.logs && receipt.logs.length) { receipt.logs.map((log) => { if (log.topics[0] === '0xa1fb700aaee2ae4a2ff6f91ce7eba292f89c2f5488b8ec4c5c5c8150692595c3') { - (receipt as any).contractAddress = toChecksumAddress(normalizeHexAddress(toHex(log.topics[2]))) + (receipt as any).contractAddress = getAddress(normalizeHexAddress(toHex(log.topics[2]))) } }) } @@ -84,7 +82,7 @@ export class TxRunnerWeb3 { resolve({ receipt, tx, - transactionHash: receipt ? receipt['transactionHash'] : null + transactionHash: receipt ? receipt['hash'] : null }) }) } @@ -98,14 +96,14 @@ export class TxRunnerWeb3 { promptCb( async (value) => { try { - const res = await (this.getWeb3() as any).eth.personal.sendTransaction({ ...tx, value }, { checkRevertBeforeSending: false, ignoreGasPricing: true }) - cb(null, res.transactionHash, isCreation, false, null) + const res = await (await this.getWeb3().getSigner()).sendTransaction({ ...tx, value }) + cb(null, res.hash, isCreation, false, null) } catch (e) { 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, isCreation, false, null) + if (e.receipt) cb(null, e.receipt.hash, isCreation, false, null) else cb(e, null, isCreation, false, null) } }, @@ -119,8 +117,8 @@ export class TxRunnerWeb3 { const { txHash, contractAddress } = await this.sendUserOp(tx, network.id) cb(null, txHash, isCreation, true, contractAddress) } else { - const res = await this.getWeb3().eth.sendTransaction(tx, null, { checkRevertBeforeSending: false, ignoreGasPricing: true }) - cb(null, res.transactionHash, isCreation, false, null) + const res = await (await this.getWeb3().getSigner(tx.from)).sendTransaction(tx) + cb(null, res.hash, isCreation, false, null) } } catch (e) { if (!e.message) e.message = '' @@ -130,7 +128,7 @@ export class TxRunnerWeb3 { 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. - if (e.receipt) cb(null, e.receipt.transactionHash, isCreation, false, null) + if (e.receipt) cb(null, e.receipt.hash, isCreation, false, null) else cb(e, null, isCreation, false, null) } } @@ -147,7 +145,7 @@ export class TxRunnerWeb3 { if (this._api && this._api.isVM()) { (this.getWeb3() as any).remix.registerCallId(timestamp) } - this.getWeb3().eth.call(tx) + this.getWeb3().call(tx) .then((result: any) => callback(null, { result: result })) @@ -165,13 +163,13 @@ export class TxRunnerWeb3 { // the sending stack (web3.js / metamask need to have the type defined) // this is to avoid the following issue: https://github.com/MetaMask/metamask-extension/issues/11824 txCopy.type = '0x2' - txCopy.maxFeePerGas = Math.ceil(Number((toBigInt(network.lastBlock.baseFeePerGas) + toBigInt(network.lastBlock.baseFeePerGas) / BigInt(3)).toString())) + txCopy.maxFeePerGas = Math.ceil(Number((BigInt(network.lastBlock.baseFeePerGas) + BigInt(network.lastBlock.baseFeePerGas) / BigInt(3)).toString())) } else { txCopy.type = '0x1' txCopy.gasPrice = undefined } } - const ethersProvider = new BrowserProvider(this.getWeb3().currentProvider as any) + const ethersProvider = this.getWeb3() ethersProvider.estimateGas(txCopy) .then(gasEstimationBigInt => { gasEstimationForceSend(null, () => { @@ -185,16 +183,16 @@ export class TxRunnerWeb3 { } if (gasLimit === '0x0') { - tx['gas'] = gasEstimation + tx['gasLimit'] = gasEstimation } else { - tx['gas'] = gasLimit + tx['gasLimit'] = gasLimit } if (this._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')) { return this._executeTx(tx, network, null, this._api, promptCb, callback) } - confirmCb(network, tx, tx['gas'], (txFee) => { + confirmCb(network, tx, tx['gasLimit'], (txFee) => { return this._executeTx(tx, network, txFee, this._api, promptCb, callback) }, (error) => { callback(error) @@ -218,13 +216,13 @@ export class TxRunnerWeb3 { err = network.name === 'VM' ? null : err // just send the tx if "VM" gasEstimationForceSend(err, () => { const defaultGasLimit = 3000000 - tx['gas'] = gasLimit === '0x0' ? '0x' + defaultGasLimit.toString(16) : gasLimit + tx['gasLimit'] = gasLimit === '0x0' ? '0x' + defaultGasLimit.toString(16) : gasLimit if (this._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')) { return this._executeTx(tx, network, null, this._api, promptCb, callback) } - confirmCb(network, tx, tx['gas'], (txFee) => { + confirmCb(network, tx, tx['gasLimit'], (txFee) => { return this._executeTx(tx, network, txFee, this._api, promptCb, callback) }, (error) => { callback(error) @@ -323,9 +321,9 @@ export class TxRunnerWeb3 { } } -async function tryTillReceiptAvailable (txhash: string, web3: Web3) { +async function tryTillReceiptAvailable (txhash: string, provider: BrowserProvider) { try { - const receipt = await web3.eth.getTransactionReceipt(txhash) + const receipt = await provider.getTransactionReceipt(txhash) if (receipt) { if (!receipt.to && !receipt.contractAddress) { // this is a contract creation and the receipt doesn't contain a contract address. we have to keep polling... @@ -335,15 +333,15 @@ async function tryTillReceiptAvailable (txhash: string, web3: Web3) { } } catch (e) {} await pause() - return await tryTillReceiptAvailable(txhash, web3) + return await tryTillReceiptAvailable(txhash, provider) } -async function tryTillTxAvailable (txhash: string, web3: Web3) { +async function tryTillTxAvailable (txhash: string, provider: BrowserProvider) { try { - const tx = await web3.eth.getTransaction(txhash) + const tx = await provider.getTransaction(txhash) if (tx && tx.blockHash) return tx } catch (e) {} - return await tryTillTxAvailable(txhash, web3) + return await tryTillTxAvailable(txhash, provider) } async function pause () { return new Promise((resolve, reject) => { setTimeout(resolve, 500) }) } diff --git a/libs/remix-lib/src/execution/typeConversion.ts b/libs/remix-lib/src/execution/typeConversion.ts index b960cae1733..f77e2d07707 100644 --- a/libs/remix-lib/src/execution/typeConversion.ts +++ b/libs/remix-lib/src/execution/typeConversion.ts @@ -1,12 +1,11 @@ 'use strict' import { BN } from 'bn.js' import { bytesToHex } from '@ethereumjs/util' -import { isBigInt } from 'web3-validator' export function toInt (h) { if (h.indexOf && h.indexOf('0x') === 0) { return (new BN(h.replace('0x', ''), 16)).toString(10) - } else if ((h.constructor && h.constructor.name === 'BigNumber') || BN.isBN(h) || isBigInt(h)) { + } else if ((h.constructor && h.constructor.name === 'BigNumber') || BN.isBN(h) || (typeof h === 'bigint')) { return h.toString(10) } return h @@ -22,7 +21,7 @@ function convertToString (v) { ret.push(convertToString(v[k])) } return ret - } else if (BN.isBN(v) || (v.constructor && v.constructor.name === 'BigNumber') || isBigInt(v)) { + } else if (BN.isBN(v) || (v.constructor && v.constructor.name === 'BigNumber') || (typeof v === 'bigint')) { return v.toString(10) } else if (v._isBigNumber) { return toInt(v._hex) diff --git a/libs/remix-lib/src/helpers/txResultHelper.ts b/libs/remix-lib/src/helpers/txResultHelper.ts index 3b171dbf057..d19519f93b3 100644 --- a/libs/remix-lib/src/helpers/txResultHelper.ts +++ b/libs/remix-lib/src/helpers/txResultHelper.ts @@ -2,7 +2,6 @@ import { bytesToHex } from '@ethereumjs/util' import { isHexString } from 'ethjs-util' import { BN } from 'bn.js' -import { isBigInt } from 'web3-validator' function convertToPrefixedHex (input) { if (input === undefined || input === null || isHexString(input)) { @@ -10,7 +9,7 @@ function convertToPrefixedHex (input) { } if ((input.constructor && input.constructor.name === 'BigNumber') || BN.isBN(input) - || isBigInt(input) + || (typeof input === 'bigint') || typeof input === 'number') { return '0x' + input.toString(16) } diff --git a/libs/remix-lib/src/init.ts b/libs/remix-lib/src/init.ts deleted file mode 100644 index 128702cd01e..00000000000 --- a/libs/remix-lib/src/init.ts +++ /dev/null @@ -1,47 +0,0 @@ -'use strict' -import { Web3, Web3PluginBase } from 'web3' -import { toNumber } from 'web3-utils' - -export function extendWeb3 (web3) { - if (!web3.debug){ - web3.registerPlugin(new Web3DebugPlugin()) - } -} - -export function loadWeb3 (url = 'http://localhost:8545') { - const web3 = new Web3() - web3.setProvider(new Web3.providers.HttpProvider(url)) - extendWeb3(web3) - return web3 -} - -class Web3DebugPlugin extends Web3PluginBase { - public pluginNamespace = 'debug' - - public preimage(key, cb) { - this.requestManager.send({ - method: 'debug_preimage', - params: [key] - }) - .then(result => cb(null, result)) - .catch(error => cb(error)) - } - - public traceTransaction(txHash, options, cb) { - this.requestManager.send({ - method: 'debug_traceTransaction', - params: [txHash, options] - }) - .then(result => cb(null, result)) - .catch(error => cb(error)) - } - - public storageRangeAt(txBlockHash, txIndex, address, start, maxSize, cb) { - this.requestManager.send({ - method: 'debug_storageRangeAt', - params: [txBlockHash, toNumber(txIndex), address, start, maxSize] - }) - .then(result => cb(null, result)) - .catch(error => cb(error)) - } -} diff --git a/libs/remix-lib/src/util.ts b/libs/remix-lib/src/util.ts index 0b57f26a6a1..d731bebc7f8 100644 --- a/libs/remix-lib/src/util.ts +++ b/libs/remix-lib/src/util.ts @@ -3,7 +3,6 @@ import { hash } from '@remix-project/remix-lib' import { setLengthLeft, toBytes, addHexPrefix } from '@ethereumjs/util' import stringSimilarity from 'string-similarity' import { BN } from 'bn.js' -import { isBigInt } from 'web3-validator' /* contains misc util: @TODO should be split @@ -174,7 +173,7 @@ export function buildCallPath (index, rootCall) { */ // eslint-disable-next-line camelcase export function sha3_256 (value) { - if ((value.constructor && value.constructor.name === 'BigNumber') || BN.isBN(value) || isBigInt(value)) { + if ((value.constructor && value.constructor.name === 'BigNumber') || BN.isBN(value) || (typeof value === 'bigint')) { value = value.toString(16) } if (typeof value === 'number') { diff --git a/libs/remix-lib/test/init.ts b/libs/remix-lib/test/init.ts index 7f844e234f9..e20c6a269d8 100644 --- a/libs/remix-lib/test/init.ts +++ b/libs/remix-lib/test/init.ts @@ -1,11 +1,11 @@ const init = { overrideWeb3: function (web3, web3Override) { - web3.eth.getCode = web3Override.getCode + web3.getCode = web3Override.getCode web3.debug.traceTransaction = web3Override.traceTransaction web3.debug.storageRangeAt = web3Override.storageRangeAt - web3.eth.getTransaction = web3Override.getTransaction - web3.eth.getTransactionFromBlock = web3Override.getTransactionFromBlock - web3.eth.getBlockNumber = web3Override.getBlockNumber + web3.getTransaction = web3Override.getTransaction + web3.getTransactionFromBlock = web3Override.getTransactionFromBlock + web3.getBlockNumber = web3Override.getBlockNumber }, readFile: function (filename, callback) { diff --git a/libs/remix-simulator/package.json b/libs/remix-simulator/package.json index 80986a7dd03..38d31db7ab3 100644 --- a/libs/remix-simulator/package.json +++ b/libs/remix-simulator/package.json @@ -39,9 +39,7 @@ "rlp": "^3.0.0", "string-similarity": "^4.0.4", "time-stamp": "^2.0.0", - "tslib": "^2.3.0", - "web3": "^4.1.1", - "web3-utils": "^4.0.5" + "tslib": "^2.3.0" }, "devDependencies": { "@babel/core": "^7.4.5", diff --git a/libs/remix-simulator/src/VmProxy.ts b/libs/remix-simulator/src/VmProxy.ts index 89fbb329f6a..b0f12af6e61 100644 --- a/libs/remix-simulator/src/VmProxy.ts +++ b/libs/remix-simulator/src/VmProxy.ts @@ -3,9 +3,7 @@ import { ConsoleLogs, hash, util, helpers } from '@remix-project/remix-lib' const { toHexPaddedString, formatMemory, padHexToEven } = util const { normalizeHexAddress } = helpers.ui import { toChecksumAddress, bytesToHex, toBytes, createAddressFromString, PrefixedHexString } from '@ethereumjs/util' -import utils, { toBigInt } from 'web3-utils' -import { isBigInt } from 'web3-validator' -import { Interface, zeroPadValue } from 'ethers' +import { Interface, zeroPadValue, keccak256, hexlify, toUtf8String, toUtf8Bytes, formatEther, parseEther, isAddress, formatUnits, parseUnits } from 'ethers' import { VMContext } from './vm-context' import type { StateManagerInterface } from '@ethereumjs/common' import type { InterpreterStep } from '@ethereumjs/evm' @@ -39,7 +37,6 @@ export class VmProxy { toWei toBigNumber isAddress - utils txsMapBlock blocks stateCopy: StateManagerInterface @@ -61,14 +58,7 @@ export class VmProxy { this.processingIndex = null this.previousDepth = 0 this.incr = 0 - this.eth = {} this.debug = {} - this.eth.getCode = (address, cb) => this.getCode(address, cb) - this.eth.getTransaction = (txHash, cb) => this.getTransaction(txHash, cb) - this.eth.getTransactionReceipt = (txHash, cb) => this.getTransactionReceipt(txHash, cb) - this.eth.getTransactionFromBlock = (blockNumber, txIndex, cb) => this.getTransactionFromBlock(blockNumber, txIndex, cb) - this.eth.getBlockNumber = (cb) => this.getBlockNumber(cb) - this.eth.getStorageAt = (address: string, position: string, blockNumber: string, cb) => this.getStorageAt(address, position, blockNumber, cb) this.debug.traceTransaction = (txHash, options, cb) => this.traceTransaction(txHash, options, cb) this.debug.storageRangeAt = (blockNumber, txIndex, address, start, maxLength, cb) => this.storageRangeAt(blockNumber, txIndex, address, start, maxLength, cb) this.debug.preimage = (hashedKey, cb) => this.preimage(hashedKey, cb) @@ -77,16 +67,14 @@ export class VmProxy { this.storageCache = {} this.sha3Preimages = {} // util - this.sha3 = (...args) => utils.sha3.apply(this, args) - this.toHex = (...args) => utils.toHex.apply(this, args) - this.toAscii = (...args) => utils.toAscii.apply(this, args) - this.fromAscii = (...args) => utils.fromAscii.apply(this, args) - this.fromDecimal = (...args) => utils.fromDecimal.apply(this, args) - this.fromWei = (...args) => utils.fromWei.apply(this, args) - this.toWei = (...args) => utils.toWei.apply(this, args) - this.toBigNumber = (...args) => toBigInt.apply(this, args) - this.isAddress = (...args) => utils.isAddress.apply(this, args) - this.utils = utils + this.sha3 = (...args) => keccak256.apply(this, args) + this.toHex = (...args) => hexlify.apply(this, args) + this.toAscii = (...args) => toUtf8String.apply(this, args) + this.fromAscii = (...args) => toUtf8Bytes.apply(this, args) + this.fromWei = (...args) => formatUnits.apply(this, args) + this.toWei = (...args) => parseUnits.apply(this, args) + this.toBigNumber = (...args) => BigInt.apply(this, args) + this.isAddress = (...args) => isAddress.apply(this, args) this.txsMapBlock = {} this.blocks = {} this.lastMemoryUpdate = [] @@ -285,7 +273,7 @@ export class VmProxy { const consoleArgs = iface.decodeFunctionData(functionDesc, payload) const consoleArgsMapped = consoleArgs.map((value) => { // Copied from: https://github.com/web3/web3.js/blob/e68194bdc590d811d4bf66dde12f99659861a110/packages/web3-utils/src/utils.js#L48C10-L48C10 - if (value && ((value.constructor && value.constructor.name === 'BigNumber') || isBigInt(value))) { + if (value && ((value.constructor && value.constructor.name === 'BigNumber') || typeof value === 'bigint')) { return value.toString() } return value @@ -432,9 +420,9 @@ export class VmProxy { getSha3Input (stack, memory) { const memoryStart = toHexPaddedString(stack[stack.length - 1]) const memoryLength = toHexPaddedString(stack[stack.length - 2]) - const memStartDec = toBigInt(memoryStart).toString(10) + const memStartDec = BigInt(memoryStart).toString(10) const memoryStartInt = parseInt(memStartDec) * 2 - const memLengthDec = toBigInt(memoryLength).toString(10) + const memLengthDec = BigInt(memoryLength).toString(10) const memoryLengthInt = parseInt(memLengthDec.toString()) * 2 let i = Math.floor(memoryStartInt / 32) diff --git a/libs/remix-simulator/src/index.ts b/libs/remix-simulator/src/index.ts index 35835a8ee26..a32997a60ac 100644 --- a/libs/remix-simulator/src/index.ts +++ b/libs/remix-simulator/src/index.ts @@ -1,2 +1,2 @@ -export { Provider, extend, JSONRPCRequestPayload, JSONRPCResponsePayload, JSONRPCResponseCallback } from './provider' +export { Provider, extendProvider, JSONRPCRequestPayload, JSONRPCResponsePayload, JSONRPCResponseCallback } from './provider' export { Server } from './server' diff --git a/libs/remix-simulator/src/methods/accounts.ts b/libs/remix-simulator/src/methods/accounts.ts index 13497d54bd4..bfa9f4465b7 100644 --- a/libs/remix-simulator/src/methods/accounts.ts +++ b/libs/remix-simulator/src/methods/accounts.ts @@ -1,8 +1,7 @@ import { signTypedData, SignTypedDataVersion, TypedMessage, MessageTypes } from '@metamask/eth-sig-util' -import { privateToAddress, toChecksumAddress, isValidPrivate, createAddressFromString, toBytes, bytesToHex, Account } from '@ethereumjs/util' +import { privateToAddress, toChecksumAddress, isValidPrivate, createAddressFromString, toBytes, bytesToHex, Account, intToHex } from '@ethereumjs/util' import type { PrefixedHexString } from '@ethereumjs/util' -import { privateKeyToAccount } from 'web3-eth-accounts' -import { toBigInt, toHex } from 'web3-utils' +import { ethers } from 'ethers' import * as crypto from 'crypto' type AccountType = { @@ -56,10 +55,10 @@ export class Web3Accounts { const stateManager = this.vmContext.vm().stateManager const account = await stateManager.getAccount(createAddressFromString(addressStr)) if (!account) { - const account = new Account(BigInt(0), toBigInt(balance || '0xf00000000000000001')) + const account = new Account(BigInt(0), BigInt(balance || '0xf00000000000000001')) await stateManager.putAccount(createAddressFromString(addressStr), account) } else { - account.balance = toBigInt(balance || '0xf00000000000000001') + account.balance = BigInt(balance || '0xf00000000000000001') await stateManager.putAccount(createAddressFromString(addressStr), account) } } catch (e) { @@ -106,9 +105,9 @@ export class Web3Accounts { eth_getBalance (payload, cb) { const address = payload.params[0] this.vmContext.vm().stateManager.getAccount(createAddressFromString(address)).then((account) => { - if (!account) return cb(null, toBigInt(0).toString(10)) - if (!account.balance) return cb(null, toBigInt(0).toString(10)) - cb(null, toBigInt(account.balance).toString(10)) + if (!account) return cb(null, BigInt(0).toString(10)) + if (!account.balance) return cb(null, BigInt(0).toString(10)) + cb(null, BigInt(account.balance).toString(10)) }).catch((error) => { cb(error) }) @@ -122,16 +121,16 @@ export class Web3Accounts { if (!privateKey) { return cb(new Error('unknown account')) } - const account = privateKeyToAccount(privateKey as string) + const account = new ethers.Wallet(privateKey as string) - const data = account.sign(message) - - cb(null, data.signature) + account.signMessage(message).then((signature) => { + cb(null, signature) + }) } eth_chainId (_payload, cb) { if (!this.options.chainId) return cb(null, '0x539') // 0x539 is hex of 1337 - const id = (typeof this.options.chainId === 'number') ? toHex(this.options.chainId) : this.options.chainId + const id = (typeof this.options.chainId === 'number') ? intToHex(this.options.chainId) : this.options.chainId return cb(null, id) } diff --git a/libs/remix-simulator/src/methods/blocks.ts b/libs/remix-simulator/src/methods/blocks.ts index b0abf5ddf5b..d945c4ee43b 100644 --- a/libs/remix-simulator/src/methods/blocks.ts +++ b/libs/remix-simulator/src/methods/blocks.ts @@ -1,4 +1,4 @@ -import { toHex } from 'web3-utils' +import { hexlify } from 'ethers' import { VMContext } from '../vm-context' import { bigIntToHex, bytesToHex } from '@ethereumjs/util' @@ -116,7 +116,7 @@ export class Blocks { blockHash: bytesToHex(block.hash()), blockNumber: bigIntToHex(block.header.number), from: receipt.from, - gas: toHex(receipt.gas), + gas: hexlify(receipt.gas), chainId: '0xd05', gasPrice: '0x4a817c800', // 20000000000 hash: receipt.transactionHash, @@ -191,7 +191,7 @@ export class Blocks { } eth_getStorageAt (payload, cb) { - return this.vmContext.web3().eth.getStorageAt( + return this.vmContext.web3().getStorageAt( payload.params[0], payload.params[1], payload.params[2], diff --git a/libs/remix-simulator/src/methods/misc.ts b/libs/remix-simulator/src/methods/misc.ts index e6f8a3716a9..ca82ac599cb 100644 --- a/libs/remix-simulator/src/methods/misc.ts +++ b/libs/remix-simulator/src/methods/misc.ts @@ -1,4 +1,4 @@ -import { sha3 } from 'web3-utils' +import { keccak256 } from 'ethers' const version = require('../../package.json').version export function methods () { @@ -39,7 +39,7 @@ export function eth_hashrate (payload, cb) { export function web3_sha3 (payload, cb) { const str: string = payload.params[0] - cb(null, sha3(str)) + cb(null, keccak256(str)) } export function eth_getCompilers (payload, cb) { diff --git a/libs/remix-simulator/src/methods/transactions.ts b/libs/remix-simulator/src/methods/transactions.ts index 56a494de1d3..c8b2196b21b 100644 --- a/libs/remix-simulator/src/methods/transactions.ts +++ b/libs/remix-simulator/src/methods/transactions.ts @@ -1,8 +1,7 @@ -import { toHex, toNumber, toBigInt } from 'web3-utils' import { toChecksumAddress, bigIntToHex, bytesToHex, createAddressFromString } from '@ethereumjs/util' import { processTx } from './txProcess' import { execution } from '@remix-project/remix-lib' -import { AbiCoder } from 'ethers' +import { AbiCoder, toNumber } from 'ethers' import { VMexecutionResult } from '@remix-project/remix-lib' import { VMContext } from '../vm-context' import { Log, EVMError } from '@ethereumjs/evm' @@ -146,7 +145,7 @@ export class Transactions { } eth_getTransactionReceipt (payload, cb) { - this.vmContext.web3().eth.getTransactionReceipt(payload.params[0], (error, receipt) => { + this.vmContext.web3().getTransactionReceipt(payload.params[0], (error, receipt) => { if (error) { return cb(error) } @@ -218,7 +217,7 @@ export class Transactions { eth_getCode (payload, cb) { const address = payload.params[0] - this.vmContext.web3().eth.getCode(address, (error, result) => { + this.vmContext.web3().getCode(address, (error, result) => { if (error) { console.dir('error getting code') console.dir(error) @@ -297,7 +296,7 @@ export class Transactions { const address = payload.params[0] this.vmContext.vm().stateManager.getAccount(createAddressFromString(address)).then((account) => { - const nonce = toBigInt(account.nonce).toString(10) + const nonce = BigInt(account.nonce).toString(10) cb(null, nonce) }).catch((error) => { cb(error) @@ -307,7 +306,7 @@ export class Transactions { eth_getTransactionByHash (payload, cb) { const address = payload.params[0] - this.vmContext.web3().eth.getTransactionReceipt(address, (error, receipt) => { + this.vmContext.web3().getTransactionReceipt(address, (error, receipt) => { if (error) { return cb(error) } @@ -319,7 +318,7 @@ export class Transactions { blockHash: bytesToHex(txBlock.hash()), blockNumber: bigIntToHex(txBlock.header.number), from: receipt.from, - gas: toHex(BigInt(receipt.gas)), + gas: bigIntToHex(BigInt(receipt.gas)), chainId: '0xd05', // 'gasPrice': '2000000000000', // 0x123 gasPrice: '0x4a817c800', // 20000000000 @@ -355,7 +354,7 @@ export class Transactions { const txBlock = this.vmContext.blocks[payload.params[0]] const txHash = bytesToHex(txBlock.transactions[toNumber(txIndex) as number].hash()) - this.vmContext.web3().eth.getTransactionReceipt(txHash, (error, receipt) => { + this.vmContext.web3().getTransactionReceipt(txHash, (error, receipt) => { if (error) { return cb(error) } @@ -367,7 +366,7 @@ export class Transactions { blockHash: bytesToHex(txBlock.hash()), blockNumber: bigIntToHex(txBlock.header.number), from: receipt.from, - gas: toHex(BigInt(receipt.gas)), + gas: bigIntToHex(BigInt(receipt.gas)), chainId: '0xd05', // 'gasPrice': '2000000000000', // 0x123 gasPrice: '0x4a817c800', // 20000000000 @@ -400,7 +399,7 @@ export class Transactions { const txBlock = this.vmContext.blocks[payload.params[0]] const txHash = bytesToHex(txBlock.transactions[toNumber(txIndex) as number].hash()) - this.vmContext.web3().eth.getTransactionReceipt(txHash, (error, receipt) => { + this.vmContext.web3().getTransactionReceipt(txHash, (error, receipt) => { if (error) { return cb(error) } @@ -412,7 +411,7 @@ export class Transactions { blockHash: bytesToHex(txBlock.hash()), blockNumber: bigIntToHex(txBlock.header.number), from: receipt.from, - gas: toHex(BigInt(receipt.gas)), + gas: bigIntToHex(BigInt(receipt.gas)), // 'gasPrice': '2000000000000', // 0x123 chainId: '0xd05', gasPrice: '0x4a817c800', // 20000000000 diff --git a/libs/remix-simulator/src/provider.ts b/libs/remix-simulator/src/provider.ts index a7f3fa35c70..a6c3f8ff5a6 100644 --- a/libs/remix-simulator/src/provider.ts +++ b/libs/remix-simulator/src/provider.ts @@ -12,7 +12,6 @@ import { Miner } from './methods/miner' import { Debug } from './methods/debug' import { EVM } from './methods/evm' import { VMContext } from './vm-context' -import { Web3PluginBase } from 'web3' export interface JSONRPCRequestPayload { params: any[]; @@ -158,54 +157,31 @@ export class Provider { } } -export function extend (web3) { - if (!web3.remix){ - web3.registerPlugin(new Web3TestPlugin()) - } -} +export function extendProvider (provider) { // Provider should be ethers.js provider -class Web3TestPlugin extends Web3PluginBase { - public pluginNamespace = 'remix' + if (!provider.remix) provider.remix = {} - public getExecutionResultFromSimulator(transactionHash) { - return this.requestManager.send({ - method: 'eth_getExecutionResultFromSimulator', - params: [transactionHash] - }) + provider.remix.getExecutionResultFromSimulator = async (transactionHash) => { + return await provider.send('eth_getExecutionResultFromSimulator', [transactionHash]) } - public getHHLogsForTx(transactionHash) { - return this.requestManager.send({ - method: 'eth_getHHLogsForTx', - params: [transactionHash] - }) + provider.remix.getHHLogsForTx = async (transactionHash) => { + return await provider.send('eth_getHHLogsForTx',[transactionHash]) } - public getHashFromTagBySimulator(timestamp) { - return this.requestManager.send({ - method: 'eth_getHashFromTagBySimulator', - params: [timestamp] - }) + provider.remix.getHashFromTagBySimulator = async (timestamp) => { + return await provider.send('eth_getHashFromTagBySimulator', [timestamp]) } - public registerCallId(id) { - return this.requestManager.send({ - method: 'eth_registerCallId', - params: [id] - }) + provider.remix.registerCallId = async (id) => { + return await provider.send('eth_registerCallId',[id]) } - public getStateDb() { - return this.requestManager.send({ - method: 'eth_getStateDb', - params: [] - }) + provider.remix.getStateDb = async () => { + return await provider.send('eth_getStateDb', []) } - public getBlocksData() { - return this.requestManager.send({ - method: 'eth_getBlocksData', - params: [] - }) + provider.remix.getBlocksData = async () => { + return await provider.send('eth_getBlocksData',[]) } } diff --git a/libs/remix-simulator/test/accounts.ts b/libs/remix-simulator/test/accounts.ts index d68d84a24c2..49f0fc61efa 100644 --- a/libs/remix-simulator/test/accounts.ts +++ b/libs/remix-simulator/test/accounts.ts @@ -1,48 +1,47 @@ /* global describe, before, it */ -import { Web3, FMT_BYTES, FMT_NUMBER } from 'web3' import { Provider } from '../src/index' -const web3 = new Web3() import * as assert from 'assert' +import { ethers, BrowserProvider } from "ethers" describe('Accounts', () => { + let ethersProvider: BrowserProvider before(async function () { const provider = new Provider() await provider.init() - web3.setProvider(provider as any) + ethersProvider = new ethers.BrowserProvider(provider as any) }) describe('eth_getAccounts', () => { it('should get a list of accounts', async function () { - const accounts: string[] = await web3.eth.getAccounts() + const accounts: string[] = await ethersProvider.send("eth_requestAccounts", []) assert.notEqual(accounts.length, 0) }) }) describe('eth_getBalance', () => { it('should get an account balance', async () => { - const accounts: string[] = await web3.eth.getAccounts() - const balance0: string = await web3.eth.getBalance(accounts[0], undefined, { number: FMT_NUMBER.STR, bytes: FMT_BYTES.HEX }) - const balance1: string = await web3.eth.getBalance(accounts[1], undefined, { number: FMT_NUMBER.STR, bytes: FMT_BYTES.HEX }) - const balance2: string = await web3.eth.getBalance(accounts[2], undefined, { number: FMT_NUMBER.STR, bytes: FMT_BYTES.HEX }) + const accounts: string[] = await ethersProvider.send("eth_requestAccounts", []) + const balance0: bigint = await ethersProvider.getBalance(accounts[0]) + const balance1: bigint = await ethersProvider.getBalance(accounts[1]) + const balance2: bigint = await ethersProvider.getBalance(accounts[2]) - assert.deepEqual(balance0, '100000000000000000000') - assert.deepEqual(balance1, '100000000000000000000') - assert.deepEqual(balance2, '100000000000000000000') + assert.deepEqual(balance0.toString(), '100000000000000000000') + assert.deepEqual(balance1.toString(), '100000000000000000000') + assert.deepEqual(balance2.toString(), '100000000000000000000') }) }) describe('eth_sign', () => { it('should sign payloads', async () => { - const accounts: string[] = await web3.eth.getAccounts() - const signature = await web3.eth.sign(web3.utils.utf8ToHex('Hello world'), accounts[0]) - + const signer = await ethersProvider.getSigner() + const signature: any = await signer._legacySignMessage('Hello world') // _legacySignMessage uses 'eth_sign' internally assert.deepEqual(typeof signature === 'string' ? signature.length : signature.signature.length, 132) }) }) describe('eth_signTypedData', () => { it('should sign typed data', async () => { - const accounts: string[] = await web3.eth.getAccounts() + const accounts: string[] = await ethersProvider.send("eth_requestAccounts", []) const typedData = { domain: { chainId: 1, @@ -68,10 +67,7 @@ describe('Accounts', () => { ], }, }; - const result = await web3.currentProvider.request({ - method: 'eth_signTypedData', - params: [accounts[0], typedData] - }) + const result = await ethersProvider.send('eth_signTypedData', [accounts[0], typedData]) assert.equal(result, '0x248d23de0e23231370db8aa21ad5908ca90c33ae2b8c611b906674bda6b1a8b85813f945c2ea896316e240089029619ab3d801a1b098c199bd462dd8026349da1c') }) }) diff --git a/libs/remix-simulator/test/blocks.ts b/libs/remix-simulator/test/blocks.ts index e5c10003682..b1befb1fce1 100644 --- a/libs/remix-simulator/test/blocks.ts +++ b/libs/remix-simulator/test/blocks.ts @@ -1,40 +1,41 @@ /* global describe, before, it */ -import { Web3 } from 'web3' import { Provider } from '../src/index' -const web3 = new Web3() import * as assert from 'assert' +import { ethers, BrowserProvider } from "ethers" describe('blocks', () => { + let ethersProvider: BrowserProvider + before(async () => { const provider = new Provider({ coinbase: '0x0000000000000000000000000000000000000001' }) await provider.init() - web3.setProvider(provider as any) + ethersProvider = new ethers.BrowserProvider(provider as any) }) describe('eth_getBlockByNumber', () => { it('should get block given its number', async () => { - const block = await web3.eth.getBlock(0) - + const block = await ethersProvider.send( 'eth_getBlockByNumber', [0]) const expectedBlock = { - baseFeePerGas: '1', - difficulty: '0', - extraData: '0x00', - gasLimit: '8000000', - gasUsed: '0', + baseFeePerGas: '0x01', + number: '0x0', hash: block.hash.toString(), - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331', - miner: '0x0000000000000000000000000000000000000001', - nonce: '0', - number: '0', parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x0000000000000000', sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - size: '163591', + logsBloom: '0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331', + transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', stateRoot: '0x0000000000000000000000000000000000000000000000000000000000000000', + miner: '0x0000000000000000000000000000000000000001', + difficulty: '0x0', + totalDifficulty: '0x0', + extraData: '0x00', + size: '0x027f07', + gasLimit: '0x7a1200', + gasUsed: '0x0', timestamp: block.timestamp, - totalDifficulty: '0', - transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', + transactions: [], uncles: [] } @@ -44,82 +45,73 @@ describe('blocks', () => { describe('eth_getGasPrice', () => { it('should get gas price', async () => { - const gasPrice = await web3.eth.getGasPrice() + const { gasPrice } = await ethersProvider.getFeeData() assert.equal(gasPrice, 1) }) }) describe('eth_coinbase', () => { it('should get coinbase', async () => { - const coinbase = await web3.eth.getCoinbase() + const coinbase = await ethersProvider.send("eth_coinbase", []) assert.equal(coinbase, '0x0000000000000000000000000000000000000001') }) }) describe('eth_blockNumber', () => { it('should get current block number', async () => { - const number = await web3.eth.getBlockNumber() + const number = await ethersProvider.getBlockNumber() assert.equal(number, 0) }) }) describe('evm_mine', () => { it('should mine empty block using evm_mine', async function () { - await web3.provider.request({ - method: 'evm_mine', - params: [{ blocks: 3 }], - }) - const number = await web3.eth.getBlockNumber() + await ethersProvider.send( 'evm_mine', [{ blocks: 3 }]) + const number = await ethersProvider.send( 'eth_blockNumber', []) assert.equal(number, 3) }) }) describe('eth_getBlockByHash', () => { it('should get block given its hash', async () => { - const correctBlock = await web3.eth.getBlock(0) - const block = await web3.eth.getBlock(correctBlock.hash) + const correctBlock = await ethersProvider.getBlock(0) + const block = await ethersProvider.getBlock(correctBlock.hash) assert.deepEqual(block, correctBlock) }) }) describe('eth_getBlockTransactionCountByHash', () => { - it('should get block given its hash', async () => { - const correctBlock = await web3.eth.getBlock(0) - const numberTransactions = await web3.eth.getBlockTransactionCount(correctBlock.hash) + it('should get block transactions count given block hash', async () => { + const correctBlock = await ethersProvider.getBlock(0) + const numberTransactions = await ethersProvider.send( 'eth_getBlockTransactionCountByHash', [correctBlock.hash]) assert.deepEqual(numberTransactions, 0) }) }) describe('eth_getBlockTransactionCountByNumber', () => { - it('should get block given its hash', async () => { - const numberTransactions = await web3.eth.getBlockTransactionCount(0) + it('should get block transactions count given block number', async () => { + const numberTransactions = await ethersProvider.send( 'eth_getBlockTransactionCountByNumber', ['0x0']) assert.deepEqual(numberTransactions, 0) }) }) describe('eth_getUncleCountByBlockHash', () => { - it('should get block given its hash', async () => { - const correctBlock = await web3.eth.getBlock(0) - const numberTransactions = await (new Promise((resolve, reject) => { - web3['_requestManager'].send({ method: 'eth_getUncleCountByBlockHash', params: [correctBlock.hash]}) - .then(numberTransactions => resolve(numberTransactions)) - .catch(err => reject(err)) - })) + it('should get block uncles count given its hash', async () => { + const correctBlock = await ethersProvider.send( 'eth_getBlockByNumber', [0]) + const numberTransactions = await ethersProvider.send('eth_getUncleCountByBlockHash', [correctBlock.hash]) + assert.deepEqual(numberTransactions, correctBlock.uncles.length) }) }) describe('eth_getUncleCountByBlockNumber', () => { - it('should get block given its number', async () => { - const correctBlock = await web3.eth.getBlock(0) - const numberTransactions = await (new Promise((resolve, reject) => { - web3['_requestManager'].send({ method: 'eth_getUncleCountByBlockHash', params: [0]}) - .then(numberTransactions => resolve(numberTransactions)) - .catch(err => reject(err)) - })) + it('should get block uncles count given its number', async () => { + const correctBlock = await ethersProvider.send( 'eth_getBlockByNumber', [0]) + const numberTransactions = await ethersProvider.send('eth_getUncleCountByBlockNumber', [0]) + assert.deepEqual(numberTransactions, correctBlock.uncles.length) }) }) @@ -208,26 +200,27 @@ describe('blocks', () => { ] as const const code = '0x608060405234801561001057600080fd5b506040516020806102018339810180604052602081101561003057600080fd5b810190808051906020019092919050505080600081905550506101a9806100586000396000f3fe60806040526004361061005c576000357c0100000000000000000000000000000000000000000000000000000000900480632a1afcd91461006157806360fe47b11461008c5780636d4ce63c146100c7578063ce01e1ec146100f2575b600080fd5b34801561006d57600080fd5b5061007661012d565b6040518082815260200191505060405180910390f35b34801561009857600080fd5b506100c5600480360360208110156100af57600080fd5b8101908080359060200190929190505050610133565b005b3480156100d357600080fd5b506100dc61013d565b6040518082815260200191505060405180910390f35b3480156100fe57600080fd5b5061012b6004803603602081101561011557600080fd5b8101908080359060200190929190505050610146565b005b60005481565b8060008190555050565b60008054905090565b80600081905550807f63a242a632efe33c0e210e04e4173612a17efa4f16aa4890bc7e46caece80de060405160405180910390a25056fea165627a7a7230582063160eb16dc361092a85ced1a773eed0b63738b83bea1e1c51cf066fa90e135d0029' + const signer = await ethersProvider.getSigner(); + const contract = new ethers.ContractFactory(abi, code, signer) - const contract = new web3.eth.Contract(abi) - const accounts = await web3.eth.getAccounts() + const contractInstance = await contract.deploy(100) + const contractAddress = await contractInstance.getAddress() + const contractInteract = new ethers.Contract(contractAddress, abi, signer) - const contractInstance: any = await contract.deploy({ data: code, arguments: [100]}).send({ from: accounts[0], gas: '400000' }) - contractInstance.currentProvider = web3.eth.currentProvider - // contractInstance.givenProvider = web3.eth.currentProvider - - await contractInstance.methods.set(100).send({ from: accounts[0].toLowerCase(), gas: 400000 }) - let storage = await web3.eth.getStorageAt(contractInstance.options.address, 0) + let tx = await contractInteract.set(100) + let storage = await ethersProvider.getStorage(contractAddress, "0x0") assert.deepEqual(storage, '0x64') - await contractInstance.methods.set(200).send({ from: accounts[0].toLowerCase(), gas: 400000 }) - storage = await web3.eth.getStorageAt(contractInstance.options.address, 0) + tx = await contractInteract.set(200) + await tx.wait() + storage = await ethersProvider.getStorage(contractAddress, "0x0") assert.deepEqual(storage, '0xc8') - await contractInstance.methods.set(1).send({ from: accounts[0].toLowerCase(), gas: 400000 }) - storage = await web3.eth.getStorageAt(contractInstance.options.address, 0) + tx = await contractInteract.set(1) + await tx.wait() + storage = await ethersProvider.getStorage(contractAddress, "0x0") assert.deepEqual(storage, '0x01') - }) + }).timeout(10000) }) describe('eth_call', () => { it('should get a value', async () => { @@ -315,13 +308,16 @@ describe('blocks', () => { const code = '0x608060405234801561001057600080fd5b506040516020806102018339810180604052602081101561003057600080fd5b810190808051906020019092919050505080600081905550506101a9806100586000396000f3fe60806040526004361061005c576000357c0100000000000000000000000000000000000000000000000000000000900480632a1afcd91461006157806360fe47b11461008c5780636d4ce63c146100c7578063ce01e1ec146100f2575b600080fd5b34801561006d57600080fd5b5061007661012d565b6040518082815260200191505060405180910390f35b34801561009857600080fd5b506100c5600480360360208110156100af57600080fd5b8101908080359060200190929190505050610133565b005b3480156100d357600080fd5b506100dc61013d565b6040518082815260200191505060405180910390f35b3480156100fe57600080fd5b5061012b6004803603602081101561011557600080fd5b8101908080359060200190929190505050610146565b005b60005481565b8060008190555050565b60008054905090565b80600081905550807f63a242a632efe33c0e210e04e4173612a17efa4f16aa4890bc7e46caece80de060405160405180910390a25056fea165627a7a7230582063160eb16dc361092a85ced1a773eed0b63738b83bea1e1c51cf066fa90e135d0029' - const contract = new web3.eth.Contract(abi) - const accounts = await web3.eth.getAccounts() + const signer = await ethersProvider.getSigner(); + const contract = new ethers.ContractFactory(abi, code, signer) + + const contractInstance = await contract.deploy(100) + + const contractAddress = await contractInstance.getAddress() + const contractInteract = new ethers.Contract(contractAddress, abi, signer) - const contractInstance: any = await contract.deploy({ data: code, arguments: [100]}).send({ from: accounts[0], gas: '400000' }) - contractInstance.currentProvider = web3.eth.currentProvider + let value = await contractInteract.get() - const value = await contractInstance.methods.get().call({ from: accounts[0] }) assert.deepEqual(value, 100) }) }) diff --git a/libs/remix-simulator/test/events.ts b/libs/remix-simulator/test/events.ts index aa0e0b77fcd..df13f2e4ef7 100644 --- a/libs/remix-simulator/test/events.ts +++ b/libs/remix-simulator/test/events.ts @@ -1,47 +1,52 @@ /* global describe, before, it */ -import { Web3 } from 'web3' import { Provider } from '../src/index' -const web3 = new Web3() import * as assert from 'assert' +import { ethers, BrowserProvider } from "ethers" describe('Events', () => { + let ethersProvider: BrowserProvider before(async function () { const provider = new Provider() await provider.init() - web3.setProvider(provider as any) + ethersProvider = new ethers.BrowserProvider(provider as any) }) describe('eth_getLogs', () => { it('should deploy 2 contracts which emit events and retrieve these events using different block ranges', async function () { - const accounts: string[] = await web3.eth.getAccounts() + const accounts: string[] = await ethersProvider.send("eth_requestAccounts", []) + const signer = await ethersProvider.getSigner(0) // deploy the contract "test". - const receiptTest = await web3.eth.sendTransaction({ + const testContractTx = await signer.sendTransaction({ from: accounts[0], - gas: 1000000, + gasLimit: 1000000, data: '0x608060405234801561001057600080fd5b506101ea806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80632801617e14610030575b600080fd5b61004a6004803603810190610045919061015d565b61004c565b005b8073ffffffffffffffffffffffffffffffffffffffff1663a6f9dae1306040518263ffffffff1660e01b81526004016100859190610199565b600060405180830381600087803b15801561009f57600080fd5b505af11580156100b3573d6000803e3d6000fd5b50505050607b7fdcd9c7fa0342f01013bd0bf2bec103a81936162dcebd1f0c38b1d4164c17e0fc60405160405180910390a250565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610118826100ed565b9050919050565b600061012a8261010d565b9050919050565b61013a8161011f565b811461014557600080fd5b50565b60008135905061015781610131565b92915050565b600060208284031215610173576101726100e8565b5b600061018184828501610148565b91505092915050565b6101938161010d565b82525050565b60006020820190506101ae600083018461018a565b9291505056fea2646970667358221220cf5368dd204d44a75752e8ba7512b73d2f54b09f6ca6147e376dd3cf2942b96464736f6c63430008120033' - }, null, { checkRevertBeforeSending: false, ignoreGasPricing: true }) + }) + const receiptTest = await ethersProvider.getTransactionReceipt(testContractTx.hash) // deploy the contract "owner", this will trigger an event. - const receiptOwner = await web3.eth.sendTransaction({ + const ownerContractTx = await signer.sendTransaction({ from: accounts[0], - gas: 1000000, + gasLimit: 1000000, data: '0x608060405234801561001057600080fd5b5061005a6040518060400160405280601b81526020017f4f776e657220636f6e7472616374206465706c6f7965642062793a00000000008152503361011a60201b61015b1760201c565b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a361034d565b6101b882826040516024016101309291906102ee565b6040516020818303038152906040527f319af333000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506101bc60201b60201c565b5050565b6101dd816101d86101e060201b6101f71761020160201b60201c565b60201c565b50565b60006a636f6e736f6c652e6c6f679050600080835160208501845afa505050565b61021360201b61023d17819050919050565b61021b61031e565b565b600081519050919050565b600082825260208201905092915050565b60005b8381101561025757808201518184015260208101905061023c565b60008484015250505050565b6000601f19601f8301169050919050565b600061027f8261021d565b6102898185610228565b9350610299818560208601610239565b6102a281610263565b840191505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102d8826102ad565b9050919050565b6102e8816102cd565b82525050565b600060408201905081810360008301526103088185610274565b905061031760208301846102df565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fd5b6104268061035c6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063893d20e81461003b578063a6f9dae114610059575b600080fd5b610043610075565b6040516100509190610288565b60405180910390f35b610073600480360381019061006e91906102d4565b61009e565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6101f38282604051602401610171929190610391565b6040516020818303038152906040527f319af333000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610218565b5050565b60006a636f6e736f6c652e6c6f679050600080835160208501845afa505050565b61022f816102276101f7610232565b63ffffffff16565b50565b61023d819050919050565b6102456103c1565b565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061027282610247565b9050919050565b61028281610267565b82525050565b600060208201905061029d6000830184610279565b92915050565b600080fd5b6102b181610267565b81146102bc57600080fd5b50565b6000813590506102ce816102a8565b92915050565b6000602082840312156102ea576102e96102a3565b5b60006102f8848285016102bf565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561033b578082015181840152602081019050610320565b60008484015250505050565b6000601f19601f8301169050919050565b600061036382610301565b61036d818561030c565b935061037d81856020860161031d565b61038681610347565b840191505092915050565b600060408201905081810360008301526103ab8185610358565b90506103ba6020830184610279565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fdfea2646970667358221220cb7beb012e0831cc632ed85a11a8652f72efc03360c81beb1fcd842a7782c3cb64736f6c63430008120033' - }, null, { checkRevertBeforeSending: false, ignoreGasPricing: true }) + }) + const receiptOwner = await ethersProvider.getTransactionReceipt(ownerContractTx.hash) + // call function set(Owner p) from "test", this will trigger 2 events, one from each contract. - await web3.eth.sendTransaction({ + await signer.sendTransaction({ from: accounts[0], to: receiptTest.contractAddress, - gas: 1000000, - data: '0x2801617e' + web3.utils.padLeft(receiptOwner.contractAddress, 64).replace('0x', '') - }, null, { checkRevertBeforeSending: false, ignoreGasPricing: true }) + gasLimit: 1000000, + data: '0x2801617e' + ethers.zeroPadValue(receiptOwner.contractAddress, 32).replace('0x', '') + }) - const testLogs = await web3.eth.getPastLogs({ + const testLogs = await ethersProvider.getLogs({ address: receiptTest.contractAddress, fromBlock: 3, toBlock: 'latest', topics: ['0xdcd9c7fa0342f01013bd0bf2bec103a81936162dcebd1f0c38b1d4164c17e0fc'] }) + assert.equal(testLogs.length, 1, '1) testLogs length should be equal to 1') - let ownerLogs = await web3.eth.getPastLogs({ + let ownerLogs = await ethersProvider.getLogs({ address: receiptOwner.contractAddress, fromBlock: 3, toBlock: 'latest', @@ -49,10 +54,9 @@ describe('Events', () => { }) // this should include the event triggered by the "set" transaction call. - assert.equal(testLogs.length, 1, '1) testLogs length should be equal to 1') assert.equal(ownerLogs.length, 1, '2) ownerLogs length should be equal to 1') - ownerLogs = await web3.eth.getPastLogs({ + ownerLogs = await ethersProvider.getLogs({ address: receiptOwner.contractAddress, fromBlock: 2, toBlock: 'latest', @@ -61,7 +65,7 @@ describe('Events', () => { // this should include the event triggered from the ctor. assert.equal(ownerLogs.length, 2, '3) ownerLogs length should be equal to 2') - ownerLogs = await web3.eth.getPastLogs({ + ownerLogs = await ethersProvider.getLogs({ address: receiptOwner.contractAddress, fromBlock: 1, toBlock: 2, @@ -70,7 +74,7 @@ describe('Events', () => { // this should only include the event triggered from the ctor. assert.equal(ownerLogs.length, 1, '4) ownerLogs length should be equal to 1') - ownerLogs = await web3.eth.getPastLogs({ + ownerLogs = await ethersProvider.getLogs({ address: receiptOwner.contractAddress, fromBlock: 1, toBlock: 2, diff --git a/libs/remix-simulator/test/misc.ts b/libs/remix-simulator/test/misc.ts index dbea658c96b..d239fd7b969 100644 --- a/libs/remix-simulator/test/misc.ts +++ b/libs/remix-simulator/test/misc.ts @@ -1,93 +1,84 @@ /* global describe, before, it */ -import { Web3 } from 'web3' import { Provider } from '../src/index' -const web3 = new Web3() import * as assert from 'assert' +import { ethers, BrowserProvider } from "ethers" describe('Misc', () => { + let ethersProvider: BrowserProvider before(async () => { const provider = new Provider() await provider.init() - web3.setProvider(provider as any) + ethersProvider = new ethers.BrowserProvider(provider as any) }) describe('web3_clientVersion', () => { it('should get correct remix simulator version', async () => { - web3['_requestManager'].send({ method: 'web3_clientVersion', params: []}) - .then(version => { - const remixVersion = require('../package.json').version - assert.equal(version, 'Remix Simulator/' + remixVersion) - }) - .catch(err => { throw new Error(err) }) + const version = await ethersProvider.send("web3_clientVersion", []) + const remixVersion = require('../package.json').version + assert.equal(version, 'Remix Simulator/' + remixVersion) }) }) describe('eth_protocolVersion', () => { it('should get protocol version', async () => { - web3['_requestManager'].send({ method: 'eth_protocolVersion', params: []}) - .then(result => assert.equal(result, '0x3f')) - .catch(err => { throw new Error(err) }) + const result = await ethersProvider.send("eth_protocolVersion", []) + assert.equal(result, '0x3f') }) }) describe('eth_syncing', () => { it('should get if is syncing', async () => { - const isSyncing = await web3.eth.isSyncing() + const isSyncing = await ethersProvider.send("eth_syncing", []) assert.equal(isSyncing, false) }) }) describe('eth_mining', () => { it('should get if is mining', async () => { - const isMining = await web3.eth.isMining() + const isMining = await ethersProvider.send("eth_mining", []) assert.equal(isMining, false) }) }) describe('eth_hashrate', () => { it('should get hashrate', async () => { - const hashrate = await web3.eth.getHashrate() + const hashrate = await ethersProvider.send("eth_hashrate", []) assert.equal(hashrate, 0) }) }) describe('web3_sha3', () => { it('should get result of a sha3', async () => { - web3['_requestManager'].send({ method: 'web3_sha3', params: ['0x68656c6c6f20776f726c64']}) - .then(result => assert.equal(result, '0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad')) - .catch(err => { throw new Error(err)} ) + const result = await ethersProvider.send("web3_sha3", ['0x68656c6c6f20776f726c64']) + assert.equal(result, '0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad') }) }) describe('eth_getCompilers', () => { it('should get list of compilers', async () => { - web3['_requestManager'].send({ method: 'eth_getCompilers', params: []}) - .then(result => assert.equal(result, 0)) - .catch(err => { throw new Error(err) }) + const result = await ethersProvider.send("eth_getCompilers", []) + assert.equal(result, 0) }) }) describe('eth_compileSolidity', () => { it('get unsupported result when requesting solidity compiler', async () => { - web3['_requestManager'].send({ method: 'eth_compileSolidity', params: []}) - .then(result => assert.equal(result, 'unsupported')) - .catch(err => { throw new Error(err) }) + const result = await ethersProvider.send("eth_compileSolidity", []) + assert.equal(result, 'unsupported') }) }) describe('eth_compileLLL', () => { it('get unsupported result when requesting LLL compiler', async () => { - web3['_requestManager'].send({ method: 'eth_compileLLL', params: []}) - .then(result => assert.equal(result, 'unsupported')) - .catch(err => { throw new Error(err) }) + const result = await ethersProvider.send("eth_compileLLL", []) + assert.equal(result, 'unsupported') }) }) describe('eth_compileSerpent', () => { it('get unsupported result when requesting serpent compiler', async () => { - web3['_requestManager'].send({ method: 'eth_compileSerpent', params: []}) - .then(result => assert.equal(result, 'unsupported')) - .catch(err => { throw new Error(err)} ) + const result = await ethersProvider.send("eth_compileSerpent", []) + assert.equal(result, 'unsupported') }) }) }) diff --git a/libs/remix-simulator/test/transactions.ts b/libs/remix-simulator/test/transactions.ts index 26504d14b26..dfb632301df 100644 --- a/libs/remix-simulator/test/transactions.ts +++ b/libs/remix-simulator/test/transactions.ts @@ -1,37 +1,35 @@ /* global describe, before, it */ -import { Web3 } from 'web3' import { createFeeMarket1559Tx } from '@ethereumjs/tx' import { Provider } from '../src/index' -const web3 = new Web3() import * as assert from 'assert' -import { bytesToHex, hexToBytes } from 'web3-utils' import type { AddressLike } from '@ethereumjs/util' +import { ethers, BrowserProvider, getBytes, hexlify } from "ethers" describe('Transactions', () => { + let ethersProvider: BrowserProvider before(async function () { const provider = new Provider({ fork: 'shanghai' }) await provider.init() - web3.setProvider(provider as any) + ethersProvider = new ethers.BrowserProvider(provider as any) }) describe('eth_sendTransaction', () => { it('should deploy Storage contract, save a number and retrieve it', async function () { - const accounts: string[] = await web3.eth.getAccounts() - let receipt = await web3.eth.sendTransaction({ + const accounts: string[] = await ethersProvider.send("eth_requestAccounts", []) + const signer = await ethersProvider.getSigner(0) + let receipt = await signer.sendTransaction({ from: accounts[0], - gas: 1000000, + gasLimit: 1000000, data: '0x608060405234801561000f575f80fd5b506101438061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80632e64cec1146100385780636057361d14610056575b5f80fd5b610040610072565b60405161004d919061009b565b60405180910390f35b610070600480360381019061006b91906100e2565b61007a565b005b5f8054905090565b805f8190555050565b5f819050919050565b61009581610083565b82525050565b5f6020820190506100ae5f83018461008c565b92915050565b5f80fd5b6100c181610083565b81146100cb575f80fd5b50565b5f813590506100dc816100b8565b92915050565b5f602082840312156100f7576100f66100b4565b5b5f610104848285016100ce565b9150509291505056fea2646970667358221220bfa7ddc6d937b635c7a8ad020080923800f04f6b0a685c47330306fd5267626b64736f6c63430008150033' }) - const storageAddress = receipt.contractAddress - const receiptPull = await web3.eth.getTransactionReceipt(receipt.transactionHash) - assert.equal(receiptPull.contractAddress, receipt.contractAddress) - receipt = await web3.eth.sendTransaction({ + const storageAddress = (await ethersProvider.getTransactionReceipt(receipt.hash)).contractAddress + receipt = await signer.sendTransaction({ from: accounts[0], to: storageAddress, - gas: 1000000, + gasLimit: 1000000, data: '0x6057361d000000000000000000000000000000000000000000000000000000000000000e' }) - const value = await web3.eth.call({ + const value = await ethersProvider.call({ from: accounts[0], to: storageAddress, data: '0x2e64cec1' @@ -43,14 +41,15 @@ describe('Transactions', () => { describe('eth_sendRawTransaction', () => { it('should deploy a contract and call a function using sendRawTransaction', async function () { - const accounts: string[] = await web3.eth.getAccounts() - + const accounts: string[] = await ethersProvider.send("eth_requestAccounts", []) + const signer = await ethersProvider.getSigner(0) const contractCreation = `0x02f908df0105010783069f638080b9088e608060405234801561001057600080fd5b5061005a6040518060400160405280601b81526020017f4f776e657220636f6e7472616374206465706c6f7965642062793a00000000008152503361011a60201b6101e91760201c565b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3610356565b6101b88282604051602401610130929190610265565b6040516020818303038152906040527f319af333000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506101bc60201b60201c565b5050565b6101dd816101d86101e060201b6102851761020160201b60201c565b60201c565b50565b60006a636f6e736f6c652e6c6f679050600080835160208501845afa505050565b61021360201b6102cb17819050919050565b61021b610316565b565b610226816102b1565b82525050565b600061023782610295565b61024181856102a0565b93506102518185602086016102e3565b61025a81610345565b840191505092915050565b6000604082019050818103600083015261027f818561022c565b905061028e602083018461021d565b9392505050565b600081519050919050565b600082825260208201905092915050565b60006102bc826102c3565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60005b838110156103015780820151818401526020810190506102e6565b83811115610310576000848401525b50505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fd5b6000601f19601f8301169050919050565b610529806103656000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063893d20e81461003b578063a6f9dae114610059575b600080fd5b610043610075565b6040516100509190610382565b60405180910390f35b610073600480360381019061006e91906102ea565b61009e565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461012c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610123906103cd565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61028182826040516024016101ff92919061039d565b6040516020818303038152906040527f319af333000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506102a6565b5050565b60006a636f6e736f6c652e6c6f679050600080835160208501845afa505050565b6102bd816102b56102856102c0565b63ffffffff16565b50565b6102cb819050919050565b6102d361046e565b565b6000813590506102e4816104dc565b92915050565b600060208284031215610300576102ff61049d565b5b600061030e848285016102d5565b91505092915050565b61032081610409565b82525050565b6000610331826103ed565b61033b81856103f8565b935061034b81856020860161043b565b610354816104a2565b840191505092915050565b600061036c6013836103f8565b9150610377826104b3565b602082019050919050565b60006020820190506103976000830184610317565b92915050565b600060408201905081810360008301526103b78185610326565b90506103c66020830184610317565b9392505050565b600060208201905081810360008301526103e68161035f565b9050919050565b600081519050919050565b600082825260208201905092915050565b60006104148261041b565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60005b8381101561045957808201518184015260208101905061043e565b83811115610468576000848401525b50505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fd5b600080fd5b6000601f19601f8301169050919050565b7f43616c6c6572206973206e6f74206f776e657200000000000000000000000000600082015250565b6104e581610409565b81146104f057600080fd5b5056fea2646970667358221220de534e7b87a9a1d73de47545c783b70d95ffebe049e62821ef2ef1c9a0fd7e8664736f6c63430008070033c080a0e9deb1e1b2cebf79e29cd9e69074f47a6680da51cb175f899a0b8c87aa893fb3a06ab1b35f54e47cd86191accdf8c915f998135c8cb58fccdb85125a9d1d1129da` - const receipt = await web3.eth.sendSignedTransaction(contractCreation) + const receipt = await ethersProvider.broadcastTransaction(contractCreation) + const contractAddress = (await ethersProvider.getTransactionReceipt(receipt.hash)).contractAddress // owner should be 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 - let value = await web3.eth.call({ + let value = await ethersProvider.call({ from: accounts[0], - to: receipt.contractAddress, + to: contractAddress, data: '0x893d20e8' }) assert.equal(value, '0x0000000000000000000000005B38Da6a701c568545dCfcB03FcB875f56beddC4'.toLowerCase()) @@ -59,16 +58,16 @@ describe('Transactions', () => { gasLimit: 1000000, maxPriorityFeePerGas: '0x01', maxFeePerGas: '0x7', - to: (hexToBytes(receipt.contractAddress) as AddressLike), + to: (getBytes(contractAddress) as AddressLike), value: 0, - data: hexToBytes('0xa6f9dae1000000000000000000000000Ab8483F64d9C6d1EcF9b849Ae677dD3315835cb2') + data: getBytes('0xa6f9dae1000000000000000000000000Ab8483F64d9C6d1EcF9b849Ae677dD3315835cb2') - }).sign(hexToBytes('0x503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb')) - await web3.eth.sendSignedTransaction(bytesToHex(tx.serialize())) + }).sign(getBytes('0x503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb')) + await ethersProvider.broadcastTransaction(hexlify(tx.serialize())) // owner should be 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2 - value = await web3.eth.call({ + value = await ethersProvider.call({ from: accounts[0], - to: receipt.contractAddress, + to: contractAddress, data: '0x893d20e8' }) assert.equal(value, '0x000000000000000000000000Ab8483F64d9C6d1EcF9b849Ae677dD3315835cb2'.toLowerCase()) diff --git a/libs/remix-solidity/package.json b/libs/remix-solidity/package.json index 412ca36a615..5bbfdeb311e 100644 --- a/libs/remix-solidity/package.json +++ b/libs/remix-solidity/package.json @@ -28,7 +28,6 @@ "semver": "^6.3.0", "solc": "0.8.26", "string-similarity": "^4.0.4", - "web3": "^4.1.1", "webworkify-webpack": "^2.1.5" }, "devDependencies": { diff --git a/libs/remix-tests/package.json b/libs/remix-tests/package.json index ff1a9314295..e9eaa6e6864 100644 --- a/libs/remix-tests/package.json +++ b/libs/remix-tests/package.json @@ -62,7 +62,6 @@ "string-similarity": "^4.0.4", "time-stamp": "^2.2.0", "tslib": "^2.3.0", - "web3": "^4.1.1", "winston": "^3.0.0" }, "devDependencies": { diff --git a/libs/remix-tests/src/deployer.ts b/libs/remix-tests/src/deployer.ts index 0094784e0a2..6d1c54586a0 100644 --- a/libs/remix-tests/src/deployer.ts +++ b/libs/remix-tests/src/deployer.ts @@ -1,17 +1,17 @@ import async from 'async' import { execution } from '@remix-project/remix-lib' -import { Web3, FMT_BYTES, FMT_NUMBER } from 'web3' import { compilationInterface } from './types' +import { BaseContract, BrowserProvider, Contract, ContractFactory, ethers, TransactionReceipt, TransactionResponse } from 'ethers' /** * @dev Deploy all contracts from compilation result * @param compileResult compilation result - * @param web3 web3 object + * @param provider BrowserProvider object * @param withDoubleGas If true, try deployment with gas double of estimation (used for Out-of-gas error only) * @param callback Callback */ -export function deployAll (compileResult: compilationInterface, web3: Web3, testsAccounts, withDoubleGas: boolean, deployCb, callback) { +export function deployAll (compileResult: compilationInterface, provider: BrowserProvider, testsAccounts, withDoubleGas: boolean, deployCb, callback) { const compiledObject = {} const contracts = {} const accounts: string[] = testsAccounts @@ -57,27 +57,26 @@ export function deployAll (compileResult: compilationInterface, web3: Web3, test next(null, contractsToDeploy) }, function deployContracts (contractsToDeploy: string[], next) { - const deployRunner = (deployObject, contractObject, contractName, filename, callback) => { - deployObject.estimateGas(undefined, { number: FMT_NUMBER.NUMBER, bytes: FMT_BYTES.HEX }).then((gasValue) => { - const gasBase = Math.ceil(gasValue * 1.2) - const gas = withDoubleGas ? gasBase * 2 : gasBase - deployObject.send({ - from: accounts[0], - gas: gas - }).on('receipt', async function (receipt) { - contractObject.options.address = receipt.contractAddress - contractObject.options.from = accounts[0] - contractObject.options.gas = 5000 * 1000 - compiledObject[contractName].deployedAddress = receipt.contractAddress + const deployRunner = (deployObject, { abi, signer }, contractName, filename, callback) => { + deployObject.getDeployTransaction().then((tx: TransactionResponse) => { + provider.estimateGas(tx).then((gasValue) => { + const gasBase = Math.ceil(Number(gasValue) * 1.2) + const gas = withDoubleGas ? gasBase * 2 : gasBase + deployObject.deploy({ + from: accounts[0], + gasLimit: gas + }).then(async function (deployContractObj: BaseContract) { + const deployTx = deployContractObj.deploymentTransaction() + const receipt: TransactionReceipt = await provider.getTransactionReceipt(deployTx.hash) + const contractObject: Contract = new ethers.Contract(receipt.contractAddress, abi, signer) + compiledObject[contractName].deployedAddress = receipt.contractAddress - contracts[contractName] = contractObject - contracts[contractName].filename = filename + contracts[contractName] = contractObject + contracts[contractName].filename = filename - if (deployCb) await deployCb(filename, receipt.contractAddress) - callback(null, { receipt: { contractAddress: receipt.contractAddress } }) // TODO this will only work with JavaScriptV VM - }).on('error', function (err) { - console.error(err) - callback(err) + if (deployCb) await deployCb(filename, receipt.contractAddress) + callback(null, { receipt: { contractAddress: receipt.contractAddress } }) // TODO this will only work with JavaScriptV VM + }) }) }).catch((err) => { console.error(err) @@ -89,9 +88,10 @@ export function deployAll (compileResult: compilationInterface, web3: Web3, test const contract = compiledObject[contractName] const encodeDataFinalCallback = (error, contractDeployData) => { if (error) return nextEach(error) - const contractObject = new web3.eth.Contract(contract.abi) - const deployObject = contractObject.deploy({ arguments: [], data: '0x' + contractDeployData.dataHex }) - deployRunner(deployObject, contractObject, contractName, contract.filename, (error) => { nextEach(error) }) + provider.getSigner().then((signer) => { + const deployObject: ContractFactory = new ethers.ContractFactory(contract.abi, '0x' + contractDeployData.dataHex, signer) + deployRunner(deployObject, { abi: contract.abi, signer }, contractName, contract.filename, (error) => { nextEach(error) }) + }) } const encodeDataStepCallback = (msg) => { console.dir(msg) } @@ -99,9 +99,10 @@ export function deployAll (compileResult: compilationInterface, web3: Web3, test const encodeDataDeployLibraryCallback = (libData, callback) => { const abi = compiledObject[libData.data.contractName].abi const code = compiledObject[libData.data.contractName].code - const libraryObject = new web3.eth.Contract(abi) - const deployObject = libraryObject.deploy({ arguments: [], data: '0x' + code }) - deployRunner(deployObject, libraryObject, libData.data.contractName, contract.filename, callback) + provider.getSigner().then((signer) => { + const deployObject: ContractFactory = new ethers.ContractFactory(abi, '0x' + code, signer) + deployRunner(deployObject, { abi, signer }, libData.data.contractName, contract.filename, callback) + }) } const funAbi = null // no need to set the abi for encoding the constructor diff --git a/libs/remix-tests/src/run.ts b/libs/remix-tests/src/run.ts index dc7569120c7..58a91e2c20d 100644 --- a/libs/remix-tests/src/run.ts +++ b/libs/remix-tests/src/run.ts @@ -1,10 +1,10 @@ import { Command } from 'commander'; -import { Web3 } from 'web3' +import { ethers, BrowserProvider } from "ethers" import path from 'path' import axios, { AxiosResponse } from 'axios' import { runTestFiles } from './runTestFiles' import fs from './fileSystem' -import { Provider, extend } from '@remix-project/remix-simulator' +import { Provider, extendProvider } from '@remix-project/remix-simulator' import { CompilerConfiguration } from './types' import Log from './logger' import colors from 'colors' @@ -127,11 +127,11 @@ commander nodeUrl: options.nodeUrl || null, blockNumber: options.blockNumber || null } - const provider: any = new Provider(providerConfig) - await provider.init() - const web3 = new Web3(provider) - extend(web3) - runTestFiles(path.resolve(file_path), isDirectory, web3, compilerConfig, (error, totalPassing, totalFailing) => { + const simulatorProvider: any = new Provider(providerConfig) + await simulatorProvider.init() + const provider: BrowserProvider = new ethers.BrowserProvider(simulatorProvider as any) + extendProvider(provider) + runTestFiles(path.resolve(file_path), isDirectory, provider, compilerConfig, (error, totalPassing, totalFailing) => { if (error) process.exit(1) if (totalFailing > 0 && options.killProcess) process.exit(1) }) diff --git a/libs/remix-tests/src/runTestFiles.ts b/libs/remix-tests/src/runTestFiles.ts index eac97d350b2..7b1352b9623 100644 --- a/libs/remix-tests/src/runTestFiles.ts +++ b/libs/remix-tests/src/runTestFiles.ts @@ -3,22 +3,22 @@ import fs from './fileSystem' import { runTest } from './testRunner' import { TestResultInterface, ResultsInterface, CompilerConfiguration, compilationInterface, ASTInterface, Options, AstNode } from './types' import colors from 'colors' -import { Web3 } from 'web3' import { format } from 'util' import { compileFileOrFiles } from './compiler' import { deployAll } from './deployer' +import { BrowserProvider } from 'ethers' /** * @dev run test contract files (used for CLI) * @param filepath Path of file * @param isDirectory True, if path is a directory - * @param web3 Web3 + * @param provider BrowserProvider * @param finalCallback optional callback to run finally * @param opts Options */ // eslint-disable-next-line @typescript-eslint/no-empty-function -export function runTestFiles (filepath: string, isDirectory: boolean, web3: Web3, compilerConfig: CompilerConfiguration, finalCallback: any = () => {}, opts?: Options) { +export function runTestFiles (filepath: string, isDirectory: boolean, provider: BrowserProvider, compilerConfig: CompilerConfiguration, finalCallback: any = () => {}, opts?: Options) { opts = opts || {} compilerConfig = compilerConfig || {} as CompilerConfiguration const sourceASTs: any = {} @@ -62,7 +62,7 @@ export function runTestFiles (filepath: string, isDirectory: boolean, web3: Web3 async.waterfall([ function getAccountList (next) { if (accounts) return next(null) - web3.eth.getAccounts() + provider.send("eth_requestAccounts", []) .then(_accounts => { accounts = _accounts next(null) @@ -77,13 +77,13 @@ export function runTestFiles (filepath: string, isDirectory: boolean, web3: Web3 for (const filename in asts) { if (filename.endsWith('_test.sol')) { sourceASTs[filename] = asts[filename].ast } } - deployAll(compilationResult, web3, accounts, false, null, (err, contracts) => { + deployAll(compilationResult, provider, accounts, false, null, (err, contracts) => { if (err) { // If contract deployment fails because of 'Out of Gas' error, try again with double gas // This is temporary, should be removed when remix-tests will have a dedicated UI to // accept deployment params from UI if (err.error.includes('The contract code couldn\'t be stored, please check your gas limit')) { - deployAll(compilationResult, web3, accounts, true, null, (error, contracts) => { + deployAll(compilationResult, provider, accounts, true, null, (error, contracts) => { if (error) next([{ message: 'contract deployment failed after trying twice: ' + (error.innerError || error.error), severity: 'error' }]) // IDE expects errors in array else next(null, compilationResult, contracts) }) @@ -150,7 +150,7 @@ export function runTestFiles (filepath: string, isDirectory: boolean, web3: Web3 async.eachOfLimit(contractsToTest, 1, (contractName: string, index, cb) => { try { const fileAST: AstNode = sourceASTs[contracts[contractName]['filename']] - runTest(contractName, contracts[contractName], contractsToTestDetails[index], fileAST, { accounts, web3 }, _testCallback, (err, result) => { + runTest(contractName, contracts[contractName], contractsToTestDetails[index], fileAST, { accounts, provider }, _testCallback, (err, result) => { if (err) { console.log(err) return cb(err) diff --git a/libs/remix-tests/src/runTestSources.ts b/libs/remix-tests/src/runTestSources.ts index 5d71f9b7b9a..a0dcbe5af6a 100644 --- a/libs/remix-tests/src/runTestSources.ts +++ b/libs/remix-tests/src/runTestSources.ts @@ -2,9 +2,8 @@ import async, { ErrorCallback } from 'async' import { compileContractSources, writeTestAccountsContract } from './compiler' import { deployAll } from './deployer' import { runTest } from './testRunner' -import { Web3 } from 'web3' import { EventEmitter } from 'events' -import { Provider, extend } from '@remix-project/remix-simulator' +import { extendProvider } from '@remix-project/remix-simulator' import { FinalResult, SrcIfc, compilationInterface, ASTInterface, Options, TestResultInterface, AstNode, CompilerConfiguration @@ -15,7 +14,7 @@ export class UnitTestRunner { event accountsLibCode testsAccounts: string[] | null - web3 + provider compiler compilerConfig @@ -23,15 +22,15 @@ export class UnitTestRunner { this.event = new EventEmitter() } - async init (web3 = null, accounts = null) { - this.web3 = await this.createWeb3Provider(web3) - this.testsAccounts = accounts || (this.web3 && await this.web3.eth.getAccounts()) || [] + async init (provider = null, accounts = null) { + this.provider = await this.createWeb3Provider(provider) + this.testsAccounts = accounts || (this.provider && await this.provider.send("eth_requestAccounts", []) ) || [] this.accountsLibCode = writeTestAccountsContract(this.testsAccounts) } - async createWeb3Provider (optWeb3) { - const web3 = optWeb3 - if (web3) extend(web3) + async createWeb3Provider (provider) { + const web3 = provider + if (web3) extendProvider(provider) return web3 } @@ -48,7 +47,7 @@ export class UnitTestRunner { async runTestSources (contractSources: SrcIfc, newCompilerConfig: CompilerConfiguration, testCallback, resultCallback, deployCb:any, finalCallback: any, importFileCb, opts: Options) { opts = opts || {} const sourceASTs: any = {} - if (opts.web3 || opts.accounts) this.init(opts.web3, opts.accounts) + if (opts.provider || opts.accounts) this.init(opts.provider, opts.accounts) async.waterfall([ (next) => { compileContractSources(contractSources, newCompilerConfig, importFileCb, this, { accounts: this.testsAccounts, testFilePath: opts.testFilePath, event: this.event }, next) @@ -57,13 +56,13 @@ export class UnitTestRunner { for (const filename in asts) { if (filename.endsWith('_test.sol')) { sourceASTs[filename] = asts[filename].ast } } - deployAll(compilationResult, this.web3, this.testsAccounts, false, deployCb, (err, contracts) => { + deployAll(compilationResult, this.provider, this.testsAccounts, false, deployCb, (err, contracts) => { if (err) { // If contract deployment fails because of 'Out of Gas' error, try again with double gas // This is temporary, should be removed when remix-tests will have a dedicated UI to // accept deployment params from UI if (err.error.includes('The contract code couldn\'t be stored, please check your gas limit')) { - deployAll(compilationResult, this.web3, this.testsAccounts, true, deployCb, (error, contracts) => { + deployAll(compilationResult, this.provider, this.testsAccounts, true, deployCb, (error, contracts) => { if (error) next([{ message: 'contract deployment failed after trying twice: ' + (error.innerError || error.error), severity: 'error' }]) // IDE expects errors in array else next(null, compilationResult, contracts) }) @@ -109,7 +108,7 @@ export class UnitTestRunner { async.eachOfLimit(contractsToTest, 1, (contractName: string, index: string | number, cb: ErrorCallback) => { const fileAST: AstNode = sourceASTs[contracts[contractName]['filename']] - runTest(contractName, contracts[contractName], contractsToTestDetails[index], fileAST, { accounts: this.testsAccounts, web3: this.web3 }, _testCallback, (err, result) => { + runTest(contractName, contracts[contractName], contractsToTestDetails[index], fileAST, { accounts: this.testsAccounts, provider: this.provider }, _testCallback, (err, result) => { if (err) { return cb(err) } diff --git a/libs/remix-tests/src/testRunner.ts b/libs/remix-tests/src/testRunner.ts index b9e1c5c2d51..755e1a5d7d0 100644 --- a/libs/remix-tests/src/testRunner.ts +++ b/libs/remix-tests/src/testRunner.ts @@ -1,6 +1,6 @@ import async from 'async' import * as changeCase from 'change-case' -import { Web3 } from 'web3' +import { keccak256, AbiCoder, ContractTransactionResponse, toUtf8Bytes, Interface } from 'ethers' import assertionEvents from './assertionEvents' import { RunListInterface, TestCbInterface, TestResultInterface, ResultCbInterface, @@ -183,28 +183,29 @@ function createRunList (jsonInterface: FunctionDescription[], fileAST: AstNode, const availableFunctions: string[] = getAvailableFunctions(fileAST, testContractName) const testFunctionsInterface: FunctionDescription[] = getTestFunctionsInterface(jsonInterface, availableFunctions) const specialFunctionsInterface: Record = getSpecialFunctionsInterface(jsonInterface) + const contractInterface: Interface = new Interface(jsonInterface) const runList: RunListInterface[] = [] if (availableFunctions.includes('beforeAll')) { const func = specialFunctionsInterface['beforeAll'] - runList.push({ name: 'beforeAll', inputs: func.inputs, signature: func.signature, type: 'internal', constant: isConstant(func), payable: isPayable(func) }) + runList.push({ name: 'beforeAll', inputs: func.inputs, signature: contractInterface.getFunction(func.name).selector, type: 'internal', constant: isConstant(func), payable: isPayable(func) }) } for (const func of testFunctionsInterface) { if (availableFunctions.includes('beforeEach')) { const func = specialFunctionsInterface['beforeEach'] - runList.push({ name: 'beforeEach', inputs: func.inputs, signature: func.signature, type: 'internal', constant: isConstant(func), payable: isPayable(func) }) + runList.push({ name: 'beforeEach', inputs: func.inputs, signature: contractInterface.getFunction(func.name).selector, type: 'internal', constant: isConstant(func), payable: isPayable(func) }) } - if (func.name && func.inputs) runList.push({ name: func.name, inputs: func.inputs, signature: func.signature, type: 'test', constant: isConstant(func), payable: isPayable(func) }) + if (func.name && func.inputs) runList.push({ name: func.name, inputs: func.inputs, signature: contractInterface.getFunction(func.name).selector, type: 'test', constant: isConstant(func), payable: isPayable(func) }) if (availableFunctions.indexOf('afterEach') >= 0) { const func = specialFunctionsInterface['afterEach'] - runList.push({ name: 'afterEach', inputs: func.inputs, signature: func.signature, type: 'internal', constant: isConstant(func), payable: isPayable(func) }) + runList.push({ name: 'afterEach', inputs: func.inputs, signature: contractInterface.getFunction(func.name).selector, type: 'internal', constant: isConstant(func), payable: isPayable(func) }) } } if (availableFunctions.indexOf('afterAll') >= 0) { const func = specialFunctionsInterface['afterAll'] - runList.push({ name: 'afterAll', inputs: func.inputs, signature: func.signature, type: 'internal', constant: isConstant(func), payable: isPayable(func) }) + runList.push({ name: 'afterAll', inputs: func.inputs, signature: contractInterface.getFunction(func.name).selector, type: 'internal', constant: isConstant(func), payable: isPayable(func) }) } return runList @@ -215,11 +216,10 @@ export function runTest (testName: string, testObject: any, contractDetails: Com let failureNum = 0 let timePassed = 0 const failedTransactions = {} - const isJSONInterfaceAvailable = testObject && testObject.options && testObject.options.jsonInterface + const isJSONInterfaceAvailable = testObject && testObject.interface && testObject.interface.fragments if (!isJSONInterfaceAvailable) { return resultsCallback(new Error('Contract interface not available'), { passingNum, failureNum, timePassed }) } - const runList: RunListInterface[] = createRunList(testObject.options.jsonInterface, fileAST, testName) - const web3 = opts.web3 || new Web3() - web3.eth.handleRevert = true // enables returning error reason on revert + const runList: RunListInterface[] = createRunList(testObject.interface.fragments, fileAST, testName) + const provider = opts.provider const accts: TestResultInterface = { type: 'accountList', value: opts.accounts @@ -232,152 +232,155 @@ export function runTest (testName: string, testObject: any, contractDetails: Com filename: testObject.filename } testCallback(undefined, resp) - async.eachOfLimit(runList, 1, function (func, index, next) { + async.eachOfLimit(runList, 1, async function (func, index) { let sender: string | null = null let hhLogs - if (func.signature) { - sender = getOverriddenSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers) - if (opts.accounts && sender) { - sender = opts.accounts[sender] - } - } let sendParams: Record | null = null - if (sender) sendParams = { from: sender } - if (func.inputs && func.inputs.length > 0) { return resultsCallback(new Error(`Method '${func.name}' can not have parameters inside a test contract`), { passingNum, failureNum, timePassed }) } - const method = testObject.methods[func.name].apply(testObject.methods[func.name], []) const startTime = Date.now() + if (func.inputs && func.inputs.length > 0) { return resultsCallback(new Error(`Method '${func.name}' can not have parameters inside a test contract`), { passingNum, failureNum, timePassed }) } let debugTxHash:string if (func.constant) { sendParams = {} const tagTimestamp = 'remix_tests_tag' + Date.now() - if (web3.remix && web3.remix.registerCallId) web3.remix.registerCallId(tagTimestamp) - method.call(sendParams).then(async (result) => { - const time = (Date.now() - startTime) / 1000.0 - let tagTxHash - if (web3.remix && web3.remix.getHashFromTagBySimulator) tagTxHash = await web3.remix.getHashFromTagBySimulator(tagTimestamp) - if (web3.remix && web3.remix.getHHLogsForTx) hhLogs = await web3.remix.getHHLogsForTx(tagTxHash) - debugTxHash = tagTxHash - if (result) { + if (provider.remix && provider.remix.registerCallId) provider.remix.registerCallId(tagTimestamp) + const result = await testObject[func.name](sendParams) + const time = (Date.now() - startTime) / 1000.0 + let tagTxHash + if (provider.remix && provider.remix.getHashFromTagBySimulator) tagTxHash = await provider.remix.getHashFromTagBySimulator(tagTimestamp) + if (provider.remix && provider.remix.getHHLogsForTx) hhLogs = await provider.remix.getHHLogsForTx(tagTxHash) + debugTxHash = tagTxHash + if (result) { + const resp: TestResultInterface = { + type: 'testPass', + value: changeCase.sentenceCase(func.name), + filename: testObject.filename, + time: time, + context: testName, + provider, + debugTxHash + } + if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs + testCallback(undefined, resp) + passingNum += 1 + timePassed += time + } else { + const resp: TestResultInterface = { + type: 'testFailure', + value: changeCase.sentenceCase(func.name), + filename: testObject.filename, + time: time, + errMsg: 'function returned false', + context: testName, + provider, + debugTxHash + } + if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs + testCallback(undefined, resp) + failureNum += 1 + timePassed += time + } + } else { + if (func.signature) { + sender = getOverriddenSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers) + if (opts.accounts && sender) { + sender = opts.accounts[sender] + } + } + if (sender) { + sendParams = { from: sender } + const signer = await provider.getSigner(sender) + testObject = testObject.connect(signer) + } + if (func.payable) { + const value = getProvidedValue(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers) + if (value) { + if (sendParams) sendParams.value = value + else sendParams = { value } + } + } + if (!sendParams) sendParams = {} + sendParams.gasLimit = 10000000 * 8 + try { + const txResponse: ContractTransactionResponse = await testObject[func.name](sendParams) + const receipt = await provider.getTransactionReceipt(txResponse.hash) + debugTxHash = receipt.hash + if (provider.remix && provider.remix.getHHLogsForTx) hhLogs = await provider.remix.getHHLogsForTx(receipt.hash) + const time: number = (Date.now() - startTime) / 1000.0 + const assertionEventHashes = assertionEvents.map(e => keccak256(toUtf8Bytes(e.name + '(' + e.params.join() + ')'))) + let testPassed = false + for (const i in receipt.logs) { + let events = receipt.logs[i] + if (!Array.isArray(events)) events = [events] + for (const event of events) { + const eIndex = assertionEventHashes.indexOf(event.topics[0]) // event name topic will always be at index 0 + if (eIndex >= 0) { + const testEventArray = AbiCoder.defaultAbiCoder().decode(assertionEvents[eIndex].params, event.data) + const testEvent = [...testEventArray] // Make it mutable + if (!testEvent[0]) { + const assertMethod = testEvent[2] + if (assertMethod === 'ok') { // for 'Assert.ok' method + testEvent[3] = 'false' + testEvent[4] = 'true' + } + const location = getAssertMethodLocation(fileAST, testName, func.name, assertMethod) + const resp: TestResultInterface = { + type: 'testFailure', + value: changeCase.sentenceCase(func.name), + filename: testObject.filename, + time: time, + errMsg: testEvent[1], + context: testName, + assertMethod, + returned: testEvent[3], + expected: testEvent[4], + location, + provider, + debugTxHash + } + if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs + testCallback(undefined, resp) + failureNum += 1 + timePassed += time + return + } + testPassed = true + } + } + } + + if (testPassed) { const resp: TestResultInterface = { type: 'testPass', value: changeCase.sentenceCase(func.name), filename: testObject.filename, time: time, context: testName, - web3, + provider, debugTxHash } if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs testCallback(undefined, resp) passingNum += 1 timePassed += time - } else { + } else if (hhLogs && hhLogs.length) { const resp: TestResultInterface = { - type: 'testFailure', + type: 'logOnly', value: changeCase.sentenceCase(func.name), filename: testObject.filename, time: time, - errMsg: 'function returned false', context: testName, - web3, - debugTxHash + hhLogs } - if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs testCallback(undefined, resp) - failureNum += 1 timePassed += time } - next() - }) - } else { - if (func.payable) { - const value = getProvidedValue(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers) - if (value) { - if (sendParams) sendParams.value = value - else sendParams = { value } - } - } - if (!sendParams) sendParams = {} - sendParams.gas = 10000000 * 8 - method.send(sendParams).on('receipt', async (receipt) => { - try { - debugTxHash = receipt.transactionHash - if (web3.remix && web3.remix.getHHLogsForTx) hhLogs = await web3.remix.getHHLogsForTx(receipt.transactionHash) - const time: number = (Date.now() - startTime) / 1000.0 - const assertionEventHashes = assertionEvents.map(e => Web3.utils.sha3(e.name + '(' + e.params.join() + ')')) - let testPassed = false - for (const i in receipt.logs) { - let events = receipt.logs[i] - if (!Array.isArray(events)) events = [events] - for (const event of events) { - const eIndex = assertionEventHashes.indexOf(event.topics[0]) // event name topic will always be at index 0 - if (eIndex >= 0) { - const testEvent = web3.eth.abi.decodeParameters(assertionEvents[eIndex].params, event.data) - if (!testEvent[0]) { - const assertMethod = testEvent[2] - if (assertMethod === 'ok') { // for 'Assert.ok' method - testEvent[3] = 'false' - testEvent[4] = 'true' - } - const location = getAssertMethodLocation(fileAST, testName, func.name, assertMethod) - const resp: TestResultInterface = { - type: 'testFailure', - value: changeCase.sentenceCase(func.name), - filename: testObject.filename, - time: time, - errMsg: testEvent[1], - context: testName, - assertMethod, - returned: testEvent[3], - expected: testEvent[4], - location, - web3, - debugTxHash - } - if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs - testCallback(undefined, resp) - failureNum += 1 - timePassed += time - return next() - } - testPassed = true - } - } - } - - if (testPassed) { - const resp: TestResultInterface = { - type: 'testPass', - value: changeCase.sentenceCase(func.name), - filename: testObject.filename, - time: time, - context: testName, - web3, - debugTxHash - } - if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs - testCallback(undefined, resp) - passingNum += 1 - timePassed += time - } else if (hhLogs && hhLogs.length) { - const resp: TestResultInterface = { - type: 'logOnly', - value: changeCase.sentenceCase(func.name), - filename: testObject.filename, - time: time, - context: testName, - hhLogs - } - testCallback(undefined, resp) - timePassed += time - } - return next() - } catch (err) { + return + } catch (err) { + if (!err.receipt) { console.error(err) - return next(err) + return } - }).on('error', async (err) => { const time: number = (Date.now() - startTime) / 1000.0 if (failedTransactions[err.receipt.transactionHash]) return // we are already aware of this transaction failing. failedTransactions[err.receipt.transactionHash] = time @@ -391,20 +394,20 @@ export function runTest (testName: string, testObject: any, contractDetails: Com time: time, errMsg, context: testName, - web3 + provider } if (err.receipt) txHash = err.receipt.transactionHash else if (err.message.includes('Transaction has been reverted by the EVM')) { txHash = JSON.parse(err.message.replace('Transaction has been reverted by the EVM:', '')).transactionHash } - if (web3.remix && web3.remix.getHHLogsForTx && txHash) hhLogs = await web3.remix.getHHLogsForTx(txHash) + if (provider.remix && provider.remix.getHHLogsForTx && txHash) hhLogs = await provider.remix.getHHLogsForTx(txHash) if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs resp.debugTxHash = txHash testCallback(undefined, resp) failureNum += 1 timePassed += time - return next() - }) + return + } } }, function (error) { resultsCallback(error, { passingNum, failureNum, timePassed }) diff --git a/libs/remix-tests/src/types.ts b/libs/remix-tests/src/types.ts index fb03e948878..1fecd9d97bf 100644 --- a/libs/remix-tests/src/types.ts +++ b/libs/remix-tests/src/types.ts @@ -37,7 +37,7 @@ export interface TestResultInterface { expected?: string | number location?: string hhLogs?: [] - web3?: any + provider?: any debugTxHash?: string } export interface TestCbInterface { @@ -50,7 +50,7 @@ export interface ResultCbInterface { export interface Options { accounts?: string[] | null, testFilePath?: string - web3?: any + provider?: any } export interface CompilerConfiguration { diff --git a/libs/remix-tests/tests/testRunner.cli.spec.ts b/libs/remix-tests/tests/testRunner.cli.spec.ts index 8b17b5370d0..652e5a71a03 100644 --- a/libs/remix-tests/tests/testRunner.cli.spec.ts +++ b/libs/remix-tests/tests/testRunner.cli.spec.ts @@ -60,7 +60,6 @@ Commands: it('remix-tests running a test file', function() { const res = spawnSync(executablePath, [resolve(__dirname + '/examples_0/assert_ok_test.sol')]) - //console.log(res.stdout.toString()) // match initial lines console.log(res.stdout.toString()) expect(res.stdout.toString().trim()).to.match(/:: Running tests using remix-tests ::/) diff --git a/libs/remix-tests/tests/testRunner.spec.ts b/libs/remix-tests/tests/testRunner.spec.ts index c5efe8452ea..84db36b6314 100644 --- a/libs/remix-tests/tests/testRunner.spec.ts +++ b/libs/remix-tests/tests/testRunner.spec.ts @@ -1,12 +1,11 @@ import * as async from 'async' -import { Web3 } from 'web3'; +import { ethers } from 'ethers' import * as assert from 'assert' -import { Provider, extend } from '@remix-project/remix-simulator' - +import { Provider, extendProvider } from '@remix-project/remix-simulator' import { compileFileOrFiles } from '../src/compiler' import { deployAll } from '../src/deployer' import { runTest, compilationInterface } from '../src/index' -import { ResultsInterface, TestCbInterface, ResultCbInterface } from '../src/index' +import { ResultsInterface, TestCbInterface } from '../src/index' // deepEqualExcluding allows us to exclude specific keys whose values vary. // In this specific test, we'll use this helper to exclude `time` keys. @@ -40,27 +39,25 @@ function deepEqualExcluding(a: any, b: any, excludedKeys: string[]) { } let accounts: string[] -const provider: any = new Provider() +const simulatorProvider: any = new Provider() async function compileAndDeploy(filename: string, callback: any) { - const web3: Web3 = new Web3() const sourceASTs: any = {} - await provider.init() - web3.setProvider(provider) - extend(web3) + await simulatorProvider.init() + const provider = new ethers.BrowserProvider(simulatorProvider) + extendProvider(provider) let compilationData: any async.waterfall([ function getAccountList(next: any): void { - web3.eth.getAccounts() + provider.send("eth_requestAccounts", []) .then(( _accounts: string[]) => { accounts = _accounts - web3.eth.defaultAccount = accounts[0] next(undefined) }) .catch((_err: Error | null | undefined) => next(_err)) }, function compile(next: any): void { - compileFileOrFiles(filename, false, { accounts, web3 }, null, next) + compileFileOrFiles(filename, false, { accounts, provider }, null, next) }, function deployAllContracts(compilationResult: compilationInterface, asts, next: any): void { for (const filename in asts) { @@ -70,13 +67,13 @@ async function compileAndDeploy(filename: string, callback: any) { // eslint-disable-next-line no-useless-catch try { compilationData = compilationResult - deployAll(compilationResult, web3, accounts, false, null, next) + deployAll(compilationResult, provider, accounts, false, null, next) } catch (e) { throw e } } ], function (_err: Error | null | undefined, contracts: any): void { - callback(null, compilationData, contracts, sourceASTs, accounts, web3) + callback(null, compilationData, contracts, sourceASTs, accounts, provider) }) } @@ -108,8 +105,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/examples_0/assert_ok_test.sol' before((done) => { - compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => { - runTest('AssertOkTest', contracts.AssertOkTest, compilationData[filename]['AssertOkTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) => { + runTest('AssertOkTest', contracts.AssertOkTest, compilationData[filename]['AssertOkTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -131,8 +128,8 @@ describe('testRunner', function () { { type: 'contract', value: 'AssertOkTest', filename: __dirname + '/examples_0/assert_ok_test.sol' }, { type: 'testPass', debugTxHash: '0x5b665752a4faf83229259b9b2811d3295be0af633b0051d4b90042283ef55707', value: 'Ok pass test', filename: __dirname + '/examples_0/assert_ok_test.sol', context: 'AssertOkTest', hhLogs: hhLogs1 }, { type: 'testFailure', debugTxHash: '0xa0a30ad042a7fc3495f72be7ba788d705888ffbbec7173f60bb27e07721510f2', value: 'Ok fail test', filename: __dirname + '/examples_0/assert_ok_test.sol', errMsg: 'okFailTest fails', context: 'AssertOkTest', hhLogs: hhLogs2, assertMethod: 'ok', location: '366:36:0', expected: 'true', returned: 'false' }, - // - ], ['time','type','debugTxHash','location','expected','returned','errMsg','assertMethod','web3']) + + ], ['time','type','debugTxHash','location','expected','returned','errMsg','assertMethod','provider']) }) }) @@ -140,8 +137,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/examples_0/assert_equal_test.sol' before((done) => { - compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => { - runTest('AssertEqualTest', contracts.AssertEqualTest, compilationData[filename]['AssertEqualTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) => { + runTest('AssertEqualTest', contracts.AssertEqualTest, compilationData[filename]['AssertEqualTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -171,7 +168,7 @@ describe('testRunner', function () { { type: 'testFailure', debugTxHash: '0x20ff637a0fb28c9f943d0eaa23d9391e9177810d77a9ac5478873f8838719fc5', value: 'Equal bytes32 fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalBytes32FailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1670:48:0', expected: '0x72656d6978000000000000000000000000000000000000000000000000000000', returned: '0x72656d6979000000000000000000000000000000000000000000000000000000' }, { type: 'testPass', debugTxHash: '0x2a7c3f1f5d87620d8f1f2a83984e2cae6ff985f25f9cb96a046b507b357941bb', value: 'Equal string pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' }, { type: 'testFailure', debugTxHash: '0x7d9381986adb7e9e6d7d65191f82633cb453406556569f77f5e0b4aa39274324', value: 'Equal string fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalStringFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1916:81:0', expected: 'remix-tests', returned: 'remix' } - ], ['time', 'web3']) + ], ['time', 'provider']) }) }) @@ -179,8 +176,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/examples_0/assert_notEqual_test.sol' before((done) => { - compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => { - runTest('AssertNotEqualTest', contracts.AssertNotEqualTest, compilationData[filename]['AssertNotEqualTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) => { + runTest('AssertNotEqualTest', contracts.AssertNotEqualTest, compilationData[filename]['AssertNotEqualTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -211,7 +208,7 @@ describe('testRunner', function () { { type: 'testFailure', debugTxHash: '0x3a8e50586fee6fe4e5d765d1392151e550b28959ea8eb823e8fdf54627fa861e', value: 'Not equal bytes32 fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualBytes32FailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '1756:54:0', expected: '0x72656d6978000000000000000000000000000000000000000000000000000000', returned: '0x72656d6978000000000000000000000000000000000000000000000000000000' }, { type: 'testPass', debugTxHash: '0x8b84801330bbd44f358aee9089263ad7400ffc738f2f1f9e6b06cf6af20816d1', value: 'Not equal string pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' }, { type: 'testFailure', debugTxHash: '0xb2e1b7cdfdc622e1c39e436054168861ca68bb51147940bff6ebd075f8afd2da', value: 'Not equal string fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualStringFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '2026:81:0', expected: 'remix', returned: 'remix' }, - ], ['time', 'web3']) + ], ['time', 'provider']) }) }) @@ -219,8 +216,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/examples_0/assert_greaterThan_test.sol' before((done) => { - compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => { - runTest('AssertGreaterThanTest', contracts.AssertGreaterThanTest, compilationData[filename]['AssertGreaterThanTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) => { + runTest('AssertGreaterThanTest', contracts.AssertGreaterThanTest, compilationData[filename]['AssertGreaterThanTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -244,7 +241,7 @@ describe('testRunner', function () { { type: 'testPass', debugTxHash: '0xf52652ef6020ae091022455df8713d20cb00a35de8bf485e177128a457a50d6c', value: 'Greater than uint int pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' }, { type: 'testFailure', debugTxHash: '0x9f826060a0e5a8c0187d5e9ffe83a153080379a1e1fea0b267745eb8bd52fd6f', value: 'Greater than uint int fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanUintIntFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '845:71:0', expected: '2', returned: '1' }, { type: 'testPass', debugTxHash: '0x04e1703c75cc4beb4b8c9ddfb79489192423fe745089382cadb1811cbf2d915c', value: 'Greater than int uint pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' }, - ], ['time', 'web3']) + ], ['time', 'provider']) }) }) @@ -252,8 +249,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/examples_0/assert_lesserThan_test.sol' before((done) => { - compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => { - runTest('AssertLesserThanTest', contracts.AssertLesserThanTest, compilationData[filename]['AssertLesserThanTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) => { + runTest('AssertLesserThanTest', contracts.AssertLesserThanTest, compilationData[filename]['AssertLesserThanTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -277,7 +274,7 @@ describe('testRunner', function () { { type: 'testFailure', debugTxHash: '0xccab30c5a154c4c2e8ca9a8966b86a55f08188d606c3519a5c29534b4b64fb47', value: 'Lesser than int fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanIntFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '557:65:0', expected: '-1', returned: '1' }, { type: 'testPass', debugTxHash: '0x8e90fb7f3b8343d037444275cd69d431f75a7fc6b46322c69397373463cee22a', value: 'Lesser than uint int pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' }, { type: 'testFailure', debugTxHash: '0x7912b2535fe0f5a56b274a7ec5ef6dbb0f52a7199f11831867a98961568f2883', value: 'Lesser than int uint fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanIntUintFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '826:69:0', expected: '1', returned: '1' }, - ], ['time', 'web3']) + ], ['time', 'provider']) }) }) @@ -285,8 +282,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/examples_1/simple_storage_test.sol' before((done) => { - compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) => { - runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) => { + runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -308,7 +305,7 @@ describe('testRunner', function () { { type: 'testPass', debugTxHash: '0x1b5cce7f93b78f8c97ba915e24648127b7f28e86008668d20a4c20fd0fde40bc', value: 'Initial value should not be200', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' }, { type: 'testFailure', debugTxHash: '0xdb9cbef289c9e53f4119ad60c1f3e29770de930091e17ab987529c7057013628', value: 'Should trigger one fail', filename: __dirname + '/examples_1/simple_storage_test.sol', errMsg: 'uint test 1 fails', context: 'MyTest', assertMethod: 'equal', location: '532:51:1', expected: '2', returned: '1' }, { type: 'testPass', debugTxHash: '0x21472600af5de67cd53a489f2435169fdfbe83d7b7dd43c8a0150725fd91e254', value: 'Should trigger one pass', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' } - ], ['time', 'web3']) + ], ['time', 'provider']) }) }) @@ -316,8 +313,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/examples_2/simple_storage_test.sol' before(done => { - compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) { - runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) { + runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -337,17 +334,17 @@ describe('testRunner', function () { { type: 'contract', value: 'MyTest', filename: __dirname + '/examples_2/simple_storage_test.sol' }, { type: 'testPass', debugTxHash: '0xd86dbe1efaf707981475a9a4762826c6852cce3e5b0e987827027602d6d6d734', value: 'Initial value should be100', filename: __dirname + '/examples_2/simple_storage_test.sol', context: 'MyTest' }, { type: 'testPass', debugTxHash: '0xa447f168cd1ce406635ea2368b61828b107473905e270957b7ee38b94a12e055', value: 'Value is set200', filename: __dirname + '/examples_2/simple_storage_test.sol', context: 'MyTest' } - ], ['time', 'web3']) + ], ['time', 'provider']) }) }) - // Test string equality + // // Test string equality describe('test string equality', function () { const filename: string = __dirname + '/examples_3/simple_string_test.sol' before(done => { - compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) { - runTest('StringTest', contracts.StringTest, compilationData[filename]['StringTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) { + runTest('StringTest', contracts.StringTest, compilationData[filename]['StringTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -363,7 +360,7 @@ describe('testRunner', function () { { type: 'contract', value: 'StringTest', filename: __dirname + '/examples_3/simple_string_test.sol' }, { type: 'testPass', debugTxHash: '0x0f988e614ae6e9a5f560734e8b63f835de14460a5b797e16fa5c68091452d2c5', value: 'Initial value should be hello world', filename: __dirname + '/examples_3/simple_string_test.sol', context: 'StringTest' }, { type: 'testPass', debugTxHash: '0x713ec0ad3cd02ffcd64f54e45b4da5498983d18b5a696ea34e9fb5d01928cb3f', value: 'Value should not be hello wordl', filename: __dirname + '/examples_3/simple_string_test.sol', context: 'StringTest' } - ], ['time', 'web3']) + ], ['time', 'provider']) }) }) @@ -372,8 +369,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/examples_5/test/simple_storage_test.sol' before(done => { - compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) { - runTest('StorageResolveTest', contracts.StorageResolveTest, compilationData[filename]['StorageResolveTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) { + runTest('StorageResolveTest', contracts.StorageResolveTest, compilationData[filename]['StorageResolveTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -390,7 +387,7 @@ describe('testRunner', function () { { type: 'testPass', debugTxHash: '0xd86dbe1efaf707981475a9a4762826c6852cce3e5b0e987827027602d6d6d734', value: 'Initial value should be100', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' }, { type: 'testPass', debugTxHash: '0xc9e1523f6f094cdd909b3977d1eef7c83284b15c22b17b9b0a4a632bf59881f6', value: 'Check if even', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' }, { type: 'testPass', debugTxHash: '0xe3f415f2cade92243fd795b9988fc9e9c4318983933c0a0b103e968f31c40f55', value: 'Check if odd', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' } - ], ['time', 'web3']) + ], ['time', 'provider']) }) }) @@ -399,8 +396,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/examples_4/SafeMath_test.sol' before(done => { - compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) { - runTest('SafeMathTest', contracts.SafeMathTest, compilationData[filename]['SafeMathTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) { + runTest('SafeMathTest', contracts.SafeMathTest, compilationData[filename]['SafeMathTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -419,8 +416,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/number/number_test.sol' before(done => { - compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) { - runTest('IntegerTest', contracts.IntegerTest, compilationData[filename]['IntegerTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) { + runTest('IntegerTest', contracts.IntegerTest, compilationData[filename]['IntegerTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -439,8 +436,8 @@ describe('testRunner', function () { const filename: string = __dirname + '/various_sender/sender_and_value_test.sol' before(done => { - compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) { - runTest('SenderAndValueTest', contracts.SenderAndValueTest, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done)) + compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) { + runTest('SenderAndValueTest', contracts.SenderAndValueTest, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts, provider }, testCallback, resultsCallback(done)) }) }) @@ -467,8 +464,8 @@ describe('testRunner', function () { } } before(done => { - compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], web3: any) { - runTest('SenderAndValueTest', undefined, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts, web3 }, testCallback, errorCallback(done)) + compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: any, contracts: any, asts: any, accounts: string[], provider: any) { + runTest('SenderAndValueTest', undefined, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts, provider }, testCallback, errorCallback(done)) }) }) diff --git a/libs/remix-ui/debugger-ui/src/lib/api/debugger-api.ts b/libs/remix-ui/debugger-ui/src/lib/api/debugger-api.ts index d2a9016ac99..60c50efed06 100644 --- a/libs/remix-ui/debugger-ui/src/lib/api/debugger-api.ts +++ b/libs/remix-ui/debugger-ui/src/lib/api/debugger-api.ts @@ -1,26 +1,27 @@ -import { Web3 } from 'web3' import { init , traceHelper, TransactionDebugger as Debugger } from '@remix-project/remix-debug' import { CompilerAbstract } from '@remix-project/remix-solidity' import { lineText } from '@remix-ui/editor' import { util } from '@remix-project/remix-lib' +import { BrowserProvider, ethers } from 'ethers' const { toHexPaddedString } = util export const DebuggerApiMixin = (Base) => class extends Base { - initialWeb3 + initialWeb3: BrowserProvider debuggerBackend + web3Provider: any initDebuggerApi () { const self = this this.web3Provider = { - sendAsync (payload, callback) { + request (payload) { return self.call('web3Provider', 'sendAsync', payload) } } - this._web3 = new Web3(this.web3Provider) + this._web3 = new ethers.BrowserProvider(this.web3Provider) // this._web3 can be overwritten and reset to initial value in 'debug' method this.initialWeb3 = this._web3 - init.extendWeb3(this._web3) + init.extendProvider(this._web3) this.offsetToLineColumnConverter = { async offsetToLineColumn (rawLocation, file, sources, asts) { @@ -96,7 +97,7 @@ export const DebuggerApiMixin = (Base) => class extends Base { async fetchContractAndCompile (address, receipt) { const target = (address && traceHelper.isContractCreation(address)) ? receipt.contractAddress : address const targetAddress = target || receipt.contractAddress || receipt.to - const codeAtAddress = await this._web3.eth.getCode(targetAddress) + const codeAtAddress = await this._web3.getCode(targetAddress) const output = await this.call('fetchAndCompile', 'resolve', targetAddress, codeAtAddress, '.debug') if (output) { return new CompilerAbstract(output.languageversion, output.data, output.source) @@ -104,7 +105,7 @@ export const DebuggerApiMixin = (Base) => class extends Base { return null } - async getDebugWeb3 () { + async getDebugProvider () { let web3 let network try { @@ -116,16 +117,16 @@ export const DebuggerApiMixin = (Base) => class extends Base { const webDebugNode = init.web3DebugNode(network.name) web3 = !webDebugNode ? this.web3() : webDebugNode } - init.extendWeb3(web3) + init.extendProvider(web3) return web3 } async getTrace (hash) { if (!hash) return - const web3 = await this.getDebugWeb3() - const currentReceipt = await web3.eth.getTransactionReceipt(hash) + const provider = await this.getDebugProvider() + const currentReceipt = await provider.getTransactionReceipt(hash) const debug = new Debugger({ - web3, + provider, offsetToLineColumnConverter: this.offsetToLineColumnConverter, compilationResult: async (address) => { try { @@ -151,15 +152,15 @@ export const DebuggerApiMixin = (Base) => class extends Base { return trace } - debug (hash, web3?) { + debug (hash, provider?: BrowserProvider) { try { this.call('fetchAndCompile', 'clearCache') } catch (e) { console.error(e) } - if (web3) this._web3 = web3 + if (provider) this._web3 = provider else this._web3 = this.initialWeb3 - init.extendWeb3(this._web3) + init.extendProvider(this._web3) if (this.onDebugRequestedListener) { this.onDebugRequestedListener(hash, this._web3).then((debuggerBackend) => { this.debuggerBackend = debuggerBackend diff --git a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx index dca1c5e37a4..bde33231a8b 100644 --- a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx @@ -261,9 +261,9 @@ export const DebuggerUI = (props: DebuggerUIProps) => { return } - const web3 = optWeb3 || (state.opt.debugWithLocalNode ? await debuggerModule.web3() : await debuggerModule.getDebugWeb3()) + const web3 = optWeb3 || (state.opt.debugWithLocalNode ? await debuggerModule.web3() : await debuggerModule.getDebugProvider()) try { - const networkId = await web3.eth.net.getId() + const networkId = (await web3.getNetwork()).chainId trackMatomoEvent({ category: 'debugger', action: 'startDebugging', value: networkId, isClick: true }) if (networkId === 42) { setState((prevState) => { @@ -281,9 +281,9 @@ export const DebuggerUI = (props: DebuggerUIProps) => { let currentBlock let currentTransaction try { - currentReceipt = await web3.eth.getTransactionReceipt(txNumber) - currentBlock = await web3.eth.getBlock(currentReceipt.blockHash) - currentTransaction = await web3.eth.getTransaction(txNumber) + currentReceipt = await web3.getTransactionReceipt(txNumber) + currentBlock = await web3.getBlock(currentReceipt.blockHash) + currentTransaction = await web3.getTransaction(txNumber) } catch (e) { setState((prevState) => { return { diff --git a/libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts b/libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts index f204b523ed9..b618433fdae 100644 --- a/libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts +++ b/libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts @@ -48,7 +48,7 @@ export interface IDebuggerApi { fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise getFile: (path: string) => Promise setFile: (path: string, content: string) => Promise - getDebugWeb3: () => any // returns an instance of web3.js, if applicable (mainet, goerli, ...) it returns a reference to a node from devops (so we are sure debug endpoint is available) + getDebugProvider: () => any // returns an instance of web3.js, if applicable (mainnet, goerli, ...) it returns a reference to a node from devops (so we are sure debug endpoint is available) web3: () => any // returns an instance of web3.js showMessage (title: string, message: string): void onStartDebugging (debuggerBackend: any): void // called when debug starts diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx index fdce3cc613c..ddda935b380 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx @@ -4,9 +4,12 @@ import {TreeView, TreeViewItem} from '@remix-ui/tree-view' // eslint-disable-lin import {DropdownPanelProps, ExtractData, ExtractFunc} from '../../types' // eslint-disable-line import {CopyToClipboard} from '@remix-ui/clipboard' // eslint-disable-line import { initialState, reducer } from '../../reducers/calldata' -import { isBigInt } from 'web3-validator' import './styles/dropdown-panel.css' +const isBigInt = (value) => { + return typeof value === 'bigint' +} + export const DropdownPanel = (props: DropdownPanelProps) => { const intl = useIntl() const [calldataObj, dispatch] = useReducer(reducer, initialState) @@ -56,7 +59,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => { } const formatSelfDefault = (key: string | number, data: ExtractData) => { let value - if (isBigInt(data.self)) data.self = data.self.toString() + if (isBigInt(data.self)) data.self = (data.self as any).toString() if (hexHighlight && typeof data.self === 'string') { const isHex = data.self.startsWith('0x') || hexHighlight if (isHex) { diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/global-variables.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/global-variables.tsx index 33d9e6c1f8b..bd32cb37834 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/global-variables.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/global-variables.tsx @@ -1,6 +1,5 @@ import React from 'react' // eslint-disable-line import DropdownPanel from './dropdown-panel' // eslint-disable-line -import {toBigInt} from 'web3-utils' // eslint-disable-line export const GlobalVariables = ({ block, receipt, tx, className }) => { // see https://docs.soliditylang.org/en/latest/units-and-global-variables.html#block-and-transaction-properties @@ -17,7 +16,7 @@ export const GlobalVariables = ({ block, receipt, tx, className }) => { 'tx.origin': tx && tx.from } if (block && block.baseFeePerGas) { - globals['block.basefee'] = toBigInt(block.baseFeePerGas).toString(10) + ` Wei (${block.baseFeePerGas})` + globals['block.basefee'] = BigInt(block.baseFeePerGas).toString(10) + ` Wei (${block.baseFeePerGas})` } return ( diff --git a/libs/remix-ui/editor/src/lib/web-types.ts b/libs/remix-ui/editor/src/lib/web-types.ts index db0afa8da59..0ad23ec31a0 100644 --- a/libs/remix-ui/editor/src/lib/web-types.ts +++ b/libs/remix-ui/editor/src/lib/web-types.ts @@ -177,35 +177,6 @@ export const loadTypes = async (monaco) => { indexEthersDefault = indexEthersDefault.replace(/@ethersproject\//g, '@ethersproject_') monaco.languages.typescript.typescriptDefaults.addExtraLib(indexEthersDefault, `file:///node_modules/@types/ethers/index.d.ts`) */ - // Web3 - - // @ts-ignore - const indexWeb3 = await import('raw-loader!web3') - monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3.default, `file:///node_modules/web3/lib/types/index.d.ts`) - - // @ts-ignore - const indexWeb3Core = await import('raw-loader!web3-core') - monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Core.default, `file:///node_modules/web3-core/lib/types/index.d.ts`) - - // @ts-ignore - const indexWeb3Eth = await import('raw-loader!web3-eth') - monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Eth.default, `file:///node_modules/web3-eth/lib/types/index.d.ts`) - - // @ts-ignore - const indexWeb3Personal = await import('raw-loader!web3-eth-personal') - monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Personal.default, `file:///node_modules/web3-eth-personal/lib/types/index.d.ts`) - - // @ts-ignore - const indexWeb3Contract = await import('raw-loader!web3-eth-contract') - monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Contract.default, `file:///node_modules/web3-eth-contract/lib/types/index.d.ts`) - - // @ts-ignore - const indexWeb3Net = await import('raw-loader!web3-net') - monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Net.default, `file:///node_modules/web3-net/lib/types/index.d.ts`) - - // @ts-ignore - const indexWeb3Util = await import('raw-loader!web3-utils') - monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Util.default, `file:///node_modules/web3-utils/lib/types/index.d.ts`) // remix const indexRemixApi = remixTypes + `\n declare global { diff --git a/libs/remix-ui/run-tab/src/lib/actions/account.ts b/libs/remix-ui/run-tab/src/lib/actions/account.ts index 3ef09b2a77f..e93483961ff 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/account.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/account.ts @@ -124,7 +124,7 @@ export const delegationAuthorization = async (contractAddress: string, plugin: R const provider = { request: async (query) => { const ret = await plugin.call('web3Provider', 'sendAsync', query) - return ret.result + return ret } } 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 9332c4558e4..022ea7323f0 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/deploy.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/deploy.ts @@ -10,7 +10,7 @@ import { DeployMode, MainnetPrompt } from "../types" import { displayNotification, fetchProxyDeploymentsSuccess, setDecodedResponse, updateInstancesBalance } from "./payload" import { addInstance } from "./actions" import { addressToString, logBuilder } from "@remix-ui/helper" -import { Web3 } from "web3" +import { isAddress } from "ethers" const txHelper = remixLib.execution.txHelper const txFormat = remixLib.execution.txFormat @@ -409,8 +409,8 @@ export const isValidContractAddress = async (plugin: RunTab, address: string) => if (!address) { return false } else { - if (Web3.utils.isAddress(address)) { - return await plugin.blockchain.web3().eth.getCode(address) !== '0x' + if (isAddress(address)) { + return await plugin.blockchain.web3().getCode(address) !== '0x' } else { return false } diff --git a/libs/remix-ui/run-tab/src/lib/actions/events.ts b/libs/remix-ui/run-tab/src/lib/actions/events.ts index bf827465e4f..51c84dbf03e 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/events.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/events.ts @@ -7,10 +7,10 @@ import { addDeployOption, clearAllInstances, clearRecorderCount, fetchContractLi import { updateInstanceBalance } from './deploy' import { CompilerAbstract } from '@remix-project/remix-solidity' import BN from 'bn.js' -import { Web3 } from 'web3' import { Plugin } from "@remixproject/engine" import { getNetworkProxyAddresses } from "./deploy" import { shortenAddress } from "@remix-ui/helper" +import { parseUnits } from "ethers" let dispatch: React.Dispatch = () => {} @@ -287,7 +287,7 @@ export const resetAndInit = (plugin: RunTab) => { const number = plugin.REACT_API.sendValue const unit = plugin.REACT_API.sendUnit - cb(null, Web3.utils.toWei(number, unit)) + cb(null, parseUnits(number, unit)) } catch (e) { cb(e) } diff --git a/libs/remix-ui/run-tab/src/lib/components/account.tsx b/libs/remix-ui/run-tab/src/lib/components/account.tsx index a22af0c257b..ea484727eed 100644 --- a/libs/remix-ui/run-tab/src/lib/components/account.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/account.tsx @@ -79,7 +79,7 @@ export function AccountUI(props: AccountProps) { delegationAuthorizationAddressRef.current = null return } - const code = await props.runTabPlugin.blockchain.web3().eth.getCode(selectedAccount) + const code = await props.runTabPlugin.blockchain.web3().getCode(selectedAccount) if (code && code.startsWith(eip7702Constants.EIP7702_CODE_INDICATOR_FLAG)) { // see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7702.md delegation indicator const address = '0x' + code.replace(eip7702Constants.EIP7702_CODE_INDICATOR_FLAG, '') diff --git a/libs/remix-ui/run-tab/src/lib/components/mainnet.tsx b/libs/remix-ui/run-tab/src/lib/components/mainnet.tsx index 80de6e4996c..d971983e6e4 100644 --- a/libs/remix-ui/run-tab/src/lib/components/mainnet.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/mainnet.tsx @@ -2,8 +2,8 @@ import React, { useEffect, useState } from 'react' import { FormattedMessage, useIntl } from 'react-intl' import { CopyToClipboard } from '@remix-ui/clipboard' -import { fromWei, toBigInt, toWei } from 'web3-utils' import { MainnetProps } from '../types' +import { formatUnits, parseUnits } from 'ethers' export function MainnetPrompt(props: MainnetProps) { const intl = useIntl() @@ -15,7 +15,7 @@ export function MainnetPrompt(props: MainnetProps) { if (txFeeText) setTransactionFee(txFeeText) if (gasPriceValue) onGasPriceChange(gasPriceValue) if (props.network && props.network.lastBlock && props.network.lastBlock.baseFeePerGas) { - const baseFee = fromWei(toBigInt(props.network.lastBlock.baseFeePerGas), 'Gwei') + const baseFee = formatUnits(BigInt(props.network.lastBlock.baseFeePerGas), 'gwei') setBaseFee(baseFee) onMaxFeeChange(baseFee) @@ -26,7 +26,7 @@ export function MainnetPrompt(props: MainnetProps) { const onMaxFeeChange = (value: string) => { const maxFee = value - if (toBigInt(props.network.lastBlock.baseFeePerGas) > toBigInt(toWei(maxFee, 'Gwei'))) { + if (BigInt(props.network.lastBlock.baseFeePerGas) > BigInt(parseUnits(maxFee, 'gwei'))) { setTransactionFee(intl.formatMessage({ id: 'udapp.transactionFee' })) props.updateGasPriceStatus(false) props.updateConfirmSettings(true) @@ -124,7 +124,7 @@ export function MainnetPrompt(props: MainnetProps) {
- : + : ) => { return fileName ? fileName.replace(/\//g, '_').replace(/\./g, '_') + testSuite : fileName } - const startDebug = async (txHash: string, web3: Web3) => { + const startDebug = async (txHash: string, provider: any) => { isDebugging.current = true if (!(await testTab.appManager.isActive('debugger'))) await testTab.appManager.activatePlugin('debugger') testTab.call('menuicons', 'select', 'debugger') - testTab.call('debugger', 'debug', txHash, web3) + testTab.call('debugger', 'debug', txHash, provider) } const printHHLogs = (logsArr: Record[], testName: string) => { @@ -359,9 +358,9 @@ export const SolidityUnitTesting = (props: Record) => { if (!test.rendered) { let debugBtn if (test.debugTxHash) { - const { web3, debugTxHash } = test + const { provider, debugTxHash } = test debugBtn = ( -
startDebug(debugTxHash, web3)}> +
startDebug(debugTxHash, provider)}> { if (data.to) to = to + ' ' + shortenHexData(data.to) const val = data.value let hash = data.hash ? shortenHexData(data.hash) : '' - const input = data.input ? shortenHexData(data.input) : '' + console.log('date in context----->', data) + const input = data.input ? shortenHexData(data.input) : (data.data ? shortenHexData(data.data) : '') const logs = opts.logs && opts.logs.raw && opts.logs.raw.length ? opts.logs.raw.length : 0 const block = data.receipt ? data.receipt.blockNumber : data.blockNumber || '' const i = data.receipt ? data.transactionIndex : data.transactionIndex diff --git a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx index a2ad694348c..f7b1b735cd3 100644 --- a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx +++ b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx @@ -1,23 +1,20 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import React, { useState, useEffect, useReducer, useRef, SyntheticEvent, MouseEvent, useContext } from 'react' // eslint-disable-line -import { FormattedMessage, useIntl } from 'react-intl' +import React, { useState, useEffect, useReducer, useRef, SyntheticEvent, useContext } from 'react' // eslint-disable-line +import { useIntl } from 'react-intl' import { registerCommandAction, registerLogScriptRunnerAction, registerInfoScriptRunnerAction, registerErrorScriptRunnerAction, registerWarnScriptRunnerAction, - listenOnNetworkAction, initListeningOnNetwork, } from './actions/terminalAction' -import { isBigInt } from 'web3-validator' -import { initialState, registerCommandReducer, addCommandHistoryReducer, registerScriptRunnerReducer } from './reducers/terminalReducer' +import { initialState, addCommandHistoryReducer, registerScriptRunnerReducer } from './reducers/terminalReducer' import { getKeyOf, getValueOf, Objectfilter, matched } from './utils/utils' import { allCommands, allPrograms } from './commands' // eslint-disable-line import TerminalWelcomeMessage from './terminalWelcome' // eslint-disable-line import { Toaster } from '@remix-ui/toaster' // eslint-disable-line import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line -import { CustomTooltip } from '@remix-ui/helper' import './remix-ui-terminal.css' import vm from 'vm' @@ -571,7 +568,7 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => { const classNameBlock = 'remix_ui_terminal_block px-4 py-1 text-break' const replacer = (key, value) => { - if (isBigInt(value)) value = value.toString() + if (typeof value === 'bigint') value = value.toString() if (typeof value === 'function') value = value.toString() return value } diff --git a/libs/remix-ui/terminal/src/lib/terminalWelcome.tsx b/libs/remix-ui/terminal/src/lib/terminalWelcome.tsx index d4f79b38d2c..e9dca7a0adf 100644 --- a/libs/remix-ui/terminal/src/lib/terminalWelcome.tsx +++ b/libs/remix-ui/terminal/src/lib/terminalWelcome.tsx @@ -44,11 +44,6 @@ const TerminalWelcomeMessage = ({ packageJson, storage }) => { :