Merge pull request #4108 from ethereum/update_web3js_4

Update web3js 4
pull/5370/head
yann300 1 year ago committed by GitHub
commit bdcf3b0424
  1. 1
      README.md
  2. 4
      apps/remix-ide-e2e/src/tests/ballot.test.ts
  3. 4
      apps/remix-ide-e2e/src/tests/ballot_0_4_14.test.ts
  4. 2
      apps/remix-ide-e2e/src/tests/erc721.test.ts
  5. 5
      apps/remix-ide-e2e/src/tests/plugin_api.ts
  6. 2
      apps/remix-ide-e2e/src/tests/recorder.test.ts
  7. 2
      apps/remix-ide-e2e/src/tests/remixd.test.ts
  8. 4
      apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts
  9. 2
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  10. 16
      apps/remix-ide-e2e/src/tests/transactionExecution.test.ts
  11. 4
      apps/remix-ide-e2e/src/tests/txListener.test.ts
  12. 6
      apps/remix-ide/src/app/plugins/solidity-script.tsx
  13. 8
      apps/remix-ide/src/app/providers/injected-provider.tsx
  14. 6
      apps/remix-ide/src/app/tabs/debugger-tab.js
  15. 3
      apps/remix-ide/src/app/tabs/network-module.js
  16. 18
      apps/remix-ide/src/app/tabs/web3-provider.js
  17. 10
      apps/remix-ide/src/app/udapp/make-udapp.js
  18. 10
      apps/remix-ide/src/app/udapp/run-tab.js
  19. 22
      apps/remix-ide/src/blockchain/blockchain.tsx
  20. 18
      apps/remix-ide/src/blockchain/execution-context.js
  21. 5
      apps/remix-ide/src/blockchain/providers/injected.ts
  22. 17
      apps/remix-ide/src/blockchain/providers/node.ts
  23. 58
      apps/remix-ide/src/blockchain/providers/vm.ts
  24. 5
      libs/ghaction-helper/package.json
  25. 4
      libs/remix-analyzer/package.json
  26. 4
      libs/remix-astwalker/package.json
  27. 4
      libs/remix-debug/package.json
  28. 9
      libs/remix-debug/src/code/codeManager.ts
  29. 70
      libs/remix-debug/src/init.ts
  30. 12
      libs/remix-debug/test/debugger.ts
  31. 87
      libs/remix-debug/test/decoder/localsTests/calldata.ts
  32. 245
      libs/remix-debug/test/decoder/localsTests/int.ts
  33. 127
      libs/remix-debug/test/decoder/localsTests/misc.ts
  34. 99
      libs/remix-debug/test/decoder/localsTests/misc2.ts
  35. 217
      libs/remix-debug/test/decoder/localsTests/structArray.ts
  36. 35
      libs/remix-debug/test/decoder/stateTests/mapping.ts
  37. 2
      libs/remix-debug/test/vmCall.ts
  38. 5
      libs/remix-lib/package.json
  39. 2
      libs/remix-lib/src/execution/logsManager.ts
  40. 21
      libs/remix-lib/src/execution/txListener.ts
  41. 8
      libs/remix-lib/src/execution/txRunnerVM.ts
  42. 134
      libs/remix-lib/src/execution/txRunnerWeb3.ts
  43. 5
      libs/remix-lib/src/execution/typeConversion.ts
  44. 68
      libs/remix-lib/src/init.ts
  45. 5
      libs/remix-simulator/package.json
  46. 21
      libs/remix-simulator/src/VmProxy.ts
  47. 12
      libs/remix-simulator/src/methods/accounts.ts
  48. 44
      libs/remix-simulator/src/methods/transactions.ts
  49. 8
      libs/remix-simulator/src/methods/txProcess.ts
  50. 76
      libs/remix-simulator/src/provider.ts
  51. 4
      libs/remix-simulator/src/vm-context.ts
  52. 12
      libs/remix-simulator/test/accounts.ts
  53. 46
      libs/remix-simulator/test/blocks.ts
  54. 70
      libs/remix-simulator/test/misc.ts
  55. 4
      libs/remix-solidity/package.json
  56. 4
      libs/remix-tests/package.json
  57. 4
      libs/remix-tests/src/deployer.ts
  58. 3
      libs/remix-tests/src/run.ts
  59. 14
      libs/remix-tests/src/runTestFiles.ts
  60. 4
      libs/remix-tests/src/runTestSources.ts
  61. 23
      libs/remix-tests/src/testRunner.ts
  62. 24
      libs/remix-tests/tests/testRunner.cli.spec.ts
  63. 44
      libs/remix-tests/tests/testRunner.spec.ts
  64. 4
      libs/remix-ui/debugger-ui/src/lib/api/debugger-api.ts
  65. 8
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx
  66. 5
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/global-variables.tsx
  67. 36
      libs/remix-ui/editor/src/lib/web-types.ts
  68. 8
      libs/remix-ui/run-tab/src/lib/components/mainnet.tsx
  69. 4
      libs/remix-ws-templates/package.json
  70. 3
      package.json
  71. 1305
      yarn.lock

@ -279,7 +279,6 @@ parameters:
default: true
```
## Important Links
- Official website: https://remix-project.org

@ -34,7 +34,7 @@ module.exports = {
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
status: '0x1 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: 'false Transaction mined but execution failed',
status: '0x0 Transaction mined but execution failed',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
},

@ -43,7 +43,7 @@ module.exports = {
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
},
@ -83,7 +83,7 @@ module.exports = {
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
},

@ -61,7 +61,7 @@ module.exports = {
.createContract('')
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded input': {}
}).end()
}

@ -31,12 +31,7 @@ const debugValues = async function (browser: NightwatchBrowser, field: string, e
return
}
browser.waitForElementVisible(`//*[@id="${field}"]`).getText(`//*[@id="${field}"]`, (result) => {
console.log(result)
if (!result.value.toString().includes(expected)) {
console.log('Actual result:')
console.log(result.value.toString())
console.log('Expected result:')
console.log(expected)
getBrowserLogs(browser)
browser.assert.ok(false, 'Returned value from call does not match expected value.')
} else {

@ -96,7 +96,7 @@ module.exports = {
.pause(1000)
.clickFunction('set2 - transact (not payable)', { types: 'uint256 _po', values: '10' })
.testFunction('last', {
status: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded input': { 'uint256 _po': '10' }
})
},

@ -250,7 +250,7 @@ module.exports = {
.createContract('')
.testFunction('last',
{
status: 'true Transaction mined and execution succeed'
status: '0x1 Transaction mined and execution succeed'
})

@ -61,7 +61,7 @@ module.exports = {
.click('*[data-id="Deploy - transact (not payable)"]')
.pause(5000)
.testFunction('last', {
status: 'true Transaction mined and execution succeed'
status: '0x1 Transaction mined and execution succeed'
})
},
@ -95,7 +95,7 @@ module.exports = {
.click('*[data-id="pluginManagerSettingsDeployAndRunLLTxSendTransaction"]')
.pause(5000)
.testFunction('last', {
status: 'true Transaction mined and execution succeed'
status: '0x1 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

@ -757,7 +757,7 @@ const scriptBlockAndTransaction = `
(async () => {
try {
web3.eth.getTransaction('0x022ccd55747677ac50f8d9dfd1bf5b843fa2f36438a28c1d0a0958e057bb3e2a').then(console.log)
web3.eth.getBlock('7367447').then(console.log);
web3.eth.getBlock(7367447).then(console.log);
let ethersProvider = new ethers.providers.Web3Provider(web3Provider)
ethersProvider.getBlock(7367447).then(console.log)
} catch (e) {

@ -20,13 +20,13 @@ module.exports = {
.clickFunction('f - transact (not payable)')
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded output': { 0: 'uint256: 8' }
})
.clickFunction('g - transact (not payable)')
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded output': {
0: 'uint256: 345',
1: 'string: comment_comment_',
@ -45,7 +45,7 @@ module.exports = {
.clickFunction('retunValues1 - transact (not payable)')
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded output': {
0: 'bool: _b true',
1: 'uint256: _u 345',
@ -56,7 +56,7 @@ module.exports = {
.clickFunction('retunValues2 - transact (not payable)')
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded output': {
0: 'bytes1: _b 0x12',
1: 'bytes2: _b2 0x1223',
@ -73,7 +73,7 @@ module.exports = {
.clickFunction('retunValues3 - transact (not payable)')
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
status: '0x1 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'
@ -89,7 +89,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: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded output': {
0: 'uint256: _uret 2343242',
1: 'int256: _iret -4324324',
@ -99,7 +99,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: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded output': {
0: 'uint256[3]: _nret 1,2,3',
1: 'bytes8[4]: _b8ret 0x1234000000000000,0x1234000000000000,0x1234000000000000,0x1234000000000000'
@ -222,7 +222,7 @@ module.exports = {
.clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '24' })
.testFunction('last', // we check if the contract is actually reachable.
{
status: 'true Transaction mined and execution succeed',
status: '0x1 Transaction mined and execution succeed',
'decoded input': {
'uint256 num': '24'
}

@ -31,7 +31,7 @@ module.exports = {
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
status: '0x1 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: 'false Transaction mined but execution failed',
status: '0x0 Transaction mined but execution failed',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
.end()

@ -2,7 +2,7 @@ import React from 'react' // eslint-disable-line
import {format} from 'util'
import {Plugin} from '@remixproject/engine'
import {compile} from '@remix-project/remix-solidity'
import {TransactionConfig} from 'web3-core'
import {Transaction} from 'web3-types'
const _paq = (window._paq = window._paq || []) //eslint-disable-line
const profile = {
@ -69,7 +69,7 @@ export class SolidityScript extends Plugin {
}
// deploy the contract
let tx: TransactionConfig = {
let tx: Transaction = {
from: accounts[0],
data: bytecode
}
@ -81,7 +81,7 @@ export class SolidityScript extends Plugin {
}
const receiptCall = await web3.eth.sendTransaction(tx)
const hhlogs = await web3.eth.getHHLogsForTx(receiptCall.transactionHash)
const hhlogs = await web3.remix.getHHLogsForTx(receiptCall.transactionHash)
if (hhlogs && hhlogs.length) {
const finalLogs = (

@ -86,12 +86,8 @@ export abstract class InjectedProvider extends Plugin implements IProvider {
}
try {
let resultData
if (web3Provider.send) resultData = await web3Provider.send(data.method, data.params)
else if (web3Provider.request)
resultData = await web3Provider.request({
method: data.method,
params: data.params
})
if (web3Provider.request) resultData = await web3Provider.request({method: data.method, params: data.params})
else if (web3Provider.send) resultData = await web3Provider.send(data.method, data.params)
else {
resolve({jsonrpc: '2.0', error: 'provider not valid', id: data.id})
return

@ -86,9 +86,9 @@ export class DebuggerTab extends DebuggerApiMixin(ViewPlugin) {
'timestamp': block.timestamp,
}
if (block.baseFeePerGas) {
blockContext['basefee'] = Web3.utils.toBN(block.baseFeePerGas).toString(10) + ` Wei (${block.baseFeePerGas})`
blockContext['basefee'] = Web3.utils.toBigInt(block.baseFeePerGas).toString(10) + ` Wei (${block.baseFeePerGas})`
}
const msg = {
const msg = {
'sender': tx.from,
'sig': tx.input.substring(0, 10),
'value': tx.value + ' Wei'
@ -97,7 +97,7 @@ export class DebuggerTab extends DebuggerApiMixin(ViewPlugin) {
const txOrigin = {
'origin': tx.from
}
return {
block: blockContext,
msg,

@ -1,6 +1,7 @@
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json'
import { Web3 } from 'web3'
import IpcProvider from 'web3-providers-ipc'
export const profile = {
name: 'network',
@ -49,7 +50,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 Web3.providers.IpcProvider() : new Web3.providers.HttpProvider(network.url)
const provider = network.url === 'ipc' ? new IpcProvider() : new Web3.providers.HttpProvider(network.url)
this.blockchain.addProvider({ name: network.name, provider })
}

@ -1,5 +1,6 @@
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json'
import {isBigInt} from 'web3-validator'
export const profile = {
name: 'web3Provider',
@ -10,6 +11,11 @@ export const profile = {
kind: 'provider'
}
const replacer = (key, value) => {
if (isBigInt(value)) value = value.toString()
return value
}
export class Web3ProviderModule extends Plugin {
constructor(blockchain) {
super(profile)
@ -23,12 +29,11 @@ export class Web3ProviderModule extends Plugin {
sendAsync(payload) {
return new Promise((resolve, reject) => {
this.askUserPermission('sendAsync', `Calling ${payload.method} with parameters ${JSON.stringify(payload.params, null, '\t')}`).then(
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
// see https://github.com/ethereum/web3.js/pull/1018/files#diff-d25786686c1053b786cc2626dc6e048675050593c0ebaafbf0814e1996f22022R129
provider[provider.sendAsync ? 'sendAsync' : 'send'](payload, async (error, message) => {
const resultFn = async (error, message) => {
if (error) {
// Handle 'The method "debug_traceTransaction" does not exist / is not available.' error
if(error.message && error.code && error.code === -32601) {
@ -55,7 +60,12 @@ export class Web3ProviderModule extends Plugin {
}
}
resolve(message)
})
}
try {
resultFn(null, await provider.sendAsync(payload))
} catch (e) {
resultFn(e.message)
}
} else {
reject(new Error('User denied permission'))
}

@ -10,13 +10,21 @@ export function makeUdapp (blockchain, compilersArtefacts, logHtmlCallback) {
if (_transactionReceipts[tx.hash]) {
return cb(null, _transactionReceipts[tx.hash])
}
blockchain.web3().eth.getTransactionReceipt(tx.hash, (error, receipt) => {
let res = blockchain.web3().eth.getTransactionReceipt(tx.hash, (error, receipt) => {
if (error) {
return cb(error)
}
_transactionReceipts[tx.hash] = receipt
cb(null, receipt)
})
if(res && typeof res.then ==='function'){
res.then((receipt)=>{
_transactionReceipts[tx.hash] = receipt
cb(null, receipt)
}).catch((error)=>{
cb(error)
})
}
}
const txlistener = blockchain.getTxListener({

@ -133,13 +133,9 @@ export class RunTab extends ViewPlugin {
}
},
provider: {
async sendAsync(payload, callback) {
try {
const result = await udapp.call(name, 'sendAsync', payload)
callback(null, result)
} catch (e) {
callback(e)
}
async sendAsync (payload) {
return udapp.call(name, 'sendAsync', payload)
}
}
})

@ -1,5 +1,5 @@
import React from 'react' // eslint-disable-line
import Web3 from 'web3'
import {fromWei, toBigInt, toWei} from 'web3-utils'
import {Plugin} from '@remixproject/engine'
import {toBuffer, addHexPrefix} from '@ethereumjs/util'
import {EventEmitter} from 'events'
@ -244,7 +244,7 @@ export class Blockchain extends Plugin {
const proxyModal = {
id: 'confirmProxyDeployment',
title: 'Confirm Deploy Proxy (ERC1967)',
message: `Confirm you want to deploy an ERC1967 proxy contract that is connected to your implementation.
message: `Confirm you want to deploy an ERC1967 proxy contract that is connected to your implementation.
For more info on ERC1967, see: https://docs.openzeppelin.com/contracts/4.x/api/proxy#ERC1967Proxy`,
modalType: 'modal',
okLabel: 'OK',
@ -477,17 +477,17 @@ export class Blockchain extends Plugin {
fromWei(value, doTypeConversion, unit) {
if (doTypeConversion) {
return Web3.utils.fromWei(typeConversion.toInt(value), unit || 'ether')
return fromWei(typeConversion.toInt(value), unit || 'ether')
}
return Web3.utils.fromWei(value.toString(10), unit || 'ether')
return fromWei(value.toString(10), unit || 'ether')
}
toWei(value, unit) {
return Web3.utils.toWei(value, unit || 'gwei')
return toWei(value, unit || 'gwei')
}
calculateFee(gas, gasPrice, unit?) {
return Web3.utils.toBN(gas).mul(Web3.utils.toBN(Web3.utils.toWei(gasPrice.toString(10) as string, unit || 'gwei')))
return toBigInt(gas) * toBigInt(toWei(gasPrice.toString(10) as string, unit || 'gwei'))
}
determineGasFees(tx) {
@ -552,7 +552,6 @@ export class Blockchain extends Plugin {
}
web3() {
// @todo(https://github.com/ethereum/remix-project/issues/431)
const isVM = this.executionContext.isVM()
if (isVM) {
return (this.providers.vm as VMProvider).web3
@ -749,7 +748,7 @@ export class Blockchain extends Plugin {
if (error) return reject(error)
try {
if (this.executionContext.isVM()) {
const execResult = await this.web3().eth.getExecutionResultFromSimulator(result.transactionHash)
const execResult = await this.web3().remix.getExecutionResultFromSimulator(result.transactionHash)
resolve(resultToRemixTx(result, execResult))
} else resolve(resultToRemixTx(result))
} catch (e) {
@ -870,7 +869,7 @@ export class Blockchain extends Plugin {
const isVM = this.executionContext.isVM()
if (isVM && tx.useCall) {
try {
result.transactionHash = await this.web3().eth.getHashFromTagBySimulator(timestamp)
result.transactionHash = await this.web3().remix.getHashFromTagBySimulator(timestamp)
} catch (e) {
console.log('unable to retrieve back the "call" hash', e)
}
@ -911,7 +910,7 @@ export class Blockchain extends Plugin {
let execResult
let returnValue = null
if (isVM) {
const hhlogs = await this.web3().eth.getHHLogsForTx(txResult.transactionHash)
const hhlogs = await this.web3().remix.getHHLogsForTx(txResult.transactionHash)
if (hhlogs && hhlogs.length) {
const finalLogs = (
@ -937,7 +936,8 @@ export class Blockchain extends Plugin {
_paq.push(['trackEvent', 'udapp', 'hardhat', 'console.log'])
this.call('terminal', 'logHtml', finalLogs)
}
execResult = await this.web3().eth.getExecutionResultFromSimulator(txResult.transactionHash)
execResult = await this.web3().remix.getExecutionResultFromSimulator(txResult.transactionHash)
if (execResult) {
// if it's not the VM, we don't have return value. We only have the transaction, and it does not contain the return value.
returnValue = execResult

@ -36,7 +36,7 @@ export class ExecutionContext {
init (config) {
this.executionContext = 'vm-shanghai'
this.event.trigger('contextChanged', [this.executionContext])
}
}
getProvider () {
return this.executionContext
@ -74,7 +74,7 @@ export class ExecutionContext {
if (!web3.currentProvider) {
return callback('No provider set')
}
web3.eth.net.getId((err, id) => {
const cb = (err, id) => {
let name = null
if (err) name = 'Unknown'
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
@ -95,7 +95,11 @@ export class ExecutionContext {
} else {
callback(err, { id, name, lastBlock: this.lastBlock, currentFork: this.currentFork })
}
})
}
const res = web3.eth.net.getId(cb)
if(res && typeof res.then ==='function'){
res.then(id=>cb(null,id)).catch(err=>cb(err))
}
}
}
@ -117,7 +121,7 @@ export class ExecutionContext {
internalWeb3 () {
return web3
}
setContext (context, endPointUrl, confirmCb, infoCb) {
this.executionContext = context
this.executionContextChange(context, endPointUrl, confirmCb, infoCb, null)
@ -128,9 +132,9 @@ export class ExecutionContext {
const context = value.context
if (!cb) cb = () => { /* Do nothing. */ }
if (!confirmCb) confirmCb = () => { /* Do nothing. */ }
if (!infoCb) infoCb = () => { /* Do nothing. */ }
if (!infoCb) infoCb = () => { /* Do nothing. */ }
if (this.customNetWorks[context]) {
var network = this.customNetWorks[context]
var network = this.customNetWorks[context]
await network.init()
this.currentFork = network.fork
this.executionContext = context
@ -156,7 +160,7 @@ export class ExecutionContext {
try {
const block = await web3.eth.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(block.gasLimit - (5 * block.gasLimit) / 1024) : this.blockGasLimitDefault
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.lastBlock = block
try {
this.currentFork = execution.forkAt(await web3.eth.net.getId(), block.number)

@ -1,5 +1,5 @@
import Web3 from 'web3'
import { hashPersonalMessage } from '@ethereumjs/util'
import { hashPersonalMessage, isHexString } from '@ethereumjs/util'
import { ExecutionContext } from '../execution-context'
export class InjectedProvider {
@ -20,7 +20,7 @@ export class InjectedProvider {
}
async resetEnvironment () {
/* Do nothing. */
/* Do nothing. */
}
async getBalanceInEther (address) {
@ -35,6 +35,7 @@ export class InjectedProvider {
signMessage (message, account, _passphrase, cb) {
const messageHash = hashPersonalMessage(Buffer.from(message))
try {
message = isHexString(message) ? message : Web3.utils.utf8ToHex(message)
this.executionContext.web3().eth.personal.sign(message, account, (error, signedData) => {
cb(error, '0x' + messageHash.toString('hex'), signedData)
})

@ -1,5 +1,5 @@
import Web3 from 'web3'
import { hashPersonalMessage } from '@ethereumjs/util'
import { hashPersonalMessage, isHexString } from '@ethereumjs/util'
import { Personal } from 'web3-eth-personal'
import { ExecutionContext } from '../execution-context'
import Config from '../../config'
@ -15,9 +15,9 @@ export class NodeProvider {
getAccounts (cb) {
if (this.config.get('settings/personal-mode')) {
return this.executionContext.web3().eth.personal.getAccounts(cb)
return this.executionContext.web3().eth.personal.getAccounts().then(res => cb(null, res)).catch(err => cb(err))
}
return this.executionContext.web3().eth.getAccounts(cb)
return this.executionContext.web3().eth.getAccounts().then(res => cb(null, res)).catch(err => cb(err))
}
newAccount (passwordPromptCb, cb) {
@ -25,7 +25,7 @@ export class NodeProvider {
return cb('Not running in personal mode')
}
passwordPromptCb((passphrase) => {
this.executionContext.web3().eth.personal.newAccount(passphrase, cb)
this.executionContext.web3().eth.personal.newAccount(passphrase).then(res => cb(null, res)).catch(err => cb(err))
})
}
@ -39,16 +39,17 @@ export class NodeProvider {
}
getGasPrice (cb) {
this.executionContext.web3().eth.getGasPrice(cb)
this.executionContext.web3().eth.getGasPrice().then(res => cb(null, res)).catch(err => cb(err))
}
signMessage (message, account, passphrase, cb) {
const messageHash = hashPersonalMessage(Buffer.from(message))
try {
const personal = new Personal(this.executionContext.web3().currentProvider)
personal.sign(message, account, passphrase, (error, signedData) => {
cb(error, '0x' + messageHash.toString('hex'), signedData)
})
message = isHexString(message) ? message : Web3.utils.utf8ToHex(message)
personal.sign(message, account, passphrase)
.then(signedData => cb(undefined, '0x' + messageHash.toString('hex'), signedData))
.catch(error => cb(error, '0x' + messageHash.toString('hex'), undefined))
} catch (e) {
cb(e.message)
}

@ -1,6 +1,6 @@
import Web3 from 'web3'
import { privateToAddress, hashPersonalMessage } from '@ethereumjs/util'
import BN from 'bn.js'
import Web3, { FMT_BYTES, FMT_NUMBER, LegacySendAsyncProvider } from 'web3'
import { fromWei, toBigInt } from 'web3-utils'
import { privateToAddress, hashPersonalMessage, isHexString } from '@ethereumjs/util'
import { extend, JSONRPCRequestPayload, JSONRPCResponseCallback } from '@remix-project/remix-simulator'
import { ExecutionContext } from '../execution-context'
@ -14,6 +14,7 @@ export class VMProvider {
newAccountCallback: {[stamp: number]: (error: Error, address: string) => void}
constructor (executionContext: ExecutionContext) {
this.executionContext = executionContext
this.worker = null
this.provider = null
@ -21,12 +22,11 @@ export class VMProvider {
}
getAccounts (cb) {
this.web3.eth.getAccounts((err, accounts) => {
if (err) {
return cb('No accounts?')
}
return cb(null, accounts)
})
this.web3.eth.getAccounts()
.then(accounts => cb(null, accounts))
.catch(err => {
cb('No accounts?')
})
}
async resetEnvironment () {
@ -36,22 +36,32 @@ export class VMProvider {
let incr = 0
const stamps = {}
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
this.worker.addEventListener('message', (msg) => {
if (msg.data.cmd === 'sendAsyncResult' && stamps[msg.data.stamp]) {
stamps[msg.data.stamp](msg.data.error, msg.data.result)
if (stamps[msg.data.stamp].callback) {
stamps[msg.data.stamp].callback(msg.data.error, msg.data.result)
return
}
if (msg.data.error) {
stamps[msg.data.stamp].reject(msg.data.error)
} else {
stamps[msg.data.stamp].resolve(msg.data.result)
}
} else if (msg.data.cmd === 'initiateResult') {
if (!msg.data.error) {
this.provider = {
sendAsync: (query, callback) => {
const stamp = Date.now() + incr
incr++
stamps[stamp] = callback
this.worker.postMessage({ cmd: 'sendAsync', query, stamp })
return new Promise((resolve, reject) => {
const stamp = Date.now() + incr
incr++
stamps[stamp] = { callback, resolve, reject }
this.worker.postMessage({ cmd: 'sendAsync', query, stamp })
})
}
}
this.web3 = new Web3(this.provider)
this.web3 = new Web3(this.provider as LegacySendAsyncProvider)
extend(this.web3)
this.executionContext.setWeb3(this.executionContext.getProvider(), this.web3)
resolve({})
@ -85,8 +95,8 @@ export class VMProvider {
}
async getBalanceInEther (address) {
const balance = await this.web3.eth.getBalance(address)
return Web3.utils.fromWei(new BN(balance).toString(10), 'ether')
const balance = await this.web3.eth.getBalance(address, undefined, { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX })
return fromWei(toBigInt(balance).toString(10), 'ether')
}
getGasPrice (cb) {
@ -95,12 +105,10 @@ export class VMProvider {
signMessage (message, account, _passphrase, cb) {
const messageHash = hashPersonalMessage(Buffer.from(message))
this.web3.eth.sign(message, account, (error, signedData) => {
if (error) {
return cb(error)
}
cb(null, '0x' + messageHash.toString('hex'), signedData)
})
message = isHexString(message) ? message : Web3.utils.utf8ToHex(message)
this.web3.eth.sign(message, account)
.then(signedData => cb(null, '0x' + messageHash.toString('hex'), signedData))
.catch(error => cb(error))
}
getProvider () {

@ -28,8 +28,9 @@
"@remix-project/remix-simulator": "^0.2.33",
"chai": "^4.3.7",
"ethers": "^5.7.2",
"web3": "^1.5.3"
"web3": "^4.1.1"
},
"types": "./src/index.d.ts",
"gitHead": "b6db2a29c223e423c70f06b87d9b245e26f0b220"
}
}

@ -31,7 +31,7 @@
"ethers": "^5.4.2",
"ethjs-util": "^0.1.6",
"string-similarity": "^4.0.4",
"web3": "^1.5.1"
"web3": "^4.1.1"
},
"publishConfig": {
"access": "public"
@ -52,4 +52,4 @@
"typings": "src/index.d.ts",
"gitHead": "b6db2a29c223e423c70f06b87d9b245e26f0b220",
"main": "./src/index.js"
}
}

@ -47,7 +47,7 @@
"tape": "^4.10.1",
"ts-node": "^8.0.3",
"typescript": "^3.4.3",
"web3": "^1.5.1"
"web3": "^4.1.1"
},
"devDependencies": {
"tap-spec": "^5.0.0"
@ -55,4 +55,4 @@
"typings": "src/index.d.ts",
"gitHead": "b6db2a29c223e423c70f06b87d9b245e26f0b220",
"types": "./src/index.d.ts"
}
}

@ -41,7 +41,7 @@
"merge": "^2.1.1",
"string-similarity": "^4.0.4",
"time-stamp": "^2.2.0",
"web3": "^1.5.1"
"web3": "^4.1.1"
},
"devDependencies": {
"@babel/core": "^7.4.5",
@ -71,4 +71,4 @@
"typings": "src/index.d.ts",
"gitHead": "b6db2a29c223e423c70f06b87d9b245e26f0b220",
"types": "./src/index.d.ts"
}
}

@ -26,12 +26,9 @@ export class CodeManager {
this.codeResolver = new CodeResolver({
getCode: async (address) => {
return new Promise((resolve, reject) => {
this.traceManager.web3.eth.getCode(address, (error, code) => {
if (error) {
return reject(error)
}
return resolve(code)
})
this.traceManager.web3.eth.getCode(address)
.then(code => resolve(code))
.catch(error => reject(error))
})
},
fork: this.traceManager.getCurrentFork()

@ -1,18 +1,20 @@
'use strict'
import Web3 from 'web3'
import Web3, { Web3PluginBase } from 'web3'
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))
extend(web3)
extendWeb3(web3)
return web3
}
export function extendWeb3 (web3) {
extend(web3)
}
export function setProvider (web3, url) {
web3.setProvider(new web3.providers.HttpProvider(url))
}
@ -31,43 +33,33 @@ export function web3DebugNode (network) {
return null
}
export function extend (web3) {
if (!web3.extend) {
return
}
// DEBUG
const methods = []
if (!(web3.debug && web3.debug.preimage)) {
methods.push(new web3.extend.Method({
name: 'preimage',
call: 'debug_preimage',
inputFormatter: [null],
params: 1
}))
}
class Web3DebugPlugin extends Web3PluginBase {
public pluginNamespace = 'debug'
if (!(web3.debug && web3.debug.traceTransaction)) {
methods.push(new web3.extend.Method({
name: 'traceTransaction',
call: 'debug_traceTransaction',
inputFormatter: [null, null],
params: 2
}))
public preimage(key, cb) {
this.requestManager.send({
method: 'debug_preimage',
params: [key]
})
.then(result => cb(null, result))
.catch(error => cb(error))
}
if (!(web3.debug && web3.debug.storageRangeAt)) {
methods.push(new web3.extend.Method({
name: 'storageRangeAt',
call: 'debug_storageRangeAt',
inputFormatter: [null, null, null, null, null],
params: 5
}))
public traceTransaction(txHash, options, cb) {
this.requestManager.send({
method: 'debug_traceTransaction',
params: [txHash, options]
})
.then(result => cb(null, result))
.catch(error => cb(error))
}
if (methods.length > 0) {
web3.extend({
property: 'debug',
methods: methods,
properties: []
public storageRangeAt(txBlockHash, txIndex, address, start, maxSize, cb) {
this.requestManager.send({
method: 'debug_storageRangeAt',
params: [txBlockHash, txIndex, address, start, maxSize]
})
.then(result => cb(null, result))
.catch(error => cb(error))
}
}

@ -156,15 +156,13 @@ contract Ballot {
output = JSON.parse(output)
const param = '0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000148656c6c6f20576f726c64210000000000000000000000000000000000000000'
const web3 = await vmCall.getWeb3()
vmCall.sendTx(web3, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['Ballot'].evm.bytecode.object + param, (error, hash) => {
vmCall.sendTx(web3, {nonce: 0, privateKey: privateKey}, undefined, 0, output.contracts['test.sol']['Ballot'].evm.bytecode.object + param, (error, hash) => {
console.log(error, hash)
if (error) {
throw error
} else {
web3.eth.getTransaction(hash, (error, tx) => {
if (error) {
throw error
} else {
web3.eth.getTransaction(hash)
.then(tx => {
const sources = {
target: 'test.sol',
sources: { 'test.sol': { content: ballot } }
@ -193,8 +191,8 @@ contract Ballot {
})
debugManager.debug(tx)
}
})
})
.catch(error => { throw error })
}
})
})()

@ -15,7 +15,7 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe
let web3
try {
web3 = await (vmCall as any).getWeb3()
const hash = await (vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode)
const hash = await (vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, undefined, 0, contractBytecode)
const receipt = await web3.eth.getTransactionReceipt(hash)
const to = receipt.contractAddress
console.log('to', to)
@ -25,52 +25,51 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe
return st.fail(e)
}
return new Promise((resolve) => {
web3.eth.getTransaction(txHash, function (error, tx) {
if (error) {
return st.fail(error)
}
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResult
})
const debuggerEvent = new EventManager()
const offsetToLineColumnConverter = {
offsetToLineColumn: (rawLocation) => {
return new Promise((resolve) => {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(contractCode)
resolve(sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, lineBreaks))
})
}
}
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }, offsetToLineColumnConverter)
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeNotReady', (reason) => {
st.fail(reason)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 140, traceManager, callTree, function (locals) {
try {
const expected = {"p":{"value":"45","type":"uint256"},"foo":{"length":"1","value":[{"value":"3","type":"uint8"}],"type":"uint8[1]"},"boo":{"length":"1","value":[{"length":"2","value":[{"value":"R","type":"string"},{"value":"T","type":"string"}],"type":"string[2]"}],"type":"string[2][1]"}}
st.deepEqual(locals, expected)
} catch (e) {
st.fail(e.message)
web3.eth.getTransaction(txHash)
.then(tx => {
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResult
})
const debuggerEvent = new EventManager()
const offsetToLineColumnConverter = {
offsetToLineColumn: (rawLocation) => {
return new Promise((resolve) => {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(contractCode)
resolve(sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, lineBreaks))
})
}
resolve({})
}
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }, offsetToLineColumnConverter)
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
})
callTree.event.register('callTreeNotReady', (reason) => {
st.fail(reason)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 140, traceManager, callTree, function (locals) {
try {
const expected = {"p":{"value":"45","type":"uint256"},"foo":{"length":"1","value":[{"value":"3","type":"uint8"}],"type":"uint8[1]"},"boo":{"length":"1","value":[{"length":"2","value":[{"value":"R","type":"string"},{"value":"T","type":"string"}],"type":"string[2]"}],"type":"string[2][1]"}}
st.deepEqual(locals, expected)
} catch (e) {
st.fail(e.message)
}
resolve({})
})
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
})
.catch(error => st.fail(error))
})
}

@ -14,141 +14,140 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult,
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve) => {
const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, undefined, 0, contractBytecode, function (error, hash) {
if (error) {
return st.fail(error)
}
web3.eth.getTransaction(hash, function (error, tx) {
if (error) {
return st.fail(error)
}
tx.to = contractCreationToken('0')
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResult
})
const debuggerEvent = new EventManager()
const offsetToLineColumnConverter = {
offsetToLineColumn: (rawLocation) => {
return new Promise((resolve) => {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(contractCode)
resolve(sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, lineBreaks))
})
web3.eth.getTransaction(hash)
.then(tx => {
tx.to = contractCreationToken('0')
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResult
})
const debuggerEvent = new EventManager()
const offsetToLineColumnConverter = {
offsetToLineColumn: (rawLocation) => {
return new Promise((resolve) => {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(contractCode)
resolve(sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, lineBreaks))
})
}
}
}
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }, offsetToLineColumnConverter)
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeNotReady', (reason) => {
st.fail(reason)
})
callTree.event.register('callTreeReady', async (scopes, scopeStarts) => {
try {
// test gas cost per line
st.equals((await callTree.getGasCostPerLine(0, 16)).gasCost, 11)
st.equals((await callTree.getGasCostPerLine(0, 32)).gasCost, 84)
const functions1 = callTree.retrieveFunctionsStack(103)
const functions2 = callTree.retrieveFunctionsStack(116)
const functions3 = callTree.retrieveFunctionsStack(13)
st.equals(functions1.length, 2)
st.equals(functions2.length, 3)
st.equals(functions3.length, 1)
st.equal(functions1[0].gasCost, 54)
st.equal(functions1[1].gasCost, 436)
st.equal(functions2[0].gasCost, 23)
st.equal(functions2[1].gasCost, 54)
st.equal(functions2[2].gasCost, 436)
st.equals(Object.keys(functions1[0])[0], 'functionDefinition')
st.equals(Object.keys(functions1[0])[1], 'inputs')
st.equals(functions1[0].inputs[0], 'foo')
st.equals(Object.keys(functions2[0])[0], 'functionDefinition')
st.equals(Object.keys(functions2[0])[1], 'inputs')
st.equals(Object.keys(functions2[1])[0], 'functionDefinition')
st.equals(Object.keys(functions2[1])[1], 'inputs')
st.equals(functions2[0].inputs[0], 'asd')
st.equals(functions2[1].inputs[0], 'foo')
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }, offsetToLineColumnConverter)
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeNotReady', (reason) => {
st.fail(reason)
})
callTree.event.register('callTreeReady', async (scopes, scopeStarts) => {
try {
st.equals(functions1[0].functionDefinition.name, 'level11')
st.equals(functions2[0].functionDefinition.name, 'level12')
st.equals(functions2[1].functionDefinition.name, 'level11')
st.equals(scopeStarts[0], '1')
st.equals(scopeStarts[10], '1.1')
st.equals(scopeStarts[102], '1.1.1')
st.equals(scopeStarts[115], '1.1.1.1')
st.equals(scopeStarts[136], '1.1.2')
st.equals(scopeStarts[153], '1.1.3')
st.equals(scopeStarts[166], '1.1.3.1')
st.equals(scopes['1.1'].locals['ui8'].type.typeName, 'uint8')
st.equals(scopes['1.1'].locals['ui16'].type.typeName, 'uint16')
st.equals(scopes['1.1'].locals['ui32'].type.typeName, 'uint32')
st.equals(scopes['1.1'].locals['ui64'].type.typeName, 'uint64')
st.equals(scopes['1.1'].locals['ui128'].type.typeName, 'uint128')
st.equals(scopes['1.1'].locals['ui256'].type.typeName, 'uint256')
st.equals(scopes['1.1'].locals['ui'].type.typeName, 'uint256')
st.equals(scopes['1.1'].locals['i8'].type.typeName, 'int8')
st.equals(scopes['1.1'].locals['i16'].type.typeName, 'int16')
st.equals(scopes['1.1'].locals['i32'].type.typeName, 'int32')
st.equals(scopes['1.1'].locals['i64'].type.typeName, 'int64')
st.equals(scopes['1.1'].locals['i128'].type.typeName, 'int128')
st.equals(scopes['1.1'].locals['i256'].type.typeName, 'int256')
st.equals(scopes['1.1'].locals['i'].type.typeName, 'int256')
st.equals(scopes['1.1'].locals['ishrink'].type.typeName, 'int32')
st.equals(scopes['1.1.1'].locals['ui8'].type.typeName, 'uint8')
st.equals(scopes['1.1.1.1'].locals['ui81'].type.typeName, 'uint8')
st.equals(scopes['1.1.2'].locals['ui81'].type.typeName, 'uint8')
st.equals(scopes['1.1.3'].locals['ui8'].type.typeName, 'uint8')
st.equals(scopes['1.1.3.1'].locals['ui81'].type.typeName, 'uint8')
} catch (e) {
st.fail(e.message)
}
// test gas cost per line
st.equals((await callTree.getGasCostPerLine(0, 16)).gasCost, 11)
st.equals((await callTree.getGasCostPerLine(0, 32)).gasCost, 84)
const functions1 = callTree.retrieveFunctionsStack(103)
const functions2 = callTree.retrieveFunctionsStack(116)
const functions3 = callTree.retrieveFunctionsStack(13)
helper.decodeLocals(st, 95, traceManager, callTree, function (locals) {
st.equals(Object.keys(locals).length, 16)
st.equals(locals['ui8'].value, '130')
st.equals(locals['ui16'].value, '456')
st.equals(locals['ui32'].value, '4356')
st.equals(locals['ui64'].value, '3543543543')
st.equals(locals['ui128'].value, '234567')
st.equals(locals['ui256'].value, '115792089237316195423570985008687907853269984665640564039457584007880697216513')
st.equals(locals['ui'].value, '123545666')
st.equals(locals['i8'].value, '-45')
st.equals(locals['i16'].value, '-1234')
st.equals(locals['i32'].value, '3455')
st.equals(locals['i64'].value, '-35566')
st.equals(locals['i128'].value, '-444444')
st.equals(locals['i256'].value, '3434343')
st.equals(locals['i'].value, '-32432423423')
st.equals(locals['ishrink'].value, '2')
})
st.equals(functions1.length, 2)
st.equals(functions2.length, 3)
st.equals(functions3.length, 1)
helper.decodeLocals(st, 106, traceManager, callTree, function (locals) {
try {
st.equals(locals['ui8'].value, '123')
st.equals(Object.keys(locals).length, 2)
st.equal(functions1[0].gasCost, 54)
st.equal(functions1[1].gasCost, 436)
st.equal(functions2[0].gasCost, 23)
st.equal(functions2[1].gasCost, 54)
st.equal(functions2[2].gasCost, 436)
st.equals(Object.keys(functions1[0])[0], 'functionDefinition')
st.equals(Object.keys(functions1[0])[1], 'inputs')
st.equals(functions1[0].inputs[0], 'foo')
st.equals(Object.keys(functions2[0])[0], 'functionDefinition')
st.equals(Object.keys(functions2[0])[1], 'inputs')
st.equals(Object.keys(functions2[1])[0], 'functionDefinition')
st.equals(Object.keys(functions2[1])[1], 'inputs')
st.equals(functions2[0].inputs[0], 'asd')
st.equals(functions2[1].inputs[0], 'foo')
st.equals(functions1[0].functionDefinition.name, 'level11')
st.equals(functions2[0].functionDefinition.name, 'level12')
st.equals(functions2[1].functionDefinition.name, 'level11')
st.equals(scopeStarts[0], '1')
st.equals(scopeStarts[10], '1.1')
st.equals(scopeStarts[102], '1.1.1')
st.equals(scopeStarts[115], '1.1.1.1')
st.equals(scopeStarts[136], '1.1.2')
st.equals(scopeStarts[153], '1.1.3')
st.equals(scopeStarts[166], '1.1.3.1')
st.equals(scopes['1.1'].locals['ui8'].type.typeName, 'uint8')
st.equals(scopes['1.1'].locals['ui16'].type.typeName, 'uint16')
st.equals(scopes['1.1'].locals['ui32'].type.typeName, 'uint32')
st.equals(scopes['1.1'].locals['ui64'].type.typeName, 'uint64')
st.equals(scopes['1.1'].locals['ui128'].type.typeName, 'uint128')
st.equals(scopes['1.1'].locals['ui256'].type.typeName, 'uint256')
st.equals(scopes['1.1'].locals['ui'].type.typeName, 'uint256')
st.equals(scopes['1.1'].locals['i8'].type.typeName, 'int8')
st.equals(scopes['1.1'].locals['i16'].type.typeName, 'int16')
st.equals(scopes['1.1'].locals['i32'].type.typeName, 'int32')
st.equals(scopes['1.1'].locals['i64'].type.typeName, 'int64')
st.equals(scopes['1.1'].locals['i128'].type.typeName, 'int128')
st.equals(scopes['1.1'].locals['i256'].type.typeName, 'int256')
st.equals(scopes['1.1'].locals['i'].type.typeName, 'int256')
st.equals(scopes['1.1'].locals['ishrink'].type.typeName, 'int32')
st.equals(scopes['1.1.1'].locals['ui8'].type.typeName, 'uint8')
st.equals(scopes['1.1.1.1'].locals['ui81'].type.typeName, 'uint8')
st.equals(scopes['1.1.2'].locals['ui81'].type.typeName, 'uint8')
st.equals(scopes['1.1.3'].locals['ui8'].type.typeName, 'uint8')
st.equals(scopes['1.1.3.1'].locals['ui81'].type.typeName, 'uint8')
} catch (e) {
st.fail(e.message)
}
resolve({})
helper.decodeLocals(st, 95, traceManager, callTree, function (locals) {
st.equals(Object.keys(locals).length, 16)
st.equals(locals['ui8'].value, '130')
st.equals(locals['ui16'].value, '456')
st.equals(locals['ui32'].value, '4356')
st.equals(locals['ui64'].value, '3543543543')
st.equals(locals['ui128'].value, '234567')
st.equals(locals['ui256'].value, '115792089237316195423570985008687907853269984665640564039457584007880697216513')
st.equals(locals['ui'].value, '123545666')
st.equals(locals['i8'].value, '-45')
st.equals(locals['i16'].value, '-1234')
st.equals(locals['i32'].value, '3455')
st.equals(locals['i64'].value, '-35566')
st.equals(locals['i128'].value, '-444444')
st.equals(locals['i256'].value, '3434343')
st.equals(locals['i'].value, '-32432423423')
st.equals(locals['ishrink'].value, '2')
})
helper.decodeLocals(st, 106, traceManager, callTree, function (locals) {
try {
st.equals(locals['ui8'].value, '123')
st.equals(Object.keys(locals).length, 2)
} catch (e) {
st.fail(e.message)
}
resolve({})
})
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
.catch(error => st.fail(error))
})
})
}

@ -13,77 +13,76 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult,
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve) => {
const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, undefined, 0, contractBytecode, function (error, hash) {
if (error) {
return st.fail(error)
}
web3.eth.getTransaction(hash, function (error, tx) {
if (error) {
return st.fail(error)
}
tx.to = contractCreationToken('0')
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResult
})
const debuggerEvent = new EventManager()
const offsetToLineColumnConverter = {
offsetToLineColumn: (rawLocation) => {
return new Promise((resolve) => {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(contractCode)
resolve(sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, lineBreaks))
})
}
}
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }, offsetToLineColumnConverter)
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 70, traceManager, callTree, function (locals) {
try {
st.equals(locals['boolFalse'].value, false)
st.equals(locals['boolTrue'].value, true)
st.equals(locals['testEnum'].value, 'three')
st.equals(locals['sender'].value, '0x5B38DA6A701C568545DCFCB03FCB875F56BEDDC4')
st.equals(locals['_bytes1'].value, '0x99')
st.equals(locals['__bytes1'].value, '0x99')
st.equals(locals['__bytes2'].value, '0x99AB')
st.equals(locals['__bytes4'].value, '0x99FA0000')
st.equals(locals['__bytes6'].value, '0x990000000000')
st.equals(locals['__bytes7'].value, '0x99356700000000')
st.equals(locals['__bytes8'].value, '0x99ABD41700000000')
st.equals(locals['__bytes9'].value, '0x99156744AF00000000')
st.equals(locals['__bytes13'].value, '0x99123423425300000000000000')
st.equals(locals['__bytes16'].value, '0x99AFAD23432400000000000000000000')
st.equals(locals['__bytes24'].value, '0x99AFAD234324000000000000000000000000000000000000')
st.equals(locals['__bytes32'].value, '0x9999ABD41799ABD4170000000000000000000000000000000000000000000000')
st.equals(Object.keys(locals).length, 16)
} catch (e) {
st.fail(e.message)
}
web3.eth.getTransaction(hash)
.then(tx => {
tx.to = contractCreationToken('0')
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResult
})
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try {
// st.equals(Object.keys(locals).length, 0)
st.equals(0, 0)
} catch (e) {
st.fail(e.message)
const debuggerEvent = new EventManager()
const offsetToLineColumnConverter = {
offsetToLineColumn: (rawLocation) => {
return new Promise((resolve) => {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(contractCode)
resolve(sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, lineBreaks))
})
}
resolve({})
}
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }, offsetToLineColumnConverter)
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 70, traceManager, callTree, function (locals) {
try {
st.equals(locals['boolFalse'].value, false)
st.equals(locals['boolTrue'].value, true)
st.equals(locals['testEnum'].value, 'three')
st.equals(locals['sender'].value, '0x5B38DA6A701C568545DCFCB03FCB875F56BEDDC4')
st.equals(locals['_bytes1'].value, '0x99')
st.equals(locals['__bytes1'].value, '0x99')
st.equals(locals['__bytes2'].value, '0x99AB')
st.equals(locals['__bytes4'].value, '0x99FA0000')
st.equals(locals['__bytes6'].value, '0x990000000000')
st.equals(locals['__bytes7'].value, '0x99356700000000')
st.equals(locals['__bytes8'].value, '0x99ABD41700000000')
st.equals(locals['__bytes9'].value, '0x99156744AF00000000')
st.equals(locals['__bytes13'].value, '0x99123423425300000000000000')
st.equals(locals['__bytes16'].value, '0x99AFAD23432400000000000000000000')
st.equals(locals['__bytes24'].value, '0x99AFAD234324000000000000000000000000000000000000')
st.equals(locals['__bytes32'].value, '0x9999ABD41799ABD4170000000000000000000000000000000000000000000000')
st.equals(Object.keys(locals).length, 16)
} catch (e) {
st.fail(e.message)
}
})
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try {
// st.equals(Object.keys(locals).length, 0)
st.equals(0, 0)
} catch (e) {
st.fail(e.message)
}
resolve({})
})
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
.catch(error => st.fail(error))
})
})
}

@ -13,63 +13,62 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult,
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve) => {
const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, undefined, 0, contractBytecode, function (error, hash) {
if (error) {
return st.fail(error)
}
web3.eth.getTransaction(hash, function (error, tx) {
if (error) {
return st.fail(error)
}
tx.to = contractCreationToken('0')
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResult
})
const debuggerEvent = new EventManager()
const offsetToLineColumnConverter = {
offsetToLineColumn: (rawLocation) => {
return new Promise((resolve) => {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(contractCode)
resolve(sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, lineBreaks))
})
}
}
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }, offsetToLineColumnConverter)
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 49, traceManager, callTree, function (locals) {
try {
st.equals(locals['dynbytes'].value, '0x64796e616d69636279746573')
st.equals(locals['smallstring'].value, 'test_test_test')
st.equals(Object.keys(locals).length, 2)
} catch (e) {
st.fail(e.message)
}
web3.eth.getTransaction(hash)
.then(tx => {
tx.to = contractCreationToken('0')
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResult
})
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try {
// st.equals(Object.keys(locals).length, 0)
st.equals(0, 0)
} catch (e) {
st.fail(e.message)
const debuggerEvent = new EventManager()
const offsetToLineColumnConverter = {
offsetToLineColumn: (rawLocation) => {
return new Promise((resolve) => {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(contractCode)
resolve(sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, lineBreaks))
})
}
resolve({})
}
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }, offsetToLineColumnConverter)
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 49, traceManager, callTree, function (locals) {
try {
st.equals(locals['dynbytes'].value, '0x64796e616d69636279746573')
st.equals(locals['smallstring'].value, 'test_test_test')
st.equals(Object.keys(locals).length, 2)
} catch (e) {
st.fail(e.message)
}
})
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try {
// st.equals(Object.keys(locals).length, 0)
st.equals(0, 0)
} catch (e) {
st.fail(e.message)
}
resolve({})
})
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
.catch(error => st.fail(error))
})
})
}

@ -13,123 +13,122 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult,c
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve) => {
const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, undefined, 0, contractBytecode, function (error, hash) {
if (error) {
return st.fail(error)
}
web3.eth.getTransaction(hash, function (error, tx) {
if (error) {
return st.fail(error)
}
tx.to = contractCreationToken('0')
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResult
})
const debuggerEvent = new EventManager()
const offsetToLineColumnConverter = {
offsetToLineColumn: (rawLocation) => {
return new Promise((resolve) => {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(contractCode)
resolve(sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, lineBreaks))
})
web3.eth.getTransaction(hash)
.then(tx => {
tx.to = contractCreationToken('0')
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResult
})
const debuggerEvent = new EventManager()
const offsetToLineColumnConverter = {
offsetToLineColumn: (rawLocation) => {
return new Promise((resolve) => {
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(contractCode)
resolve(sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, lineBreaks))
})
}
}
}
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }, offsetToLineColumnConverter)
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 1622, traceManager, callTree, function (locals) {
try {
console.log('at 1622', locals)
st.equals(locals['bytesSimple'].length, '0x14')
st.equals(locals['bytesSimple'].value, '0x746573745f7375706572')
st.equals(locals['e'].value['a'].value, 'test')
st.equals(locals['e'].value['a'].length, '0x8')
st.equals(locals['e'].value['a'].raw, '0x74657374')
st.equals(locals['e'].value['b'].value, '5')
st.equals(locals['e'].value['c'].length, '0x220')
st.equals(locals['e'].value['c'].raw, '0x746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374')
st.equals(locals['e'].value['c'].value, 'test_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_test')
st.equals(locals['e'].value['d'].value, '3')
st.equals(locals['f'].length, '0x1b8')
st.equals(locals['f'].raw, '0x746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f')
st.equals(locals['f'].value, 'test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_')
st.equals(locals['e'].value['e'].value, true)
st.equals(locals['simpleArray'].value[0].value, '45')
st.equals(locals['simpleArray'].value[1].value, '324324')
st.equals(locals['simpleArray'].value[2].value, '-333')
st.equals(locals['simpleArray'].value[3].value, '5656')
st.equals(locals['simpleArray'].value[4].value, '-1111')
st.equals(locals['stringArray'].value[0].value, 'long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_')
st.equals(locals['stringArray'].value[1].value, 'two')
st.equals(locals['stringArray'].value[2].value, 'three')
st.equals(locals['dynArray'].value[0].value[0].value, '3423423532')
st.equals(locals['dynArray'].value[1].value[0].value, '-342343323532')
st.equals(locals['dynArray'].value[1].value[1].value, '23432')
st.equals(locals['dynArray'].value[2].value[0].value, '-432432')
st.equals(locals['dynArray'].value[2].value[1].value, '3423423532')
st.equals(locals['dynArray'].value[2].value[2].value, '-432432')
st.equals(locals['structArray'].value[0].value['a'].value, 'test')
st.equals(locals['structArray'].value[0].value['a'].length, '0x8')
st.equals(locals['structArray'].value[0].value['a'].raw, '0x74657374')
st.equals(locals['structArray'].value[0].value['b'].value, '5')
st.equals(locals['structArray'].value[0].value['c'].length, '0x220')
st.equals(locals['structArray'].value[0].value['c'].raw, '0x746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374')
st.equals(locals['structArray'].value[0].value['c'].value, 'test_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_test')
st.equals(locals['structArray'].value[0].value['d'].value, '3')
st.equals(locals['structArray'].value[0].value['e'].value, true)
st.equals(locals['structArray'].value[1].value['a'].value, 'item1 a')
st.equals(locals['structArray'].value[1].value['b'].value, '20')
st.equals(locals['structArray'].value[1].value['c'].value, 'item1 c')
st.equals(locals['structArray'].value[1].value['d'].value, '-45')
st.equals(locals['structArray'].value[1].value['e'].value, false)
st.equals(locals['structArray'].value[2].value['a'].value, 'item2 a')
st.equals(locals['structArray'].value[2].value['b'].value, '200')
st.equals(locals['structArray'].value[2].value['c'].value, 'item2 c')
st.equals(locals['structArray'].value[2].value['d'].value, '-450')
st.equals(locals['structArray'].value[2].value['e'].value, true)
st.equals(locals['arrayStruct'].value.a.value[0].value, 'string')
st.equals(locals['arrayStruct'].value.b.value[0].value, '34')
st.equals(locals['arrayStruct'].value.b.value[1].value, '-23')
st.equals(locals['arrayStruct'].value.b.value[2].value, '-3')
st.equals(locals['arrayStruct'].value.c.value, 'three')
const callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }, offsetToLineColumnConverter)
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 1622, traceManager, callTree, function (locals) {
try {
console.log('at 1622', locals)
st.equals(locals['bytesSimple'].length, '0x14')
st.equals(locals['bytesSimple'].value, '0x746573745f7375706572')
st.equals(locals['e'].value['a'].value, 'test')
st.equals(locals['e'].value['a'].length, '0x8')
st.equals(locals['e'].value['a'].raw, '0x74657374')
st.equals(locals['e'].value['b'].value, '5')
st.equals(locals['e'].value['c'].length, '0x220')
st.equals(locals['e'].value['c'].raw, '0x746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374')
st.equals(locals['e'].value['c'].value, 'test_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_test')
st.equals(locals['e'].value['d'].value, '3')
st.equals(locals['f'].length, '0x1b8')
st.equals(locals['f'].raw, '0x746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f')
st.equals(locals['f'].value, 'test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_')
st.equals(locals['e'].value['e'].value, true)
st.equals(locals['simpleArray'].value[0].value, '45')
st.equals(locals['simpleArray'].value[1].value, '324324')
st.equals(locals['simpleArray'].value[2].value, '-333')
st.equals(locals['simpleArray'].value[3].value, '5656')
st.equals(locals['simpleArray'].value[4].value, '-1111')
st.equals(locals['stringArray'].value[0].value, 'long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_')
st.equals(locals['stringArray'].value[1].value, 'two')
st.equals(locals['stringArray'].value[2].value, 'three')
st.equals(locals['dynArray'].value[0].value[0].value, '3423423532')
st.equals(locals['dynArray'].value[1].value[0].value, '-342343323532')
st.equals(locals['dynArray'].value[1].value[1].value, '23432')
st.equals(locals['dynArray'].value[2].value[0].value, '-432432')
st.equals(locals['dynArray'].value[2].value[1].value, '3423423532')
st.equals(locals['dynArray'].value[2].value[2].value, '-432432')
st.equals(locals['structArray'].value[0].value['a'].value, 'test')
st.equals(locals['structArray'].value[0].value['a'].length, '0x8')
st.equals(locals['structArray'].value[0].value['a'].raw, '0x74657374')
st.equals(locals['structArray'].value[0].value['b'].value, '5')
st.equals(locals['structArray'].value[0].value['c'].length, '0x220')
st.equals(locals['structArray'].value[0].value['c'].raw, '0x746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374')
st.equals(locals['structArray'].value[0].value['c'].value, 'test_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_test')
st.equals(locals['structArray'].value[0].value['d'].value, '3')
st.equals(locals['structArray'].value[0].value['e'].value, true)
st.equals(locals['structArray'].value[1].value['a'].value, 'item1 a')
st.equals(locals['structArray'].value[1].value['b'].value, '20')
st.equals(locals['structArray'].value[1].value['c'].value, 'item1 c')
st.equals(locals['structArray'].value[1].value['d'].value, '-45')
st.equals(locals['structArray'].value[1].value['e'].value, false)
st.equals(locals['structArray'].value[2].value['a'].value, 'item2 a')
st.equals(locals['structArray'].value[2].value['b'].value, '200')
st.equals(locals['structArray'].value[2].value['c'].value, 'item2 c')
st.equals(locals['structArray'].value[2].value['d'].value, '-450')
st.equals(locals['structArray'].value[2].value['e'].value, true)
st.equals(locals['arrayStruct'].value.a.value[0].value, 'string')
st.equals(locals['arrayStruct'].value.b.value[0].value, '34')
st.equals(locals['arrayStruct'].value.b.value[1].value, '-23')
st.equals(locals['arrayStruct'].value.b.value[2].value, '-3')
st.equals(locals['arrayStruct'].value.c.value, 'three')
st.equals(Object.keys(locals).length, 8)
} catch (e) {
st.fail(e.message)
}
})
st.equals(Object.keys(locals).length, 8)
} catch (e) {
st.fail(e.message)
}
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try {
console.log('at 7', locals)
st.equals(0, 0)
// st.equals(Object.keys(locals).length, 0)
} catch (e) {
st.fail(e.message)
}
resolve({})
})
})
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try {
console.log('at 7', locals)
st.equals(0, 0)
// st.equals(Object.keys(locals).length, 0)
} catch (e) {
st.fail(e.message)
}
resolve({})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
traceManager.resolveTrace(tx).then(() => {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}).catch((error) => {
st.fail(error)
})
})
.catch(error => st.fail(error))
})
})
}

@ -23,23 +23,22 @@ module.exports = async function testMappingStorage (st, cb) {
}
const compilationResults = new CompilerAbstract('json', output, sources)
const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['SimpleMappingState'].evm.bytecode.object, function (error, hash) {
(vmCall as any).sendTx(web3, {nonce: 0, privateKey: privateKey}, undefined, 0, output.contracts['test.sol']['SimpleMappingState'].evm.bytecode.object, function (error, hash) {
if (error) {
console.log(error)
st.end(error)
} else {
web3.eth.getTransactionReceipt(hash, (error, tx) => {
if (error) {
console.log(error)
st.end(error)
} else {
web3.eth.getTransactionReceipt(hash)
.then(tx =>
// const storage = await this.vm.stateManager.dumpStorage(data.to)
// (vmCall as any).web3().eth.getCode(tx.contractAddress).then((code) => console.log('code:', code))
// (vmCall as any).web3().debug.traceTransaction(hash).then((code) => console.log('trace:', code))
testMapping(st, privateKey, tx.contractAddress, output, compilationResults, web3, cb)
// st.end()
}
})
)
.catch(error => {
st.end(error)
})
}
})
}
@ -50,18 +49,15 @@ function testMapping (st, privateKey, contractAddress, output, compilationResult
if (error) {
console.log(error)
st.end(error)
} else {
web3.eth.getTransaction(hash, (error, tx) => {
if (error) {
console.log(error)
st.end(error)
} else {
} else {
web3.eth.getTransaction(hash)
.then(tx => {
const traceManager = new TraceManager({ web3 })
const codeManager = new CodeManager(traceManager)
codeManager.clear()
console.log(compilationResults)
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
const solidityProxy = new SolidityProxy({
getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager),
getCode: codeManager.getCode.bind(codeManager),
compilationResult: () => compilationResults
})
@ -101,8 +97,11 @@ function testMapping (st, privateKey, contractAddress, output, compilationResult
}).catch((error) => {
st.fail(error)
})
}
})
})
.catch(error => {
console.log(error)
st.end(error)
})
}
})
}

@ -1,8 +1,8 @@
'use strict'
import { extendWeb3 } from '../src/init'
import { Address } from '@ethereumjs/util'
import { Web3 } from 'web3';
const { Provider } = require('@remix-project/remix-simulator')
const Web3 = require('web3')
async function getWeb3 () {

@ -25,7 +25,8 @@
"from-exponential": "1.1.1",
"solc": "^0.7.4",
"string-similarity": "^4.0.4",
"web3": "^1.5.1"
"web3": "^4.1.1",
"web3-validator": "^2.0.0"
},
"devDependencies": {
"@babel/core": "^7.4.5",
@ -54,4 +55,4 @@
"typings": "src/index.d.ts",
"gitHead": "b6db2a29c223e423c70f06b87d9b245e26f0b220",
"types": "./src/index.d.ts"
}
}

@ -20,12 +20,10 @@ export class LogsManager {
checkBlock (blockNumber, block, web3) {
eachOf(block.transactions, (tx: any, i, next) => {
const txHash = '0x' + tx.hash().toString('hex')
web3.eth.getTransactionReceipt(txHash, (_error, receipt) => {
for (const log of receipt.logs) {
this.oldLogs.push({ type: 'block', blockNumber, block, tx, log, txNumber: i, receipt })
const subscriptions = this.getSubscriptionsFor({ type: 'block', blockNumber, block, tx, log, receipt})
for (const subscriptionId of subscriptions) {
const result = {
logIndex: '0x1', // 1

@ -33,7 +33,7 @@ export class TxListener {
_listenOnNetwork:boolean
_loopId
blocks
constructor (opt, executionContext) {
this.event = new EventManager()
// has a default for now for backwards compatibility
@ -63,7 +63,7 @@ export class TxListener {
let returnValue
let execResult
if (this.executionContext.isVM()) {
execResult = await this.executionContext.web3().eth.getExecutionResultFromSimulator(txResult.transactionHash)
execResult = await this.executionContext.web3().remix.getExecutionResultFromSimulator(txResult.transactionHash)
returnValue = toBuffer(execResult.returnValue)
} else {
returnValue = toBuffer(addHexPrefix(txResult.result))
@ -94,19 +94,17 @@ 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, async (error, tx) => {
if (error) return console.log(error)
this.executionContext.web3().eth.getTransaction(txResult.transactionHash).then(async tx=>{
let execResult
if (this.executionContext.isVM()) {
execResult = await this.executionContext.web3().eth.getExecutionResultFromSimulator(txResult.transactionHash)
execResult = await this.executionContext.web3().remix.getExecutionResultFromSimulator(txResult.transactionHash)
}
addExecutionCosts(txResult, tx, execResult)
tx.envMode = this.executionContext.getProvider()
tx.status = txResult.receipt.status
this._resolve([tx])
})
}).catch(error=>console.log(error))
})
}
@ -159,7 +157,7 @@ export class TxListener {
}
async _startListenOnNetwork () {
let lastSeenBlock = this.executionContext.lastBlock?.number - 1
let lastSeenBlock = this.executionContext.lastBlock?.number - BigInt(1)
let processingBlock = false
const processBlocks = async () => {
@ -204,7 +202,7 @@ export class TxListener {
async _manageBlock (blockNumber) {
try {
const result = await this.executionContext.web3().eth.getBlock(blockNumber, true)
return await this._newBlock(Object.assign({ type: 'web3' }, result))
return await this._newBlock(Object.assign({ type: 'web3' }, result))
} catch (e) {}
}
@ -285,8 +283,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, (error, code) => {
if (error) return cb(error)
this.executionContext.web3().eth.getCode(tx.to).then(code=>{
if (code) {
const contract = this._tryResolveContract(code, contracts, false)
if (contract) {
@ -296,7 +293,7 @@ export class TxListener {
}
}
return cb()
})
}).catch(error=>cb(error))
return
}
if (contract) {

@ -72,12 +72,12 @@ export class TxRunnerVM {
if (!from && useCall && Object.keys(this.vmaccounts).length) {
from = Object.keys(this.vmaccounts)[0]
account = this.vmaccounts[from]
} else account = this.vmaccounts[from]
} else account = this.vmaccounts[from]
if (!account) {
return callback('Invalid account selected')
}
this.getVMObject().stateManager.getAccount(Address.fromString(from)).then((res: Account) => {
const EIP1559 = this.commonContext.hardfork() !== 'berlin' // berlin is the only pre eip1559 fork that we handle.
let tx
@ -106,7 +106,7 @@ export class TxRunnerVM {
const coinbases = ['0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a', '0x8945a1288dc78a6d8952a92c77aee6730b414778', '0x94d76e24f818426ae84aa404140e8d5f60e10e7e']
const difficulties = [69762765929000, 70762765929000, 71762765929000]
const difficulty = this.commonContext.consensusType() === ConsensusType.ProofOfStake ? 0 : difficulties[this.blockNumber % difficulties.length]
const blocknumber = this.blockNumber + 1
const block = Block.fromBlockData({
header: {

@ -2,6 +2,7 @@
import { EventManager } from '../eventManager'
import type { Transaction as InternalTransaction } from './txRunner'
import Web3 from 'web3'
import {toBigInt} from 'web3-utils'
export class TxRunnerWeb3 {
event
@ -16,11 +17,13 @@ export class TxRunnerWeb3 {
this._api = api
}
_executeTx (tx, network, txFee, api, promptCb, callback) {
async _executeTx (tx, network, txFee, api, promptCb, callback) {
if (network && network.lastBlock && network.lastBlock.baseFeePerGas) {
// 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
tx.type = '0x2'
} else {
tx.type = '0x1'
}
if (txFee) {
if (txFee.baseFeePerGas) {
@ -33,21 +36,6 @@ export class TxRunnerWeb3 {
}
}
if (api.personalMode()) {
promptCb(
(value) => {
this._sendTransaction((this.getWeb3() as any).personal.sendTransaction, tx, value, callback)
},
() => {
return callback('Canceled by user.')
}
)
} else {
this._sendTransaction(this.getWeb3().eth.sendTransaction, tx, null, callback)
}
}
_sendTransaction (sendTx, tx, pass, callback) {
let currentDateTime = new Date();
const start = currentDateTime.getTime() / 1000
const cb = (err, resp) => {
@ -72,11 +60,30 @@ export class TxRunnerWeb3 {
}
listenOnResponse().then((txData) => { callback(null, txData) }).catch((error) => { callback(error) })
}
const args = pass !== null ? [tx, pass, cb] : [tx, cb]
try {
sendTx.apply({}, args)
} catch (e) {
return callback(`Send transaction failed: ${e.message} . if you use an injected provider, please check it is properly unlocked. `)
if (api.personalMode()) {
promptCb(
async (value) => {
try {
const res = await (this.getWeb3() as any).eth.personal.sendTransaction({...tx, value})
cb(null, res.transactionHash)
} catch (e) {
console.log(`Send transaction failed: ${e.message} . if you use an injected provider, please check it is properly unlocked. `)
cb(null, e.receipt.transactionHash)
}
},
() => {
return callback('Canceled by user.')
}
)
} else {
try {
const res = await this.getWeb3().eth.sendTransaction(tx)
cb(null, res.transactionHash)
} catch (e) {
console.log(`Send transaction failed: ${e.message} . if you use an injected provider, please check it is properly unlocked. `)
cb(null, e.receipt.transactionHash)
}
}
}
@ -94,13 +101,15 @@ export class TxRunnerWeb3 {
if (!from) return callback('the value of "from" is not defined. Please make sure an account is selected.')
if (useCall) {
tx['gas'] = gasLimit
if (this._api && this._api.isVM()) tx['timestamp'] = timestamp
return this.getWeb3().eth.call(tx, function (error, result: any) {
if (error) return callback(error)
callback(null, {
if (this._api && this._api.isVM()) {
(this.getWeb3() as any).remix.registerCallId(timestamp)
}
this.getWeb3().eth.call(tx)
.then((result: any) => callback(null, {
result: result
})
})
}))
.catch(error => callback(error))
return
}
this._api.detectNetwork((errNetWork, network) => {
if (errNetWork) {
@ -113,48 +122,49 @@ 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(network.lastBlock.baseFeePerGas + network.lastBlock.baseFeePerGas / 3)
txCopy.maxFeePerGas = Math.ceil(Number((toBigInt(network.lastBlock.baseFeePerGas) + toBigInt(network.lastBlock.baseFeePerGas) / BigInt(3)).toString()))
} else {
txCopy.type = '0x1'
txCopy.gasPrice = network.lastBlock.baseFeePerGas
}
}
this.getWeb3().eth.estimateGas(txCopy, (err, gasEstimation) => {
if (err && err.message.indexOf('Invalid JSON RPC response') !== -1) {
// // @todo(#378) this should be removed when https://github.com/WalletConnect/walletconnect-monorepo/issues/334 is fixed
callback(new Error('Gas estimation failed because of an unknown internal error. This may indicated that the transaction will fail.'))
txCopy.gasPrice = undefined
}
err = network.name === 'VM' ? null : err // just send the tx if "VM"
gasEstimationForceSend(err, () => {
// callback is called whenever no error
tx['gas'] = !gasEstimation ? gasLimit : gasEstimation
if (this._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')) {
return this._executeTx(tx, network, null, this._api, promptCb, callback)
}
}
this.getWeb3().eth.estimateGas(txCopy)
.then(gasEstimation => {
gasEstimationForceSend(null, () => {
// callback is called whenever no error
tx['gas'] = !gasEstimation ? gasLimit : gasEstimation
confirmCb(network, tx, tx['gas'], (txFee) => {
return this._executeTx(tx, network, txFee, this._api, promptCb, callback)
}, (error) => {
callback(error)
if (this._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')) {
return this._executeTx(tx, network, null, this._api, promptCb, callback)
}
confirmCb(network, tx, tx['gas'], (txFee) => {
return this._executeTx(tx, network, txFee, this._api, promptCb, callback)
}, (error) => {
callback(error)
})
})
}, () => {
const blockGasLimit = this.currentblockGasLimit()
// NOTE: estimateGas very likely will return a large limit if execution of the code failed
// we want to be able to run the code in order to debug and find the cause for the failure
if (err) return callback(err)
let warnEstimation = ' An important gas estimation might also be the sign of a problem in the contract code. Please check loops and be sure you did not sent value to a non payable function (that\'s also the reason of strong gas estimation). '
warnEstimation += ' ' + err
if (gasEstimation > gasLimit) {
return callback('Gas required exceeds limit: ' + gasLimit + '. ' + warnEstimation)
}
if (gasEstimation > blockGasLimit) {
return callback('Gas required exceeds block gas limit: ' + gasLimit + '. ' + warnEstimation)
})
.catch(err => {
if (err && err.message.indexOf('Invalid JSON RPC response') !== -1) {
// // @todo(#378) this should be removed when https://github.com/WalletConnect/walletconnect-monorepo/issues/334 is fixed
callback(new Error('Gas estimation failed because of an unknown internal error. This may indicated that the transaction will fail.'))
}
err = network.name === 'VM' ? null : err // just send the tx if "VM"
gasEstimationForceSend(err, () => {
tx['gas'] = gasLimit
if (this._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')) {
return this._executeTx(tx, network, null, this._api, promptCb, callback)
}
confirmCb(network, tx, tx['gas'], (txFee) => {
return this._executeTx(tx, network, txFee, this._api, promptCb, callback)
}, (error) => {
callback(error)
})
})
})
})
})
}
}

@ -1,11 +1,12 @@
'use strict'
import { BN } from 'bn.js'
import { bufferToHex } 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)) {
} else if ((h.constructor && h.constructor.name === 'BigNumber') || BN.isBN(h) || isBigInt(h)) {
return h.toString(10)
}
return h
@ -21,7 +22,7 @@ function convertToString (v) {
ret.push(convertToString(v[k]))
}
return ret
} else if (BN.isBN(v) || (v.constructor && v.constructor.name === 'BigNumber')) {
} else if (BN.isBN(v) || (v.constructor && v.constructor.name === 'BigNumber') || isBigInt(v)) {
return v.toString(10)
} else if (v._isBuffer) {
return bufferToHex(v)

@ -1,54 +1,46 @@
'use strict'
import Web3 from 'web3'
import Web3, { Web3PluginBase } from 'web3'
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))
extend(web3)
extendWeb3(web3)
return web3
}
export function extendWeb3 (web3) {
extend(web3)
}
class Web3DebugPlugin extends Web3PluginBase {
public pluginNamespace = 'debug'
export function extend (web3) {
if (!web3.extend) {
return
}
// DEBUG
const methods = []
if (!(web3.debug && web3.debug.preimage)) {
methods.push(new web3.extend.Method({
name: 'preimage',
call: 'debug_preimage',
inputFormatter: [null],
params: 1
}))
public preimage(key, cb) {
this.requestManager.send({
method: 'debug_preimage',
params: [key]
})
.then(result => cb(null, result))
.catch(error => cb(error))
}
if (!(web3.debug && web3.debug.traceTransaction)) {
methods.push(new web3.extend.Method({
name: 'traceTransaction',
call: 'debug_traceTransaction',
inputFormatter: [null, null],
params: 2
}))
public traceTransaction(txHash, options, cb) {
this.requestManager.send({
method: 'debug_traceTransaction',
params: [txHash, options]
})
.then(result => cb(null, result))
.catch(error => cb(error))
}
if (!(web3.debug && web3.debug.storageRangeAt)) {
methods.push(new web3.extend.Method({
name: 'storageRangeAt',
call: 'debug_storageRangeAt',
inputFormatter: [null, null, null, null, null],
params: 5
}))
}
if (methods.length > 0) {
web3.extend({
property: 'debug',
methods: methods,
properties: []
public storageRangeAt(txBlockHash, txIndex, address, start, maxSize, cb) {
this.requestManager.send({
method: 'debug_storageRangeAt',
params: [txBlockHash, txIndex, address, start, maxSize]
})
.then(result => cb(null, result))
.catch(error => cb(error))
}
}

@ -36,7 +36,8 @@
"merge": "^1.2.0",
"string-similarity": "^4.0.4",
"time-stamp": "^2.0.0",
"web3": "^1.5.1"
"web3": "^4.1.1",
"web3-utils": "^4.0.5"
},
"devDependencies": {
"@babel/core": "^7.4.5",
@ -69,4 +70,4 @@
"typings": "src/index.d.ts",
"gitHead": "b6db2a29c223e423c70f06b87d9b245e26f0b220",
"types": "./src/index.d.ts"
}
}

@ -3,10 +3,9 @@ const { toHexPaddedString, formatMemory } = util
import { helpers } from '@remix-project/remix-lib'
const { normalizeHexAddress } = helpers.ui
import { ConsoleLogs, hash } from '@remix-project/remix-lib'
import BN from 'bn.js'
import { isBigNumber } from 'web3-utils'
import { toChecksumAddress, bufferToHex, Address, toBuffer } from '@ethereumjs/util'
import utils from 'web3-utils'
import utils, {toBigInt} from 'web3-utils'
import {isBigInt} from 'web3-validator'
import { ethers } from 'ethers'
import { VMContext } from './vm-context'
import type { StateManager } from '@ethereumjs/statemanager'
@ -47,7 +46,7 @@ export class VmProxy {
stateCopy: StateManager
flagDoNotRecordEVMSteps: boolean
lastMemoryUpdate: Array<string>
constructor (vmContext: VMContext) {
this.vmContext = vmContext
this.stateCopy
@ -84,7 +83,7 @@ export class VmProxy {
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) => utils.toBN.apply(this, args)
this.toBigNumber = (...args) => toBigInt.apply(this, args)
this.isAddress = (...args) => utils.isAddress.apply(this, args)
this.utils = utils
this.txsMapBlock = {}
@ -176,6 +175,7 @@ export class VmProxy {
const topics = []
if (log[1].length > 0) {
for (const k in log[1]) {
// @ts-ignore
topics.push('0x' + log[1][k].toString('hex'))
}
} else {
@ -278,7 +278,8 @@ export class VmProxy {
}
let consoleArgs = iface.decodeFunctionData(functionDesc, payload)
consoleArgs = consoleArgs.map((value) => {
if (isBigNumber(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))) {
return value.toString()
}
return value
@ -347,7 +348,7 @@ export class VmProxy {
getStorageAt (address: string, position: string, blockNumber: string, cb) {
// we don't use the range params here
address = toChecksumAddress(address)
blockNumber = blockNumber === 'latest' ? this.vmContext.latestBlockNumber : blockNumber
const block = this.vmContext.blocks[blockNumber]
@ -425,10 +426,10 @@ export class VmProxy {
getSha3Input (stack, memory) {
const memoryStart = toHexPaddedString(stack[stack.length - 1])
const memoryLength = toHexPaddedString(stack[stack.length - 2])
const memStartDec = (new BN(memoryStart.replace('0x', ''), 16)).toString(10)
const memStartDec = toBigInt(memoryStart).toString(10)
const memoryStartInt = parseInt(memStartDec) * 2
const memLengthDec = (new BN(memoryLength.replace('0x', ''), 16).toString(10))
const memoryLengthInt = parseInt(memLengthDec) * 2
const memLengthDec = toBigInt(memoryLength).toString(10)
const memoryLengthInt = parseInt(memLengthDec.toString()) * 2
let i = Math.floor(memoryStartInt / 32)
const maxIndex = Math.floor(memoryLengthInt / 32) + i

@ -1,19 +1,17 @@
import { privateToAddress, toChecksumAddress, isValidPrivate, Address } from '@ethereumjs/util'
import BN from 'bn.js'
const Web3EthAccounts = require('web3-eth-accounts');
import { privateKeyToAccount } from 'web3-eth-accounts'
import { toBigInt } from 'web3-utils'
import * as crypto from 'crypto'
export class Web3Accounts {
accounts: Record<string, unknown>
accountsKeys: Record<string, unknown>
web3Accounts: any
vmContext
constructor (vmContext) {
this.vmContext = vmContext
// TODO: make it random and/or use remix-libs
this.web3Accounts = new Web3EthAccounts()
this.accounts = {}
this.accountsKeys = {}
}
@ -48,7 +46,7 @@ export class Web3Accounts {
const stateManager = this.vmContext.vm().stateManager
stateManager.getAccount(Address.fromString(addressStr)).then((account) => {
account.balance = new BN(balance.replace('0x', '') || 'f00000000000000001', 16)
account.balance = toBigInt(balance || '0xf00000000000000001')
stateManager.putAccount(Address.fromString(addressStr), account).catch((error) => {
reject(error)
}).then(() => {
@ -85,7 +83,7 @@ export class Web3Accounts {
const address = payload.params[0]
this.vmContext.vm().stateManager.getAccount(Address.fromString(address)).then((account) => {
cb(null, new BN(account.balance).toString(10))
cb(null, toBigInt(account.balance).toString(10))
}).catch((error) => {
cb(error)
})
@ -99,7 +97,7 @@ export class Web3Accounts {
if (!privateKey) {
return cb(new Error('unknown account'))
}
const account = this.web3Accounts.privateKeyToAccount(privateKey as string)
const account = privateKeyToAccount(privateKey as string)
const data = account.sign(message)

@ -1,5 +1,4 @@
import { toHex, toDecimal } from 'web3-utils'
import BN from 'bn.js'
import { toHex, toNumber, toBigInt } from 'web3-utils'
import { toChecksumAddress, Address, bigIntToHex } from '@ethereumjs/util'
import { processTx } from './txProcess'
import { execution } from '@remix-project/remix-lib'
@ -26,6 +25,7 @@ export class Transactions {
txRunnerVMInstance
txRunnerInstance
TX_INDEX = '0x0' // currently there's always only 1 tx per block, so the transaction index will always be 0x0
comingCallId
constructor (vmContext) {
this.vmContext = vmContext
@ -73,7 +73,8 @@ export class Transactions {
eth_getTransactionByBlockNumberAndIndex: this.eth_getTransactionByBlockNumberAndIndex.bind(this),
eth_getExecutionResultFromSimulator: this.eth_getExecutionResultFromSimulator.bind(this),
eth_getHHLogsForTx: this.eth_getHHLogsForTx.bind(this),
eth_getHashFromTagBySimulator: this.eth_getHashFromTagBySimulator.bind(this)
eth_getHashFromTagBySimulator: this.eth_getHashFromTagBySimulator.bind(this),
eth_registerCallId: this.eth_registerCallId.bind(this)
}
}
@ -154,9 +155,8 @@ export class Transactions {
}
payload.params[0].gas = 10000000 * 10
this.vmContext.web3().flagNextAsDoNotRecordEvmSteps()
processTx(this.txRunnerInstance, payload, true, (error, value: VMexecutionResult) => {
processTx(this.txRunnerInstance, payload, true, (error, value: VMexecutionResult) => {
if (error) return cb(error)
const result: RunTxResult = value.result
if ((result as any).receipt?.status === '0x0' || (result as any).receipt?.status === 0) {
@ -169,12 +169,12 @@ export class Transactions {
return cb(e.message)
}
}
let gasUsed = result.execResult.executionGasUsed
let gasUsed = Number(toNumber(result.execResult.executionGasUsed))
if (result.execResult.gasRefund) {
gasUsed += result.execResult.gasRefund
gasUsed += Number(toNumber(result.execResult.gasRefund))
}
gasUsed = gasUsed + value.tx.getBaseFee()
cb(null, Math.ceil(Number(gasUsed) + (15 * Number(gasUsed)) / 100))
gasUsed = gasUsed + Number(toNumber(value.tx.getBaseFee()))
cb(null, Math.ceil(gasUsed + (15 * gasUsed) / 100))
})
}
@ -190,6 +190,11 @@ export class Transactions {
})
}
eth_registerCallId (payload, cb) {
this.comingCallId = payload.params[0]
cb()
}
eth_call (payload, cb) {
// from might be lowercased address (web3)
if (payload.params && payload.params.length > 0 && payload.params[0].from) {
@ -200,12 +205,10 @@ export class Transactions {
}
payload.params[0].value = undefined
const tag = payload.params[0].timestamp // e2e reference
const tag = payload.params[0].timestamp
processTx(this.txRunnerInstance, payload, true, (error, result: VMexecutionResult) => {
if (!error && result) {
this.vmContext.addBlock(result.block)
this.vmContext.addBlock(result.block, null, true)
const hash = '0x' + result.tx.hash().toString('hex')
this.vmContext.trackTx(hash, result.block, result.tx)
const returnValue = `0x${result.result.execResult.returnValue.toString('hex') || '0'}`
@ -217,9 +220,14 @@ export class Transactions {
logs: result.result.execResult.logs,
returnValue: returnValue
}
this.vmContext.trackExecResult(hash, execResult)
this.tags[tag] = result.transactionHash
// calls are not supposed to return a transaction hash. we do this for keeping track of it and allowing debugging calls.
// either the tag is specified as a timestamp in a tx or the caller should call registerCallId before calling the call.
if (tag) this.tags[tag] = result.transactionHash
else if (this.comingCallId) {
this.tags[this.comingCallId] = result.transactionHash
this.comingCallId = null
}
this.vmContext.trackExecResult(hash, execResult)
return cb(null, returnValue)
}
cb(error)
@ -234,7 +242,7 @@ export class Transactions {
const address = payload.params[0]
this.vmContext.vm().stateManager.getAccount(Address.fromString(address)).then((account) => {
const nonce = new BN(account.nonce).toString(10)
const nonce = toBigInt(account.nonce).toString(10)
cb(null, nonce)
}).catch((error) => {
cb(error)
@ -292,7 +300,7 @@ export class Transactions {
const txIndex = payload.params[1]
const txBlock = this.vmContext.blocks[payload.params[0]]
const txHash = '0x' + txBlock.transactions[toDecimal(txIndex)].hash().toString('hex')
const txHash = '0x' + txBlock.transactions[toNumber(txIndex) as number].hash().toString('hex')
this.vmContext.web3().eth.getTransactionReceipt(txHash, (error, receipt) => {
if (error) {
@ -337,7 +345,7 @@ export class Transactions {
const txIndex = payload.params[1]
const txBlock = this.vmContext.blocks[payload.params[0]]
const txHash = '0x' + txBlock.transactions[toDecimal(txIndex)].hash().toString('hex')
const txHash = '0x' + txBlock.transactions[toNumber(txIndex) as number].hash().toString('hex')
this.vmContext.web3().eth.getTransactionReceipt(txHash, (error, receipt) => {
if (error) {

@ -35,7 +35,7 @@ function createContract (payload, from, data, value, gasLimit, txRunner, callbac
}
export function processTx (txRunnerInstance, payload, isCall, callback) {
let { from, to, data, value, gas } = payload.params[0] // eslint-disable-line
let { from, to, data, input, value, gas } = payload.params[0] // eslint-disable-line
gas = gas || 3000000
const callbacks = {
@ -54,10 +54,10 @@ export function processTx (txRunnerInstance, payload, isCall, callback) {
}
if (isCall) {
runCall(payload, from, to, data, value, gas, txRunnerInstance, callbacks, callback)
runCall(payload, from, to, data||input, value, gas, txRunnerInstance, callbacks, callback)
} else if (to) {
runTx(payload, from, to, data, value, gas, txRunnerInstance, callbacks, callback)
runTx(payload, from, to, data||input, value, gas, txRunnerInstance, callbacks, callback)
} else {
createContract(payload, from, data, value, gas, txRunnerInstance, callbacks, callback)
createContract(payload, from, data||input, value, gas, txRunnerInstance, callbacks, callback)
}
}

@ -10,6 +10,7 @@ import { methods as netMethods } from './methods/net'
import { Transactions } from './methods/transactions'
import { Debug } from './methods/debug'
import { VMContext } from './vm-context'
import { Web3PluginBase } from 'web3'
export interface JSONRPCRequestPayload {
params: any[];
@ -69,7 +70,7 @@ export class Provider {
}
}
sendAsync (payload: JSONRPCRequestPayload, callback: (err: Error, result?: JSONRPCResponsePayload) => void) {
_send(payload: JSONRPCRequestPayload, callback: (err: Error, result?: JSONRPCResponsePayload) => void) {
// log.info('payload method is ', payload.method) // commented because, this floods the IDE console
if (!this.initialized) {
this.pendingRequests.push({ payload, callback })
@ -95,8 +96,23 @@ export class Provider {
callback(new Error('unknown method ' + payload.method))
}
sendAsync (payload: JSONRPCRequestPayload, callback: (err: Error, result?: JSONRPCResponsePayload) => void) {
return new Promise((resolve,reject)=>{
const cb = (err, result) => {
if(typeof callback==='function'){
callback(err,result)
}
if(err){
return reject(err)
}
return resolve(result)
}
this._send(payload, cb)
})
}
send (payload, callback) {
this.sendAsync(payload, callback || function () {})
return this.sendAsync(payload,callback)
}
isConnected () {
@ -117,43 +133,39 @@ export class Provider {
}
export function extend (web3) {
if (!web3.extend) {
return
if(!web3.remix){
web3.registerPlugin(new Web3TestPlugin())
}
// DEBUG
const methods = []
if (!(web3.eth && web3.eth.getExecutionResultFromSimulator)) {
methods.push(new web3.extend.Method({
name: 'getExecutionResultFromSimulator',
call: 'eth_getExecutionResultFromSimulator',
inputFormatter: [null],
params: 1
}))
}
class Web3TestPlugin extends Web3PluginBase {
public pluginNamespace = 'remix'
public getExecutionResultFromSimulator(transactionHash) {
return this.requestManager.send({
method: 'eth_getExecutionResultFromSimulator',
params: [transactionHash]
})
}
if (!(web3.eth && web3.eth.getHHLogsForTx)) {
methods.push(new web3.extend.Method({
name: 'getHHLogsForTx',
call: 'eth_getHHLogsForTx',
inputFormatter: [null],
params: 1
}))
public getHHLogsForTx(transactionHash) {
return this.requestManager.send({
method: 'eth_getHHLogsForTx',
params: [transactionHash]
})
}
if (!(web3.eth && web3.eth.getHashFromTagBySimulator)) {
methods.push(new web3.extend.Method({
name: 'getHashFromTagBySimulator',
call: 'eth_getHashFromTagBySimulator',
inputFormatter: [null],
params: 1
}))
public getHashFromTagBySimulator(timestamp) {
return this.requestManager.send({
method: 'eth_getHashFromTagBySimulator',
params: [timestamp]
})
}
if (methods.length > 0) {
web3.extend({
property: 'eth',
methods: methods,
properties: []
public registerCallId(id) {
return this.requestManager.send({
method: 'eth_registerCallId',
params: [id]
})
}
}

@ -374,7 +374,7 @@ export class VMContext {
return this.currentVm
}
addBlock (block: Block, genesis?: boolean) {
addBlock (block: Block, genesis?: boolean, isCall?: boolean) {
let blockNumber = bigIntToHex(block.header.number)
if (blockNumber === '0x') {
blockNumber = '0x0'
@ -384,7 +384,7 @@ export class VMContext {
this.blocks[blockNumber] = block
this.latestBlockNumber = blockNumber
if (!genesis) this.logsManager.checkBlock(blockNumber, block, this.web3())
if (!isCall && !genesis) this.logsManager.checkBlock(blockNumber, block, this.web3())
}
trackTx (txHash, block, tx) {

@ -1,5 +1,5 @@
/* global describe, before, it */
import Web3 from 'web3'
import Web3, { FMT_BYTES, FMT_NUMBER } from 'web3'
import { Provider } from '../src/index'
const web3 = new Web3()
import * as assert from 'assert'
@ -21,9 +21,9 @@ describe('Accounts', () => {
describe('eth_getBalance', () => {
it('should get a account balance', async () => {
const accounts: string[] = await web3.eth.getAccounts()
const balance0: string = await web3.eth.getBalance(accounts[0])
const balance1: string = await web3.eth.getBalance(accounts[1])
const balance2: string = await web3.eth.getBalance(accounts[2])
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 })
assert.deepEqual(balance0, '100000000000000000000')
assert.deepEqual(balance1, '100000000000000000000')
@ -34,9 +34,9 @@ describe('Accounts', () => {
describe('eth_sign', () => {
it('should sign payloads', async () => {
const accounts: string[] = await web3.eth.getAccounts()
const signature: string = await web3.eth.sign('Hello world', accounts[0])
const signature = await web3.eth.sign(web3.utils.utf8ToHex('Hello world'), accounts[0])
assert.deepEqual(signature.length, 132)
assert.deepEqual(typeof signature === 'string' ? signature.length : signature.signature.length, 132)
})
})
})

@ -18,23 +18,22 @@ describe('blocks', () => {
const block = await web3.eth.getBlock(0)
const expectedBlock = {
baseFeePerGas: 1,
difficulty: 0,
baseFeePerGas: '1',
difficulty: '0',
extraData: '0x0',
gasLimit: 8000000,
gasUsed: 0,
gasLimit: '8000000',
gasUsed: '0',
hash: block.hash.toString(),
logsBloom: '0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331',
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331',
miner: '0x0000000000000000000000000000000000000001',
nonce: '0x0000000000000000',
number: 0,
nonce: '0',
number: '0',
parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
size: 163591,
size: '163591',
stateRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
timestamp: block.timestamp,
totalDifficulty: '0',
transactions: [],
transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
uncles: []
}
@ -94,10 +93,9 @@ describe('blocks', () => {
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]}, (err, numberTransactions) => {
if (err) return reject(err)
resolve(numberTransactions)
})
web3['_requestManager'].send({method: 'eth_getUncleCountByBlockHash', params: [correctBlock.hash]})
.then(numberTransactions => resolve(numberTransactions))
.catch(err => reject(err))
}))
assert.deepEqual(numberTransactions, correctBlock.uncles.length)
})
@ -107,17 +105,16 @@ describe('blocks', () => {
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]}, (err, numberTransactions) => {
if (err) return reject(err)
resolve(numberTransactions)
})
web3['_requestManager'].send({method: 'eth_getUncleCountByBlockHash', params: [0]})
.then(numberTransactions => resolve(numberTransactions))
.catch(err => reject(err))
}))
assert.deepEqual(numberTransactions, correctBlock.uncles.length)
})
})
describe('eth_getStorageAt', () => {
it('should get storage at position at given address', async () => {
const abi: any = [
const abi = [
{
'constant': false,
'inputs': [
@ -197,16 +194,16 @@ describe('blocks', () => {
'stateMutability': 'view',
'type': 'function'
}
]
] as const
const code = '0x608060405234801561001057600080fd5b506040516020806102018339810180604052602081101561003057600080fd5b810190808051906020019092919050505080600081905550506101a9806100586000396000f3fe60806040526004361061005c576000357c0100000000000000000000000000000000000000000000000000000000900480632a1afcd91461006157806360fe47b11461008c5780636d4ce63c146100c7578063ce01e1ec146100f2575b600080fd5b34801561006d57600080fd5b5061007661012d565b6040518082815260200191505060405180910390f35b34801561009857600080fd5b506100c5600480360360208110156100af57600080fd5b8101908080359060200190929190505050610133565b005b3480156100d357600080fd5b506100dc61013d565b6040518082815260200191505060405180910390f35b3480156100fe57600080fd5b5061012b6004803603602081101561011557600080fd5b8101908080359060200190929190505050610146565b005b60005481565b8060008190555050565b60008054905090565b80600081905550807f63a242a632efe33c0e210e04e4173612a17efa4f16aa4890bc7e46caece80de060405160405180910390a25056fea165627a7a7230582063160eb16dc361092a85ced1a773eed0b63738b83bea1e1c51cf066fa90e135d0029'
const contract = new web3.eth.Contract(abi)
const accounts = await web3.eth.getAccounts()
const contractInstance: any = await contract.deploy({ data: code, arguments: [100] }).send({ from: accounts[0], gas: 400000 })
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
// 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)
@ -223,7 +220,7 @@ describe('blocks', () => {
})
describe('eth_call', () => {
it('should get a value', async () => {
const abi: any = [
const abi = [
{
'constant': false,
'inputs': [
@ -303,16 +300,15 @@ describe('blocks', () => {
'stateMutability': 'view',
'type': 'function'
}
]
] as const
const code = '0x608060405234801561001057600080fd5b506040516020806102018339810180604052602081101561003057600080fd5b810190808051906020019092919050505080600081905550506101a9806100586000396000f3fe60806040526004361061005c576000357c0100000000000000000000000000000000000000000000000000000000900480632a1afcd91461006157806360fe47b11461008c5780636d4ce63c146100c7578063ce01e1ec146100f2575b600080fd5b34801561006d57600080fd5b5061007661012d565b6040518082815260200191505060405180910390f35b34801561009857600080fd5b506100c5600480360360208110156100af57600080fd5b8101908080359060200190929190505050610133565b005b3480156100d357600080fd5b506100dc61013d565b6040518082815260200191505060405180910390f35b3480156100fe57600080fd5b5061012b6004803603602081101561011557600080fd5b8101908080359060200190929190505050610146565b005b60005481565b8060008190555050565b60008054905090565b80600081905550807f63a242a632efe33c0e210e04e4173612a17efa4f16aa4890bc7e46caece80de060405160405180910390a25056fea165627a7a7230582063160eb16dc361092a85ced1a773eed0b63738b83bea1e1c51cf066fa90e135d0029'
const contract = new web3.eth.Contract(abi)
const accounts = await web3.eth.getAccounts()
const contractInstance: any = await contract.deploy({ data: code, arguments: [100] }).send({ from: accounts[0], gas: 400000 })
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
const value = await contractInstance.methods.get().call({ from: accounts[0] })
assert.deepEqual(value, 100)

@ -12,26 +12,21 @@ describe('Misc', () => {
})
describe('web3_clientVersion', () => {
it('should get correct remix simulator version', async (done) => {
web3['_requestManager'].send({ method: 'web3_clientVersion', params: [] }, (err, version) => {
if (err) {
throw new Error(err)
}
const remixVersion = require('../package.json').version
assert.equal(version, 'Remix Simulator/' + remixVersion)
done()
})
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) })
})
})
describe('eth_protocolVersion', () => {
it('should get protocol version', async () => {
web3['_requestManager'].send({ method: 'eth_protocolVersion', params: [] }, (err, result) => {
if (err) {
throw new Error(err)
}
assert.equal(result, '0x3f')
})
web3['_requestManager'].send({ method: 'eth_protocolVersion', params: [] })
.then(result => assert.equal(result, '0x3f'))
.catch(err => { throw new Error(err) })
})
})
@ -58,56 +53,41 @@ describe('Misc', () => {
describe('web3_sha3', () => {
it('should get result of a sha3', async () => {
web3['_requestManager'].send({ method: 'web3_sha3', params: ['0x68656c6c6f20776f726c64'] }, (err, result) => {
if (err) {
throw new Error(err)
}
assert.equal(result, '0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad')
})
web3['_requestManager'].send({ method: 'web3_sha3', params: ['0x68656c6c6f20776f726c64'] })
.then(result => assert.equal(result, '0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad'))
.catch(err => { throw new Error(err)} )
})
})
describe('eth_getCompilers', () => {
it('should get list of compilers', async () => {
web3['_requestManager'].send({ method: 'eth_getCompilers', params: [] }, (err, result) => {
if (err) {
throw new Error(err)
}
assert.equal(result, 0)
})
web3['_requestManager'].send({ method: 'eth_getCompilers', params: [] })
.then(result => assert.equal(result, 0))
.catch(err => { throw new Error(err) })
})
})
describe('eth_compileSolidity', () => {
it('get unsupported result when requesting solidity compiler', async () => {
web3['_requestManager'].send({ method: 'eth_compileSolidity', params: [] }, (err, result) => {
if (err) {
throw new Error(err)
}
assert.equal(result, 'unsupported')
})
web3['_requestManager'].send({ method: 'eth_compileSolidity', params: [] })
.then(result => assert.equal(result, 'unsupported'))
.catch(err => { throw new Error(err) })
})
})
describe('eth_compileLLL', () => {
it('get unsupported result when requesting LLL compiler', async () => {
web3['_requestManager'].send({ method: 'eth_compileLLL', params: [] }, (err, result) => {
if (err) {
throw new Error(err)
}
assert.equal(result, 'unsupported')
})
web3['_requestManager'].send({ method: 'eth_compileLLL', params: [] })
.then(result => assert.equal(result, 'unsupported'))
.catch(err => { throw new Error(err) })
})
})
describe('eth_compileSerpent', () => {
it('get unsupported result when requesting serpent compiler', async () => {
web3['_requestManager'].send({ method: 'eth_compileSerpent', params: [] }, (err, result) => {
if (err) {
throw new Error(err)
}
assert.equal(result, 'unsupported')
})
web3['_requestManager'].send({ method: 'eth_compileSerpent', params: [] })
.then(result => assert.equal(result, 'unsupported'))
.catch(err => { throw new Error(err)} )
})
})
})

@ -28,7 +28,7 @@
"semver": "^6.3.0",
"solc": "^0.7.4",
"string-similarity": "^4.0.4",
"web3": "^1.5.1",
"web3": "^4.1.1",
"webworkify-webpack": "^2.1.5"
},
"devDependencies": {
@ -58,4 +58,4 @@
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-solidity#readme",
"typings": "src/index.d.ts",
"gitHead": "b6db2a29c223e423c70f06b87d9b245e26f0b220"
}
}

@ -62,7 +62,7 @@
"string-similarity": "^4.0.4",
"time-stamp": "^2.2.0",
"tslib": "^2.3.0",
"web3": "^1.5.1",
"web3": "^4.1.1",
"winston": "^3.0.0"
},
"devDependencies": {
@ -79,4 +79,4 @@
},
"typings": "src/index.d.ts",
"gitHead": "b6db2a29c223e423c70f06b87d9b245e26f0b220"
}
}

@ -1,6 +1,6 @@
import async from 'async'
import { execution } from '@remix-project/remix-lib'
import Web3 from 'web3'
import Web3, { FMT_BYTES, FMT_NUMBER } from 'web3'
import { compilationInterface } from './types'
/**
@ -58,7 +58,7 @@ export function deployAll (compileResult: compilationInterface, web3: Web3, test
},
function deployContracts (contractsToDeploy: string[], next) {
const deployRunner = (deployObject, contractObject, contractName, filename, callback) => {
deployObject.estimateGas().then((gasValue) => {
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({

@ -127,10 +127,9 @@ commander
nodeUrl: options.nodeUrl || null,
blockNumber: options.blockNumber || null
}
const web3 = new Web3()
const provider: any = new Provider(providerConfig)
await provider.init()
web3.setProvider(provider)
const web3 = new Web3(provider)
extend(web3)
runTestFiles(path.resolve(file_path), isDirectory, web3, compilerConfig, (error, totalPassing, totalFailing) => {
if (error) process.exit(1)

@ -62,10 +62,12 @@ export function runTestFiles (filepath: string, isDirectory: boolean, web3: Web3
async.waterfall([
function getAccountList (next) {
if (accounts) return next(null)
web3.eth.getAccounts((_err: Error | null | undefined, _accounts) => {
accounts = _accounts
next(null)
})
web3.eth.getAccounts()
.then(_accounts => {
accounts = _accounts
next(null)
})
.catch((_err: Error | null | undefined) => next(null))
},
function compile (next) {
compileFileOrFiles(filepath, isDirectory, { accounts }, compilerConfig, next)
@ -82,10 +84,10 @@ export function runTestFiles (filepath: string, isDirectory: boolean, web3: Web3
// accept deployment params from UI
if (err.message.includes('The contract code couldn\'t be stored, please check your gas limit')) {
deployAll(compilationResult, web3, accounts, true, null, (error, contracts) => {
if (error) next([{ message: 'contract deployment failed after trying twice: ' + error.message, severity: 'error' }]) // IDE expects errors in array
if (error) next([{ message: 'contract deployment failed after trying twice: ' + error.innerError || error.message, severity: 'error' }]) // IDE expects errors in array
else next(null, compilationResult, contracts)
})
} else { next([{ message: 'contract deployment failed: ' + err.message, severity: 'error' }]) } // IDE expects errors in array
} else { next([{ message: 'contract deployment failed: ' + err.innerError || err.message, severity: 'error' }]) } // IDE expects errors in array
} else { next(null, compilationResult, contracts) }
})
},

@ -64,10 +64,10 @@ export class UnitTestRunner {
// accept deployment params from UI
if (err.message.includes('The contract code couldn\'t be stored, please check your gas limit')) {
deployAll(compilationResult, this.web3, this.testsAccounts, true, deployCb, (error, contracts) => {
if (error) next([{ message: 'contract deployment failed after trying twice: ' + error.message, severity: 'error' }]) // IDE expects errors in array
if (error) next([{ message: 'contract deployment failed after trying twice: ' + error.innerError || error.message, severity: 'error' }]) // IDE expects errors in array
else next(null, compilationResult, contracts)
})
} else { next([{ message: 'contract deployment failed: ' + err.message, severity: 'error' }]) } // IDE expects errors in array
} else { next([{ message: 'contract deployment failed: ' + err.innerError || err.message, severity: 'error' }]) } // IDE expects errors in array
} else { next(null, compilationResult, contracts) }
})
},

@ -214,6 +214,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
let passingNum = 0
let failureNum = 0
let timePassed = 0
const failedTransactions = {}
const isJSONInterfaceAvailable = testObject && testObject.options && testObject.options.jsonInterface
if (!isJSONInterfaceAvailable) { return resultsCallback(new Error('Contract interface not available'), { passingNum, failureNum, timePassed }) }
const runList: RunListInterface[] = createRunList(testObject.options.jsonInterface, fileAST, testName)
@ -249,12 +250,12 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
if (func.constant) {
sendParams = {}
const tagTimestamp = 'remix_tests_tag' + Date.now()
sendParams.timestamp = tagTimestamp
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.eth && web3.eth.getHashFromTagBySimulator) tagTxHash = await web3.eth.getHashFromTagBySimulator(tagTimestamp)
if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(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) {
const resp: TestResultInterface = {
@ -301,17 +302,17 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
method.send(sendParams).on('receipt', async (receipt) => {
try {
debugTxHash = receipt.transactionHash
if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(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.events) {
let events = receipt.events[i]
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.raw.topics[0]) // event name topic will always be at index 0
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.raw.data)
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
@ -378,9 +379,11 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
}
}).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
let errMsg = err.message
let txHash
if (err.reason) errMsg = `transaction reverted with the reason: ${err.reason}`
if (err.reason) errMsg = `transaction reverted with the reason: ${err.reason}`
const resp: TestResultInterface = {
type: 'testFailure',
value: changeCase.sentenceCase(func.name),
@ -394,7 +397,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
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.eth && web3.eth.getHHLogsForTx && txHash) hhLogs = await web3.eth.getHHLogsForTx(txHash)
if (web3.remix && web3.remix.getHHLogsForTx && txHash) hhLogs = await web3.remix.getHHLogsForTx(txHash)
if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs
resp.debugTxHash = txHash
testCallback(undefined, resp)

@ -4,10 +4,10 @@ import { expect } from 'chai';
describe('testRunner: remix-tests CLI', function(){
this.timeout(120000)
// remix-tests binary, after build, is used as executable
// remix-tests binary, after build, is used as executable
const executablePath = resolve(__dirname + '/../../../dist/libs/remix-tests/bin/remix-tests')
const result = spawnSync('ls', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
if(result) {
const dirContent = result.stdout.toString()
@ -20,7 +20,7 @@ describe('testRunner: remix-tests CLI', function(){
execSync('yarn install', { cwd: resolve(__dirname + '/../../../dist/libs/remix-tests') })
}
}
describe('test various CLI options', function() {
it('remix-tests version', () => {
@ -74,10 +74,10 @@ Commands:
expect(res.stdout.toString().trim()).to.match(/Expected value should be ok to: true/)
expect(res.stdout.toString().trim()).to.match(/Received: false/)
expect(res.stdout.toString().trim()).to.match(/Message: okFailTest fails/)
})
it('remix-tests running a test file with custom compiler version', () => {
const res = spawnSync(executablePath, ['--compiler', '0.7.4', resolve(__dirname + '/examples_0/assert_ok_test.sol')])
@ -92,13 +92,13 @@ Commands:
// match fail test details
expect(res.stdout.toString().trim()).to.match(/Message: okFailTest fails/)
})
it('remix-tests running a test file with unavailable custom compiler version (should fail)', () => {
const res = spawnSync(executablePath, ['--compiler', '1.10.4', resolve(__dirname + '/examples_0/assert_ok_test.sol')])
// match initial lines
expect(res.stdout.toString().trim()).to.contain('No compiler found in releases with version 1.10.4')
})
it('remix-tests running a test file with custom EVM', () => {
const res = spawnSync(executablePath, ['--evm', 'petersburg', resolve(__dirname + '/examples_0/assert_ok_test.sol')])
// match initial lines
@ -111,7 +111,7 @@ Commands:
// match fail test details
expect(res.stdout.toString().trim()).to.match(/Message: okFailTest fails/)
})
it('remix-tests running a test file by enabling optimization', () => {
const res = spawnSync(executablePath, ['--optimize', 'true', resolve(__dirname + '/examples_0/assert_ok_test.sol')])
// match initial lines
@ -124,7 +124,7 @@ Commands:
// match fail test details
expect(res.stdout.toString().trim()).to.match(/Message: okFailTest fails/)
})
it('remix-tests running a test file by enabling optimization and setting runs', () => {
const res = spawnSync(executablePath, ['--optimize', 'true', '--runs', '300', resolve(__dirname + '/examples_0/assert_ok_test.sol')])
// match initial lines
@ -161,6 +161,6 @@ Commands:
// match fail test details
expect(res.stdout.toString().trim()).to.match(/Message: okFailTest fails/)
})
})
})
})

@ -53,14 +53,16 @@ async function compileAndDeploy(filename: string, callback: any) {
let compilationData: any
async.waterfall([
function getAccountList(next: any): void {
web3.eth.getAccounts((_err: Error | null | undefined, _accounts: string[]) => {
accounts = _accounts
web3.eth.defaultAccount = accounts[0]
next(_err)
})
web3.eth.getAccounts()
.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 }, null, next)
compileFileOrFiles(filename, false, { accounts, web3 }, null, next)
},
function deployAllContracts(compilationResult: compilationInterface, asts, next: any): void {
for (const filename in asts) {
@ -131,8 +133,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', 'web3'])
//
], ['time','type','debugTxHash','location','expected','returned','errMsg','assertMethod','web3'])
})
})
@ -141,7 +143,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('AssertEqualTest', contracts.AssertEqualTest, compilationData[filename]['AssertEqualTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -182,7 +184,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('AssertNotEqualTest', contracts.AssertNotEqualTest, compilationData[filename]['AssertNotEqualTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -222,7 +224,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('AssertGreaterThanTest', contracts.AssertGreaterThanTest, compilationData[filename]['AssertGreaterThanTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -256,7 +258,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('AssertLesserThanTest', contracts.AssertLesserThanTest, compilationData[filename]['AssertLesserThanTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -291,7 +293,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -322,7 +324,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -352,7 +354,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('StringTest', contracts.StringTest, compilationData[filename]['StringTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -378,7 +380,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('StorageResolveTest', contracts.StorageResolveTest, compilationData[filename]['StorageResolveTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -405,7 +407,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('SafeMathTest', contracts.SafeMathTest, compilationData[filename]['SafeMathTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -425,7 +427,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('IntegerTest', contracts.IntegerTest, compilationData[filename]['IntegerTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -445,7 +447,7 @@ describe('testRunner', function () {
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 }, testCallback, resultsCallback(done))
runTest('SenderAndValueTest', contracts.SenderAndValueTest, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -473,7 +475,7 @@ 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 }, testCallback, errorCallback(done))
runTest('SenderAndValueTest', undefined, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts, web3 }, testCallback, errorCallback(done))
})
})
@ -486,4 +488,4 @@ describe('testRunner', function () {
})
})
})
})

@ -14,9 +14,7 @@ export const DebuggerApiMixin = (Base) => class extends Base {
const self = this
this.web3Provider = {
sendAsync (payload, callback) {
self.call('web3Provider', 'sendAsync', payload)
.then(result => callback(null, result))
.catch(e => callback(e))
return self.call('web3Provider', 'sendAsync', payload)
}
}
this._web3 = new Web3(this.web3Provider)

@ -4,6 +4,7 @@ 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'
export const DropdownPanel = (props: DropdownPanelProps) => {
@ -55,6 +56,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 (hexHighlight && typeof data.self === 'string') {
const isHex = data.self.startsWith('0x') || hexHighlight
if (isHex) {
@ -184,6 +186,10 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
else if (calldata && Object.keys(calldata).length === 0 && calldata.constructor === Object) isEmpty = true
setState((prevState) => {
const copiableContent = JSON.stringify(calldata, (key, value) => {
if (isBigInt(value)) value = value.toString()
return value
}, '\t').replace(/0xNaN/g, '0x0')
return {
...prevState,
dropdownContent: {
@ -191,7 +197,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
display: 'block'
},
// replace 0xNaN with 0x0
copiableContent: JSON.stringify(calldata, null, '\t').replace(/0xNaN/g, '0x0'),
copiableContent,
message: {
innerText: isEmpty ? intl.formatMessage({id: 'debugger.noDataAvailable'}) : '',
display: isEmpty ? 'block' : 'none'

@ -1,7 +1,6 @@
import React from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
import {BN} from 'bn.js'
import Web3 from 'web3'
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
@ -18,7 +17,7 @@ export const GlobalVariables = ({block, receipt, tx, className}) => {
'tx.origin': tx && tx.from
}
if (block && block.baseFeePerGas) {
globals['block.basefee'] = Web3.utils.toBN(block.baseFeePerGas).toString(10) + ` Wei (${block.baseFeePerGas})`
globals['block.basefee'] = toBigInt(block.baseFeePerGas).toString(10) + ` Wei (${block.baseFeePerGas})`
}
return (

@ -184,40 +184,32 @@ export const loadTypes = async (monaco) => {
// Web3
// @ts-ignore
const indexWeb3 = await import('raw-loader!web3/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3.default, `file:///node_modules/@types/web3/index.d.ts`)
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 indexWeb3Bzz = await import('raw-loader!web3-bzz/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Bzz.default, `file:///node_modules/@types/web3-bzz/index.d.ts`)
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 indexWeb3Core = await import('raw-loader!web3-core/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Core.default, `file:///node_modules/@types/web3-core/index.d.ts`)
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 indexWeb3Eth = await import('raw-loader!web3-eth/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Eth.default, `file:///node_modules/@types/web3-eth/index.d.ts`)
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 indexWeb3Personal = await import('raw-loader!web3-eth-personal/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Personal.default, `file:///node_modules/@types/web3-eth-personal/index.d.ts`)
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 indexWeb3Contract = await import('raw-loader!web3-eth-contract/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Contract.default, `file:///node_modules/@types/web3-eth-contract/index.d.ts`)
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 indexWeb3Net = await import('raw-loader!web3-net/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Net.default, `file:///node_modules/@types/web3-net/index.d.ts`)
// @ts-ignore
const indexWeb3Shh = await import('raw-loader!web3-shh/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Shh.default, `file:///node_modules/@types/web3-shh/index.d.ts`)
// @ts-ignore
const indexWeb3Util = await import('raw-loader!web3-utils/types/index.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(indexWeb3Util.default, `file:///node_modules/@types/web3-utils/index.d.ts`)
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 {

@ -2,7 +2,7 @@
import React, {useEffect, useState} from 'react'
import {FormattedMessage, useIntl} from 'react-intl'
import {CopyToClipboard} from '@remix-ui/clipboard'
import Web3 from 'web3'
import {fromWei, toBigInt, toWei} from 'web3-utils'
import {MainnetProps} from '../types'
export function MainnetPrompt(props: MainnetProps) {
@ -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 = Web3.utils.fromWei(Web3.utils.toBN(props.network.lastBlock.baseFeePerGas), 'Gwei')
const baseFee = fromWei(toBigInt(props.network.lastBlock.baseFeePerGas), 'Gwei')
setBaseFee(baseFee)
onMaxFeeChange(baseFee)
@ -27,7 +27,7 @@ export function MainnetPrompt(props: MainnetProps) {
const onMaxFeeChange = (value: string) => {
const maxFee = value
// @ts-ignore
if (Web3.utils.toBN(props.network.lastBlock.baseFeePerGas).gt(Web3.utils.toBN(Web3.utils.toWei(maxFee, 'Gwei')))) {
if (toBN(props.network.lastBlock.baseFeePerGas).gt(toBN(toWei(maxFee, 'Gwei')))) {
setTransactionFee(intl.formatMessage({id: 'udapp.transactionFeeText'}))
props.updateGasPriceStatus(false)
props.updateConfirmSettings(true)
@ -125,7 +125,7 @@ export function MainnetPrompt(props: MainnetProps) {
<div className="align-items-center my-1" title={intl.formatMessage({id: 'udapp.title2'})}>
<div className="d-flex">
<span className="text-dark mr-2 text-nowrap">
<FormattedMessage id="udapp.maxFee" values={{baseFeePerGas: Web3.utils.fromWei(Web3.utils.toBN(props.network.lastBlock.baseFeePerGas), 'Gwei')}} />:
<FormattedMessage id="udapp.maxFee" values={{baseFeePerGas: fromWei(toBigInt(props.network.lastBlock.baseFeePerGas), 'Gwei')}} />:
</span>
<input
className="form-control mr-1 text-right"

@ -22,7 +22,7 @@
"@openzeppelin/contracts": "^5.0.0",
"@openzeppelin/wizard": "^0.4.0",
"ethers": "^5.4.2",
"web3": "^1.5.1"
"web3": "^4.1.1"
},
"gitHead": "b6db2a29c223e423c70f06b87d9b245e26f0b220"
}
}

@ -154,6 +154,7 @@
"color-support": "^1.1.3",
"commander": "^9.4.1",
"core-js": "^3.6.5",
"cors": "^2.8.5",
"deep-equal": "^1.0.1",
"document-register-element": "1.13.1",
"eslint-config-prettier": "^8.5.0",
@ -211,7 +212,7 @@
"tslib": "^2.3.0",
"viem": "^1.6.0",
"wagmi": "^1.3.10",
"web3": "^1.8.0",
"web3": "^4.1.0",
"winston": "^3.3.3",
"ws": "^7.3.0"
},

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save