Merge branch 'master' into fix-resolver

pull/3262/head
David Disu 2 years ago committed by GitHub
commit 73ac187fa2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .circleci/config.yml
  2. 1
      apps/debugger/webpack.config.js
  3. 6
      apps/remix-ide-e2e/src/tests/debugger.test.ts
  4. 49
      apps/remix-ide-e2e/src/tests/remixd.test.ts
  5. 2
      apps/remix-ide/.babelrc
  6. 1
      apps/remix-ide/ci/browser_test.sh
  7. 7
      apps/remix-ide/src/app/tabs/test-tab.js
  8. 10
      apps/remix-ide/src/blockchain/blockchain.js
  9. 6
      apps/remix-ide/src/blockchain/execution-context.js
  10. 27
      apps/remix-ide/src/blockchain/providers/vm.js
  11. 36
      apps/remix-ide/src/blockchain/providers/worker-vm.ts
  12. 1
      babel.config.js
  13. 6
      libs/remix-analyzer/package.json
  14. 6
      libs/remix-astwalker/package.json
  15. 8
      libs/remix-debug/package.json
  16. 8
      libs/remix-debug/src/code/codeUtils.ts
  17. 3
      libs/remix-lib/package.json
  18. 4
      libs/remix-lib/src/execution/txExecution.ts
  19. 6
      libs/remix-lib/src/execution/txListener.ts
  20. 58
      libs/remix-lib/src/execution/txRunnerVM.ts
  21. 5
      libs/remix-lib/src/execution/txRunnerWeb3.ts
  22. 1
      libs/remix-lib/src/index.ts
  23. 8
      libs/remix-simulator/package.json
  24. 224
      libs/remix-simulator/src/VmProxy.ts
  25. 5
      libs/remix-simulator/src/genesis.ts
  26. 10
      libs/remix-simulator/src/methods/accounts.ts
  27. 44
      libs/remix-simulator/src/methods/blocks.ts
  28. 4
      libs/remix-simulator/src/methods/misc.ts
  29. 84
      libs/remix-simulator/src/methods/transactions.ts
  30. 5
      libs/remix-simulator/src/provider.ts
  31. 80
      libs/remix-simulator/src/vm-context.ts
  32. 2
      libs/remix-simulator/test/blocks.ts
  33. 6
      libs/remix-solidity/package.json
  34. 8
      libs/remix-tests/package.json
  35. 9
      libs/remix-tests/src/runTestSources.ts
  36. 102
      libs/remix-tests/tests/testRunner.spec.ts
  37. 1
      libs/remix-ui/run-tab/src/lib/types/execution-context.d.ts
  38. 4
      libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx
  39. 4
      libs/remix-ui/terminal/src/lib/components/ChechTxStatus.tsx
  40. 4
      libs/remix-ui/terminal/src/lib/components/Table.tsx
  41. 10
      libs/remix-ws-templates/src/templates/ozerc20/index.ts
  42. 104
      libs/remix-ws-templates/src/templates/ozerc20/tests/MyToken_mintable_test.sol
  43. 15
      libs/remix-ws-templates/src/templates/ozerc20/tests/MyToken_test.sol
  44. 16
      package.json
  45. 819
      yarn.lock

@ -313,3 +313,5 @@ workflows:
filters:
branches:
only: remix_beta
# VS Code Extension Version: 1.5.0

@ -2,6 +2,7 @@ const nxWebpack = require('@nrwl/react/plugins/webpack')
module.exports = config => {
const nxWebpackConfig = nxWebpack(config)
const webpackConfig = {
...nxWebpackConfig,
resolve : {

@ -167,7 +167,11 @@ module.exports = {
.clickFunction('t - transact (not payable)')
.pause(2000)
.debugTransaction(0)
.waitForElementVisible('*[data-id="slider"]').pause(2000)
.waitForElementVisible('*[data-id="slider"]')
.waitForElementVisible({
locateStrategy: 'xpath',
selector: '//*[@data-id="treeViewLivm trace step" and contains(.,"29")]',
})
.goToVMTraceStep(7453)
.waitForElementPresent('*[data-id="treeViewDivtreeViewItemarray"]')
.click('*[data-id="treeViewDivtreeViewItemarray"]')

@ -72,8 +72,8 @@ module.exports = {
return sources
},
'run Remixd tests #group4': function (browser) {
browser.perform((done) => {
remixd = spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts'))
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts'))
console.log('working directory', process.cwd())
connectRemixd(browser, done)
})
@ -86,8 +86,8 @@ module.exports = {
when a relative import is used (i.e import "openzeppelin-solidity/contracts/math/SafeMath.sol")
remix (as well as truffle) try to resolve it against the node_modules and installed_contracts folder.
*/
browser.perform((done) => {
remixd = spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts'))
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts'))
console.log('working directory', process.cwd())
connectRemixd(browser, done)
})
@ -100,8 +100,8 @@ module.exports = {
.testContracts('test_import_node_modules.sol', sources[3]['test_import_node_modules.sol'], ['SafeMath'])
},
'Import from node_modules and reference a github import #group2': function (browser) {
browser.perform((done) => {
remixd = spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts'))
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts'))
console.log('working directory', process.cwd())
connectRemixd(browser, done)
})
@ -146,8 +146,8 @@ module.exports = {
'Should listen on compilation result from hardhat #group5': function (browser: NightwatchBrowser) {
browser.perform((done) => {
remixd = spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/hardhat'))
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/hardhat'))
console.log('working directory', process.cwd())
connectRemixd(browser, done)
})
@ -181,8 +181,8 @@ module.exports = {
writeFileSync('./apps/remix-ide/contracts/hardhat/artifacts/build-info/7839ba878952cc00ff316061405f273a.json', JSON.stringify(hardhatCompilation))
done()
})
.perform((done) => {
remixd = spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/hardhat'))
.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/hardhat'))
console.log('working directory', process.cwd())
connectRemixd(browser, done)
})
@ -201,8 +201,8 @@ module.exports = {
'Should listen on compilation result from foundry #group7': function (browser: NightwatchBrowser) {
browser.perform((done) => {
remixd = spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/foundry'))
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/foundry'))
console.log('working directory', process.cwd())
connectRemixd(browser, done)
})
@ -236,8 +236,8 @@ module.exports = {
'Should listen on compilation result from truffle #group8': function (browser: NightwatchBrowser) {
browser.perform((done) => {
remixd = spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/truffle'))
browser.perform(async (done) => {
remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/truffle'))
console.log('working directory', process.cwd())
connectRemixd(browser, done)
})
@ -311,15 +311,22 @@ function testImportFromRemixd(browser: NightwatchBrowser, callback: VoidFunction
.perform(() => { callback() })
}
function spawnRemixd(path: string) {
async function spawnRemixd(path: string): Promise<ChildProcess> {
const remixd = spawn('yarn run remixd', [`-s ${path}`], { cwd: process.cwd(), shell: true, detached: true })
remixd.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString())
})
remixd.stderr.on('err', function (data) {
console.log('err: ' + data.toString())
return new Promise((resolve, reject) => {
remixd.stdout.on('data', function (data) {
if(
data.toString().includes('is listening')
|| data.toString().includes('There is already a client running')
) {
resolve(remixd)
}
})
remixd.stderr.on('err', function (data) {
reject(data.toString())
})
})
return remixd
}
function connectRemixd(browser: NightwatchBrowser, done: any) {

@ -2,7 +2,7 @@
"presets": ["@babel/preset-env", ["@babel/preset-react",
{"runtime": "automatic"}
]],
"plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime"],
"plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime", "@babel/plugin-proposal-nullish-coalescing-operator"],
"ignore": [
"**/node_modules/**"
]

@ -7,7 +7,6 @@ set -e
BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}}
echo "$BUILD_ID"
TEST_EXITCODE=0
yarn run ganache-cli &
yarn run serve:production &
echo 'sharing folder: ' $PWD '/apps/remix-ide/contracts' &

@ -74,7 +74,7 @@ module.exports = class TestTab extends ViewPlugin {
if (!isSolidityActive) {
await this.call('manager', 'activatePlugin', 'solidity')
}
await this.testRunner.init()
await this.testRunner.init(await this.call('blockchain', 'web3VM'))
await this.createTestLibs()
}
@ -108,7 +108,8 @@ module.exports = class TestTab extends ViewPlugin {
/*
Test is not associated with the UI
*/
testFromSource (content, path = 'browser/unit_test.sol') {
async testFromSource (content, path = 'browser/unit_test.sol') {
const web3 = await this.call('blockchain', 'web3VM')
return new Promise((resolve, reject) => {
const runningTest = {}
runningTest[path] = { content }
@ -126,6 +127,8 @@ module.exports = class TestTab extends ViewPlugin {
resolve(result)
}, (url, cb) => {
return this.contentImport.resolveAndSave(url).then((result) => cb(null, result)).catch((error) => cb(error.message))
}, {
web3
})
})
}

@ -22,7 +22,7 @@ const profile = {
name: 'blockchain',
displayName: 'Blockchain',
description: 'Blockchain - Logic',
methods: ['getCode', 'getTransactionReceipt', 'addProvider', 'removeProvider'],
methods: ['getCode', 'getTransactionReceipt', 'addProvider', 'removeProvider', 'getCurrentFork', 'web3VM'],
version: packageJson.version
}
@ -295,7 +295,7 @@ export class Blockchain extends Plugin {
if (error) {
return finalCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`)
}
if (txResult.receipt.status === false || txResult.receipt.status === '0x0') {
if (txResult.receipt.status === false || txResult.receipt.status === '0x0' || txResult.receipt.status === 0) {
return finalCb(`creation of ${selectedContract.name} errored: transaction execution failed`)
}
finalCb(null, selectedContract, address)
@ -401,6 +401,10 @@ export class Blockchain extends Plugin {
this.getCurrentProvider().signMessage(message, account, passphrase, cb)
}
web3VM () {
return this.providers.vm.web3
}
web3 () {
// @todo(https://github.com/ethereum/remix-project/issues/431)
const isVM = this.getProvider() === 'vm'
@ -733,7 +737,7 @@ export class Blockchain extends Plugin {
execResult = await this.web3().eth.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 ? execResult.returnValue : toBuffer(addHexPrefix(txResult.result) || '0x0000000000000000000000000000000000000000000000000000000000000000')
returnValue = execResult ? toBuffer(execResult.returnValue) : toBuffer(addHexPrefix(txResult.result) || '0x0000000000000000000000000000000000000000000000000000000000000000')
const compiledContracts = await this.call('compilerArtefacts', 'getAllContractDatas')
const vmError = txExecution.checkVMError(execResult, compiledContracts)
if (vmError.error) {

@ -133,11 +133,7 @@ export class ExecutionContext {
internalWeb3 () {
return web3
}
blankWeb3 () {
return new Web3()
}
setContext (context, endPointUrl, confirmCb, infoCb) {
this.executionContext = context
this.executionContextChange(context, endPointUrl, confirmCb, infoCb, null)

@ -1,10 +1,10 @@
const Web3 = require('web3')
const { BN, privateToAddress, hashPersonalMessage } = require('ethereumjs-util')
const { Provider, extend } = require('@remix-project/remix-simulator')
const { extend } = require('@remix-project/remix-simulator')
class VMProvider {
constructor (executionContext) {
this.executionContext = executionContext
this.worker = null
}
getAccounts (cb) {
@ -17,10 +17,27 @@ class VMProvider {
}
resetEnvironment () {
if (this.worker) this.worker.terminate()
this.accounts = {}
this.RemixSimulatorProvider = new Provider({ fork: this.executionContext.getCurrentFork() })
this.RemixSimulatorProvider.init()
this.web3 = new Web3(this.RemixSimulatorProvider)
this.worker = new Worker(new URL('./worker-vm', import.meta.url))
this.worker.postMessage({ cmd: 'init', fork: this.executionContext.getCurrentFork() })
let incr = 0
const stamps = {}
this.worker.addEventListener('message', (msg) => {
if (stamps[msg.data.stamp]) {
stamps[msg.data.stamp](msg.data.error, msg.data.result)
}
})
const provider = {
sendAsync: (query, callback) => {
const stamp = Date.now() + incr
incr++
stamps[stamp] = callback
this.worker.postMessage({ cmd: 'sendAsync', query, stamp })
}
}
this.web3 = new Web3(provider)
extend(this.web3)
this.accounts = {}
this.executionContext.setWeb3('vm', this.web3)

@ -0,0 +1,36 @@
import { Provider } from '@remix-project/remix-simulator'
let provider: Provider = null
self.onmessage = (e: MessageEvent) => {
const data = e.data
switch (data.cmd) {
case 'init':
{
provider = new Provider({ fork: data.fork })
if (provider) provider.init()
break
}
case 'sendAsync':
{
if (provider) {
provider.sendAsync(data.query, (error, result) => {
self.postMessage({
cmd: 'sendAsyncResult',
error,
result,
stamp: data.stamp
})
})
} else {
self.postMessage({
cmd: 'sendAsyncResult',
error: 'Provider not instantiated',
result: null,
stamp: data.stamp
})
}
break
}
}
}

@ -4,6 +4,7 @@ module.exports = {
"babel-plugin-replace-ts-export-assignment",
"@babel/plugin-transform-modules-commonjs",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-nullish-coalescing-operator",
["@babel/plugin-proposal-private-property-in-object", { "loose": false }],
["@babel/plugin-proposal-private-methods", { "loose": false }]]
}

@ -21,9 +21,9 @@
}
],
"dependencies": {
"@ethereumjs/block": "^3.5.1",
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"@ethereumjs/block": "^4.0.0",
"@ethereumjs/tx": "^4.0.0",
"@ethereumjs/vm": "^6.0.0",
"@remix-project/remix-astwalker": "^0.0.51",
"@remix-project/remix-lib": "^0.5.21",
"async": "^2.6.2",

@ -33,9 +33,9 @@
]
},
"dependencies": {
"@ethereumjs/block": "^3.5.1",
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"@ethereumjs/block": "^4.0.0",
"@ethereumjs/tx": "^4.0.0",
"@ethereumjs/vm": "^6.0.0",
"@remix-project/remix-lib": "^0.5.21",
"@types/tape": "^4.2.33",
"async": "^2.6.2",

@ -21,10 +21,10 @@
"test": "./../../node_modules/.bin/ts-node --project ../../tsconfig.base.json --require tsconfig-paths/register ./../../node_modules/.bin/tape ./test/tests.ts"
},
"dependencies": {
"@ethereumjs/block": "^3.5.1",
"@ethereumjs/common": "^2.5.0",
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"@ethereumjs/block": "^4.0.0",
"@ethereumjs/common": "^3.0.0",
"@ethereumjs/tx": "^4.0.0",
"@ethereumjs/vm": "^6.0.0",
"@remix-project/remix-astwalker": "^0.0.51",
"@remix-project/remix-lib": "^0.5.21",
"@remix-project/remix-simulator": "^0.2.21",

@ -1,11 +1,11 @@
'use strict'
import Common from '@ethereumjs/common'
import { getOpcodesForHF } from '@ethereumjs/vm/dist/evm/opcodes'
import { Common } from '@ethereumjs/common'
import { getOpcodesForHF, OpcodeList } from '@ethereumjs/evm/dist/opcodes/codes'
import getOpcodes from './opcodes'
export function nameOpCodes (raw, hardfork) {
const common = new Common({ chain: 'mainnet', hardfork })
const opcodes = getOpcodesForHF(common)
const opcodes = getOpcodesForHF(common).opcodes
let pushData = ''
const codeMap = {}
@ -47,7 +47,7 @@ type Opcode = {
*/
export function parseCode (raw) {
const common = new Common({ chain: 'mainnet', hardfork: 'london' })
const opcodes = getOpcodesForHF(common)
const opcodes = getOpcodesForHF(common).opcodes
const code = []
for (let i = 0; i < raw.length; i++) {

@ -17,9 +17,6 @@
"test": "./../../node_modules/.bin/ts-node --require tsconfig-paths/register ./../../node_modules/.bin/tape ./test/tests.ts"
},
"dependencies": {
"@ethereumjs/block": "^3.5.1",
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"async": "^2.1.2",
"ethereumjs-util": "^7.0.10",
"ethers": "^4.0.40",

@ -89,7 +89,7 @@ export function checkVMError (execResult, compiledContracts) {
ret.error = true
} else if (exceptionError === errorCode.REVERT) {
const returnData = execResult.returnValue
const returnDataHex = returnData.slice(0, 4).toString('hex')
const returnDataHex = returnData.slice(2, 10)
let customError
if (compiledContracts) {
let decodedCustomErrorInputsClean
@ -159,7 +159,7 @@ export function checkVMError (execResult, compiledContracts) {
// It is the hash of Error(string)
if (returnData && (returnDataHex === '08c379a0')) {
const abiCoder = new ethers.utils.AbiCoder()
const reason = abiCoder.decode(['string'], returnData.slice(4))[0]
const reason = abiCoder.decode(['string'], '0x' + returnData.slice(10))[0]
msg = `\tThe transaction has been reverted to the initial state.\nReason provided by the contract: "${reason}".`
} else {
msg = '\tThe transaction has been reverted to the initial state.\nNote: The called function should be payable if you send value and the value you send should be less than your current balance.'

@ -10,7 +10,7 @@ function addExecutionCosts (txResult, tx, execResult) {
if (txResult) {
if (execResult) {
tx.returnValue = execResult.returnValue
if (execResult.gasUsed) tx.executionCost = execResult.gasUsed.toString(10)
if (execResult.executionGasUsed) tx.executionCost = execResult.executionGasUsed.toString(10)
}
if (txResult.receipt && txResult.receipt.gasUsed) tx.transactionCost = txResult.receipt.gasUsed.toString(10)
}
@ -64,7 +64,7 @@ export class TxListener {
let execResult
if (this.executionContext.isVM()) {
execResult = await this.executionContext.web3().eth.getExecutionResultFromSimulator(txResult.transactionHash)
returnValue = execResult.returnValue
returnValue = toBuffer(execResult.returnValue)
} else {
returnValue = toBuffer(addHexPrefix(txResult.result))
}
@ -104,7 +104,7 @@ export class TxListener {
addExecutionCosts(txResult, tx, execResult)
tx.envMode = this.executionContext.getProvider()
tx.status = txResult.receipt.status // 0x0 or 0x1
tx.status = txResult.receipt.status
this._resolve([tx])
})
})

@ -1,10 +1,21 @@
'use strict'
import { RunBlockResult, RunTxResult } from '@ethereumjs/vm'
import { Transaction, FeeMarketEIP1559Transaction } from '@ethereumjs/tx'
import { Block } from '@ethereumjs/block'
import { BN, bufferToHex, Address } from 'ethereumjs-util'
import type { Account } from '@ethereumjs/util'
import { EventManager } from '../eventManager'
import { LogsManager } from './logsManager'
export type VMexecutionResult = {
result: RunTxResult,
transactionHash: string
block: Block,
tx: Transaction
}
export type VMExecutionCallBack = (error: string | Error, result?: VMexecutionResult) => void
export class TxRunnerVM {
event
blockNumber
@ -41,20 +52,20 @@ export class TxRunnerVM {
this.nextNonceForCall = 0
}
execute (args, confirmationCb, gasEstimationForceSend, promptCb, callback) {
execute (args, confirmationCb, gasEstimationForceSend, promptCb, callback: VMExecutionCallBack) {
let data = args.data
if (data.slice(0, 2) !== '0x') {
data = '0x' + data
}
try {
this.runInVm(args.from, args.to, data, args.value, args.gasLimit, args.useCall, args.timestamp, callback)
this.runInVm(args.from, args.to, data, args.value, args.gasLimit, args.useCall, callback)
} catch (e) {
callback(e, null)
}
}
runInVm (from, to, data, value, gasLimit, useCall, timestamp, callback) {
runInVm (from: string, to: string, data: string, value: string, gasLimit: number, useCall: boolean, callback: VMExecutionCallBack) {
const self = this
let account
if (!from && useCall && Object.keys(self.vmaccounts).length) {
@ -65,30 +76,13 @@ export class TxRunnerVM {
if (!account) {
return callback('Invalid account selected')
}
if (Number.isInteger(gasLimit)) {
gasLimit = '0x' + gasLimit.toString(16)
}
this.getVMObject().stateManager.getAccount(Address.fromString(from)).then((res) => {
// See https://github.com/ethereumjs/ethereumjs-tx/blob/master/docs/classes/transaction.md#constructor
// for initialization fields and their types
if (!value) value = 0
if (typeof value === 'string') {
if (value.startsWith('0x')) value = new BN(value.replace('0x', ''), 'hex')
else {
try {
value = new BN(value, 10)
} catch (e) {
return callback('Unable to parse the value ' + e.message)
}
}
}
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
if (!EIP1559) {
tx = Transaction.fromTxData({
nonce: useCall ? this.nextNonceForCall : new BN(res.nonce),
nonce: useCall ? this.nextNonceForCall : res.nonce,
gasPrice: '0x1',
gasLimit: gasLimit,
to: to,
@ -97,7 +91,7 @@ export class TxRunnerVM {
}, { common: this.commonContext }).sign(account.privateKey)
} else {
tx = FeeMarketEIP1559Transaction.fromTxData({
nonce: useCall ? this.nextNonceForCall : new BN(res.nonce),
nonce: useCall ? this.nextNonceForCall : res.nonce,
maxPriorityFeePerGas: '0x01',
maxFeePerGas: '0x1',
gasLimit: gasLimit,
@ -109,15 +103,15 @@ export class TxRunnerVM {
if (useCall) this.nextNonceForCall++
const coinbases = ['0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a', '0x8945a1288dc78a6d8952a92c77aee6730b414778', '0x94d76e24f818426ae84aa404140e8d5f60e10e7e']
const difficulties = [new BN('69762765929000', 10), new BN('70762765929000', 10), new BN('71762765929000', 10)]
const difficulties = [69762765929000, 70762765929000, 71762765929000]
const block = Block.fromBlockData({
header: {
timestamp: timestamp || (new Date().getTime() / 1000 | 0),
timestamp: new Date().getTime() / 1000 | 0,
number: self.blockNumber,
coinbase: coinbases[self.blockNumber % coinbases.length],
difficulty: difficulties[self.blockNumber % difficulties.length],
gasLimit: new BN(gasLimit.replace('0x', ''), 16).imuln(2),
gasLimit,
baseFeePerGas: EIP1559 ? '0x1' : undefined
},
transactions: [tx]
@ -141,14 +135,10 @@ export class TxRunnerVM {
}
runBlockInVm (tx, block, callback) {
this.getVMObject().vm.runBlock({ block: block, generate: true, skipBlockValidation: true, skipBalance: false, skipNonce: true }).then((results) => {
const result = results.results[0]
if (result) {
const status = result.execResult.exceptionError ? 0 : 1
result.status = `0x${status}`
}
this.getVMObject().vm.runBlock({ block: block, generate: true, skipBlockValidation: true, skipBalance: false, skipNonce: true }).then((results: RunBlockResult) => {
const result: RunTxResult = results.results[0]
callback(null, {
result: result,
result,
transactionHash: bufferToHex(Buffer.from(tx.hash())),
block,
tx

@ -47,6 +47,8 @@ export class TxRunnerWeb3 {
}
_sendTransaction (sendTx, tx, pass, callback) {
let currentDateTime = new Date();
const start = currentDateTime.getTime() / 1000
const cb = (err, resp) => {
if (err) {
return callback(err, resp)
@ -57,6 +59,9 @@ export class TxRunnerWeb3 {
return new Promise(async (resolve, reject) => {
const receipt = await tryTillReceiptAvailable(resp, this.getWeb3())
tx = await tryTillTxAvailable(resp, this.getWeb3())
currentDateTime = new Date();
const end = currentDateTime.getTime() / 1000
console.log('stopwatch', end - start)
resolve({
receipt,
tx,

@ -18,6 +18,7 @@ import * as txResultHelper from './helpers/txResultHelper'
export { ConsoleLogs } from './helpers/hhconsoleSigs'
export { ICompilerApi, ConfigurationSettings } from './types/ICompilerApi'
export { QueryParams } from './query-params'
export { VMexecutionResult } from './execution/txRunnerVM'
const helpers = {
ui: uiHelper,

@ -17,10 +17,10 @@
"test": "./../../node_modules/.bin/ts-node --project ../../tsconfig.base.json --require tsconfig-paths/register ./../../node_modules/.bin/mocha test/*.ts"
},
"dependencies": {
"@ethereumjs/block": "^3.5.1",
"@ethereumjs/common": "^2.5.0",
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"@ethereumjs/block": "^4.0.0",
"@ethereumjs/common": "^3.0.0",
"@ethereumjs/tx": "^4.0.0",
"@ethereumjs/vm": "^6.0.0",
"@remix-project/remix-lib": "^0.5.21",
"ansi-gray": "^0.1.1",
"async": "^3.1.0",

@ -4,14 +4,17 @@ import { helpers } from '@remix-project/remix-lib'
const { normalizeHexAddress } = helpers.ui
import { ConsoleLogs } from '@remix-project/remix-lib'
import { toChecksumAddress, BN, keccak, bufferToHex, Address, toBuffer } from 'ethereumjs-util'
import Web3 from 'web3'
import utils from 'web3-utils'
import { ethers } from 'ethers'
import { VMContext } from './vm-context'
import type { StateManager } from '@ethereumjs/statemanager'
import type { InterpreterStep } from '@ethereumjs/evm/dist/interpreter'
import type { AfterTxEvent, VM } from '@ethereumjs/vm'
import type { TypedTransaction } from '@ethereumjs/tx'
export class VmProxy {
vmContext: VMContext
web3: Web3
vm
vm: VM
vmTraces
txs
txsReceipt
@ -26,7 +29,6 @@ export class VmProxy {
providers
currentProvider
storageCache
lastProcessedStorageTxHash
sha3Preimages
sha3
toHex
@ -40,10 +42,11 @@ export class VmProxy {
utils
txsMapBlock
blocks
stateCopy: StateManager
constructor (vmContext: VMContext) {
this.vmContext = vmContext
this.web3 = new Web3()
this.stateCopy
this.vm = null
this.vmTraces = {}
this.txs = {}
@ -68,19 +71,18 @@ export class VmProxy {
this.providers = { HttpProvider: function (url) {} }
this.currentProvider = { host: 'vm provider' }
this.storageCache = {}
this.lastProcessedStorageTxHash = {}
this.sha3Preimages = {}
// util
this.sha3 = (...args) => this.web3.utils.sha3.apply(this, args)
this.toHex = (...args) => this.web3.utils.toHex.apply(this, args)
this.toAscii = (...args) => this.web3.utils.toAscii.apply(this, args)
this.fromAscii = (...args) => this.web3.utils.fromAscii.apply(this, args)
this.fromDecimal = (...args) => this.web3.utils.fromDecimal.apply(this, args)
this.fromWei = (...args) => this.web3.utils.fromWei.apply(this, args)
this.toWei = (...args) => this.web3.utils.toWei.apply(this, args)
this.toBigNumber = (...args) => this.web3.utils.toBN.apply(this, args)
this.isAddress = (...args) => this.web3.utils.isAddress.apply(this, args)
this.utils = Web3.utils || []
this.sha3 = (...args) => utils.sha3.apply(this, args)
this.toHex = (...args) => utils.toHex.apply(this, args)
this.toAscii = (...args) => utils.toAscii.apply(this, args)
this.fromAscii = (...args) => utils.fromAscii.apply(this, args)
this.fromDecimal = (...args) => utils.fromDecimal.apply(this, args)
this.fromWei = (...args) => utils.fromWei.apply(this, args)
this.toWei = (...args) => utils.toWei.apply(this, args)
this.toBigNumber = (...args) => utils.toBN.apply(this, args)
this.isAddress = (...args) => utils.isAddress.apply(this, args)
this.utils = utils
this.txsMapBlock = {}
this.blocks = {}
}
@ -88,17 +90,16 @@ export class VmProxy {
setVM (vm) {
if (this.vm === vm) return
this.vm = vm
this.vm.on('step', async (data, next) => {
this.vm.evm.events.on('step', async (data: InterpreterStep) => {
await this.pushTrace(data)
next()
})
this.vm.on('afterTx', async (data, next) => {
this.vm.events.on('afterTx', async (data: AfterTxEvent, resolve: (result?: any) => void) => {
await this.txProcessed(data)
next()
resolve()
})
this.vm.on('beforeTx', async (data, next) => {
this.vm.events.on('beforeTx', async (data: TypedTransaction, resolve: (result?: any) => void) => {
await this.txWillProcess(data)
next()
resolve()
})
}
@ -108,7 +109,8 @@ export class VmProxy {
return ret
}
async txWillProcess (data) {
async txWillProcess (data: TypedTransaction) {
this.stateCopy = await this.vm.stateManager.copy()
this.incr++
this.processingHash = bufferToHex(data.hash())
this.vmTraces[this.processingHash] = {
@ -133,23 +135,24 @@ export class VmProxy {
this.storageCache[this.processingHash] = {}
this.storageCache['after_' + this.processingHash] = {}
if (data.to) {
try {
const storage = await this.vm.stateManager.dumpStorage(data.to)
this.storageCache[this.processingHash][tx['to']] = storage
this.lastProcessedStorageTxHash[tx['to']] = this.processingHash
} catch (e) {
console.log(e)
}
(async (processingHash, processingAccount, processingAddress, self) => {
try {
const storage = await self.stateCopy.dumpStorage(processingAccount)
self.storageCache[processingHash][processingAddress] = storage
} catch (e) {
console.log(e)
}
})(this.processingHash, data.to, tx['to'], this)
}
this.processingIndex = 0
}
async txProcessed (data) {
async txProcessed (data: AfterTxEvent) {
const lastOp = this.vmTraces[this.processingHash].structLogs[this.processingIndex - 1]
if (lastOp) {
lastOp.error = lastOp.op !== 'RETURN' && lastOp.op !== 'STOP' && lastOp.op !== 'DESTRUCT'
}
const gasUsed = '0x' + data.gasUsed.toString(16)
const gasUsed = '0x' + data.totalGasSpent.toString(16)
this.vmTraces[this.processingHash].gas = gasUsed
this.txsReceipt[this.processingHash].gasUsed = gasUsed
const logs = []
@ -191,95 +194,102 @@ export class VmProxy {
this.vmTraces[this.processingHash].return = toChecksumAddress(address)
this.txsReceipt[this.processingHash].contractAddress = toChecksumAddress(address)
} else if (data.execResult.returnValue) {
this.vmTraces[this.processingHash].return = bufferToHex(data.execResult.returnValue)
this.vmTraces[this.processingHash].return = '0x' + data.execResult.returnValue.toString('hex')
} else {
this.vmTraces[this.processingHash].return = '0x'
}
this.processingIndex = null
this.processingAddress = null
this.previousDepth = 0
this.stateCopy = null
}
async pushTrace (data) {
const depth = data.depth + 1 // geth starts the depth from 1
if (!this.processingHash) {
console.log('no tx processing')
return
}
let previousopcode
if (this.vmTraces[this.processingHash] && this.vmTraces[this.processingHash].structLogs[this.processingIndex - 1]) {
previousopcode = this.vmTraces[this.processingHash].structLogs[this.processingIndex - 1]
}
if (this.previousDepth > depth && previousopcode) {
// returning from context, set error it is not STOP, RETURN
previousopcode.invalidDepthChange = previousopcode.op !== 'RETURN' && previousopcode.op !== 'STOP'
}
const step = {
stack: hexListFromBNs(data.stack),
memory: formatMemory(data.memory),
storage: data.storage,
op: data.opcode.name,
pc: data.pc,
gasCost: data.opcode.fee.toString(),
gas: data.gasLeft.toString(),
depth: depth,
error: data.error === false ? undefined : data.error
}
this.vmTraces[this.processingHash].structLogs.push(step)
// Track hardhat console.log call
if (step.op === 'STATICCALL' && step.stack[step.stack.length - 2] === '0x000000000000000000000000000000000000000000636f6e736f6c652e6c6f67') {
const stackLength = step.stack.length
const payloadStart = parseInt(step.stack[stackLength - 3], 16)
const memory = step.memory.join('')
let payload = memory.substring(payloadStart * 2, memory.length)
const fnselectorStr = payload.substring(0, 8)
const fnselectorStrInHex = '0x' + fnselectorStr
const fnselector = parseInt(fnselectorStrInHex)
const fnArgs = ConsoleLogs[fnselector]
const iface = new ethers.utils.Interface([`function log${fnArgs} view`])
const functionDesc = iface.getFunction(`log${fnArgs}`)
const sigHash = iface.getSighash(`log${fnArgs}`)
if (fnArgs.includes('uint') && sigHash !== fnselectorStrInHex) {
payload = payload.replace(fnselectorStr, sigHash)
} else {
payload = '0x' + payload
async pushTrace (data: InterpreterStep) {
try {
const depth = data.depth + 1 // geth starts the depth from 1
if (!this.processingHash) {
return
}
let previousOpcode
if (this.vmTraces[this.processingHash] && this.vmTraces[this.processingHash].structLogs[this.processingIndex - 1]) {
previousOpcode = this.vmTraces[this.processingHash].structLogs[this.processingIndex - 1]
}
if (this.previousDepth > depth && previousOpcode) {
// returning from context, set error it is not STOP, RETURN
previousOpcode.invalidDepthChange = previousOpcode.op !== 'RETURN' && previousOpcode.op !== 'STOP'
}
const step = {
stack: hexListFromBNs(data.stack),
memory: formatMemory(data.memory),
storage: {},
op: data.opcode.name,
pc: data.pc,
gasCost: data.opcode.fee.toString(),
gas: data.gasLeft.toString(),
depth: depth
}
this.vmTraces[this.processingHash].structLogs.push(step)
// Track hardhat console.log call
if (step.op === 'STATICCALL' && step.stack[step.stack.length - 2] === '0x000000000000000000000000000000000000000000636f6e736f6c652e6c6f67') {
const stackLength = step.stack.length
const payloadStart = parseInt(step.stack[stackLength - 3], 16)
const memory = step.memory.join('')
let payload = memory.substring(payloadStart * 2, memory.length)
const fnselectorStr = payload.substring(0, 8)
const fnselectorStrInHex = '0x' + fnselectorStr
const fnselector = parseInt(fnselectorStrInHex)
const fnArgs = ConsoleLogs[fnselector]
const iface = new ethers.utils.Interface([`function log${fnArgs} view`])
const functionDesc = iface.getFunction(`log${fnArgs}`)
const sigHash = iface.getSighash(`log${fnArgs}`)
if (fnArgs.includes('uint') && sigHash !== fnselectorStrInHex) {
payload = payload.replace(fnselectorStr, sigHash)
} else {
payload = '0x' + payload
}
let consoleArgs = iface.decodeFunctionData(functionDesc, payload)
consoleArgs = consoleArgs.map((value) => {
if (utils.isBigNumber(value)) {
return value.toString()
}
return value
})
this.hhLogs[this.processingHash] = this.hhLogs[this.processingHash] ? this.hhLogs[this.processingHash] : []
this.hhLogs[this.processingHash].push(consoleArgs)
}
const consoleArgs = iface.decodeFunctionData(functionDesc, payload)
this.hhLogs[this.processingHash] = this.hhLogs[this.processingHash] ? this.hhLogs[this.processingHash] : []
this.hhLogs[this.processingHash].push(consoleArgs)
}
if (step.op === 'CREATE' || step.op === 'CALL') {
if (step.op === 'CREATE') {
this.processingAddress = '(Contract Creation - Step ' + this.processingIndex + ')'
this.storageCache[this.processingHash][this.processingAddress] = {}
this.lastProcessedStorageTxHash[this.processingAddress] = this.processingHash
} else {
this.processingAddress = normalizeHexAddress(step.stack[step.stack.length - 2])
this.processingAddress = toChecksumAddress(this.processingAddress)
if (!this.storageCache[this.processingHash][this.processingAddress]) {
const account = Address.fromString(this.processingAddress)
try {
const storage = await this.vm.stateManager.dumpStorage(account)
this.storageCache[this.processingHash][this.processingAddress] = storage
this.lastProcessedStorageTxHash[this.processingAddress] = this.processingHash
} catch (e) {
console.log(e)
if (step.op === 'CREATE' || step.op === 'CALL') {
if (step.op === 'CREATE') {
this.processingAddress = '(Contract Creation - Step ' + this.processingIndex + ')'
this.storageCache[this.processingHash][this.processingAddress] = {}
} else {
this.processingAddress = normalizeHexAddress(step.stack[step.stack.length - 2])
this.processingAddress = toChecksumAddress(this.processingAddress)
if (!this.storageCache[this.processingHash][this.processingAddress]) {
(async (processingHash, processingAddress, self) => {
try {
const account = Address.fromString(processingAddress)
const storage = await self.stateCopy.dumpStorage(account)
self.storageCache[processingHash][processingAddress] = storage
} catch (e) {
console.log(e)
}
})(this.processingHash, this.processingAddress, this)
}
}
}
}
if (previousopcode && previousopcode.op === 'SHA3') {
const preimage = this.getSha3Input(previousopcode.stack, previousopcode.memory)
const imageHash = step.stack[step.stack.length - 1].replace('0x', '')
this.sha3Preimages[imageHash] = {
preimage: preimage
if (previousOpcode && previousOpcode.op === 'SHA3') {
const preimage = this.getSha3Input(previousOpcode.stack, previousOpcode.memory)
const imageHash = step.stack[step.stack.length - 1].replace('0x', '')
this.sha3Preimages[imageHash] = {
preimage: preimage
}
}
this.processingIndex++
this.previousDepth = depth
} catch (e) {
console.log(e)
}
this.processingIndex++
this.previousDepth = depth
}
getCode (address, cb) {
@ -321,7 +331,7 @@ export class VmProxy {
}
// Before https://github.com/ethereum/remix-project/pull/1703, it used to throw error as
// 'unable to retrieve storage ' + txIndex + ' ' + address
cb(null, { storage: {} })
cb(null, '0x0')
}
storageRangeAt (blockNumber, txIndex, address, start, maxLength, cb) {

@ -1,5 +1,4 @@
import { Block } from '@ethereumjs/block'
import { BN } from 'ethereumjs-util'
export function generateBlock (vmContext) {
return new Promise((resolve, reject) => {
@ -8,8 +7,8 @@ export function generateBlock (vmContext) {
timestamp: (new Date().getTime() / 1000 | 0),
number: 0,
coinbase: '0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a',
difficulty: new BN('69762765929000', 10),
gasLimit: new BN('8000000').imuln(1)
difficulty: 69762765929000,
gasLimit: 8000000
}
}, { common: vmContext.vmObject().common })

@ -1,18 +1,18 @@
import { BN, privateToAddress, toChecksumAddress, isValidPrivate, Address } from 'ethereumjs-util'
import Web3 from 'web3'
const Web3EthAccounts = require('web3-eth-accounts')
import * as crypto from 'crypto'
export class Accounts {
web3
export class Web3Accounts {
accounts: Record<string, unknown>
accountsKeys: Record<string, unknown>
web3Accounts: any
vmContext
constructor (vmContext) {
this.web3 = new Web3()
this.vmContext = vmContext
// TODO: make it random and/or use remix-libs
this.web3Accounts = new Web3EthAccounts()
this.accounts = {}
this.accountsKeys = {}
}
@ -98,7 +98,7 @@ export class Accounts {
if (!privateKey) {
return cb(new Error('unknown account'))
}
const account = this.web3.eth.accounts.privateKeyToAccount(privateKey)
const account = this.web3Accounts.privateKeyToAccount(privateKey as string)
const data = account.sign(message)

@ -1,5 +1,7 @@
import Web3 from 'web3'
import { toHex } from 'web3-utils'
import { VMContext } from '../vm-context'
import { bigIntToHex } from '@ethereumjs/util'
export class Blocks {
vmContext: VMContext
coinbase: string
@ -47,23 +49,23 @@ export class Blocks {
if (receipt) {
return {
blockHash: '0x' + block.hash().toString('hex'),
blockNumber: '0x' + block.header.number.toString('hex'),
blockNumber: bigIntToHex(block.header.number),
from: receipt.from,
gas: Web3.utils.toHex(receipt.gas),
gas: bigIntToHex(receipt.gas),
chainId: '0xd05',
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: '0x' + tx.nonce.toString('hex'),
nonce: bigIntToHex(tx.nonce),
transactionIndex: this.TX_INDEX,
value: receipt.value === '0x' ? '0x0' : receipt.value,
value: bigIntToHex(tx.value),
to: receipt.to ? receipt.to : null
}
}
})
const b = {
baseFeePerGas: '0x01',
number: this.toHex(block.header.number),
number: bigIntToHex(block.header.number),
hash: this.toHex(block.hash()),
parentHash: this.toHex(block.header.parentHash),
nonce: this.toHex(block.header.nonce),
@ -72,13 +74,13 @@ export class Blocks {
transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
stateRoot: this.toHex(block.header.stateRoot),
miner: this.coinbase,
difficulty: this.toHex(block.header.difficulty),
totalDifficulty: this.toHex((block.header as any).totalDifficulty),
difficulty: bigIntToHex(block.header.difficulty),
totalDifficulty: bigIntToHex((block.header as any).totalDifficulty || 0),
extraData: this.toHex(block.header.extraData),
size: '0x027f07', // 163591
gasLimit: this.toHex(block.header.gasLimit),
gasUsed: this.toHex(block.header.gasUsed),
timestamp: this.toHex(block.header.timestamp),
gasLimit: bigIntToHex(block.header.gasLimit),
gasUsed: bigIntToHex(block.header.gasUsed),
timestamp: bigIntToHex(block.header.timestamp),
transactions,
uncles: []
}
@ -101,23 +103,23 @@ export class Blocks {
if (receipt) {
return {
blockHash: '0x' + block.hash().toString('hex'),
blockNumber: '0x' + block.header.number.toString('hex'),
blockNumber: bigIntToHex(block.header.number),
from: receipt.from,
gas: Web3.utils.toHex(receipt.gas),
gas: toHex(receipt.gas),
chainId: '0xd05',
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: '0x' + tx.nonce.toString('hex'),
nonce: bigIntToHex(tx.nonce),
transactionIndex: this.TX_INDEX,
value: receipt.value === '0x' ? '0x0' : receipt.value,
value: bigIntToHex(tx.value),
to: receipt.to ? receipt.to : null
}
}
})
const b = {
baseFeePerGas: '0x01',
number: this.toHex(block.header.number),
number: bigIntToHex(block.header.number),
hash: this.toHex(block.hash()),
parentHash: this.toHex(block.header.parentHash),
nonce: this.toHex(block.header.nonce),
@ -126,13 +128,13 @@ export class Blocks {
transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
stateRoot: this.toHex(block.header.stateRoot),
miner: this.coinbase,
difficulty: this.toHex(block.header.difficulty),
totalDifficulty: this.toHex((block.header as any).totalDifficulty),
difficulty: bigIntToHex(block.header.difficulty),
totalDifficulty: bigIntToHex((block.header as any).totalDifficulty || 0),
extraData: this.toHex(block.header.extraData),
size: '0x027f07', // 163591
gasLimit: this.toHex(block.header.gasLimit),
gasUsed: this.toHex(block.header.gasUsed),
timestamp: this.toHex(block.header.timestamp),
gasLimit: bigIntToHex(block.header.gasLimit),
gasUsed: bigIntToHex(block.header.gasUsed),
timestamp: bigIntToHex(block.header.timestamp),
transactions,
uncles: []
}

@ -1,4 +1,4 @@
import Web3 from 'web3'
import { sha3 } from 'web3-utils'
const version = require('../../package.json').version
export function methods () {
@ -39,7 +39,7 @@ export function eth_hashrate (payload, cb) {
export function web3_sha3 (payload, cb) {
const str: string = payload.params[0]
cb(null, Web3.utils.sha3(str))
cb(null, sha3(str))
}
export function eth_getCompilers (payload, cb) {

@ -1,11 +1,24 @@
import Web3 from 'web3'
import { toHex, toDecimal } from 'web3-utils'
import { bigIntToHex } from '@ethereumjs/util'
import { toChecksumAddress, BN, Address } from 'ethereumjs-util'
import { processTx } from './txProcess'
import { execution } from '@remix-project/remix-lib'
import { ethers } from 'ethers'
import { VMexecutionResult } from '@remix-project/remix-lib'
import { RunTxResult } from '@ethereumjs/vm'
import { Log, EvmError } from '@ethereumjs/evm'
const TxRunnerVM = execution.TxRunnerVM
const TxRunner = execution.TxRunner
export type VMExecResult = {
exceptionError: EvmError
executionGasUsed: bigint
gas: bigint
gasRefund: bigint
logs: Log[]
returnValue: string
}
export class Transactions {
vmContext
accounts
@ -69,12 +82,21 @@ export class Transactions {
if (payload.params && payload.params.length > 0 && payload.params[0].from) {
payload.params[0].from = toChecksumAddress(payload.params[0].from)
}
processTx(this.txRunnerInstance, payload, false, (error, result) => {
processTx(this.txRunnerInstance, payload, false, (error, result: VMexecutionResult) => {
if (!error && result) {
this.vmContext.addBlock(result.block)
const hash = '0x' + result.tx.hash().toString('hex')
this.vmContext.trackTx(hash, result.block, result.tx)
this.vmContext.trackExecResult(hash, result.result.execResult)
const returnValue = `0x${result.result.execResult.returnValue.toString('hex') || '0'}`
const execResult: VMExecResult = {
exceptionError: result.result.execResult.exceptionError,
executionGasUsed: result.result.execResult.executionGasUsed,
gas: result.result.execResult.gas,
gasRefund: result.result.execResult.gasRefund,
logs: result.result.execResult.logs,
returnValue
}
this.vmContext.trackExecResult(hash, execResult)
return cb(null, result.transactionHash)
}
cb(error)
@ -105,7 +127,7 @@ export class Transactions {
transactionHash: receipt.hash,
transactionIndex: this.TX_INDEX,
blockHash: '0x' + txBlock.hash().toString('hex'),
blockNumber: '0x' + txBlock.header.number.toString('hex'),
blockNumber: bigIntToHex(txBlock.header.number),
gasUsed: receipt.gasUsed,
cumulativeGasUsed: receipt.gasUsed, // only 1 tx per block
contractAddress: receipt.contractAddress,
@ -133,23 +155,25 @@ export class Transactions {
payload.params[0].gas = 10000000 * 10
processTx(this.txRunnerInstance, payload, true, (error, { result }) => {
processTx(this.txRunnerInstance, payload, true, (error, value: VMexecutionResult) => {
const result: RunTxResult = value.result
if (error) return cb(error)
if (result.status === '0x0') {
if ((result as any).receipt?.status === '0x0' || (result as any).receipt?.status === 0) {
try {
const msg = result.execResult.returnValue
const msg = `0x${result.execResult.returnValue.toString('hex') || '0'}`
const abiCoder = new ethers.utils.AbiCoder()
const reason = abiCoder.decode(['string'], msg.slice(4))[0]
const reason = abiCoder.decode(['string'], '0x' + msg.slice(10))[0]
return cb('revert ' + reason)
} catch (e) {
return cb(e.message)
}
}
let gasUsed = result.execResult.gasUsed.toNumber()
let gasUsed = result.execResult.executionGasUsed
if (result.execResult.gasRefund) {
gasUsed += result.execResult.gasRefund.toNumber()
gasUsed += result.execResult.gasRefund
}
cb(null, Math.ceil(gasUsed + (15 * gasUsed) / 100))
gasUsed = gasUsed + value.tx.getBaseFee()
cb(null, Math.ceil(Number(gasUsed) + (15 * Number(gasUsed)) / 100))
})
}
@ -178,15 +202,23 @@ export class Transactions {
const tag = payload.params[0].timestamp // e2e reference
processTx(this.txRunnerInstance, payload, true, (error, result) => {
processTx(this.txRunnerInstance, payload, true, (error, result: VMexecutionResult) => {
if (!error && result) {
this.vmContext.addBlock(result.block)
const hash = '0x' + result.tx.hash().toString('hex')
this.vmContext.trackTx(hash, result.block, result.tx)
this.vmContext.trackExecResult(hash, result.result.execResult)
const returnValue = `0x${result.result.execResult.returnValue.toString('hex') || '0'}`
const execResult: VMExecResult = {
exceptionError: result.result.execResult.exceptionError,
executionGasUsed: result.result.execResult.executionGasUsed,
gas: result.result.execResult.gas,
gasRefund: result.result.execResult.gasRefund,
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.
const returnValue = `0x${result.result.execResult.returnValue.toString('hex') || '0'}`
return cb(null, returnValue)
}
cb(error)
@ -222,17 +254,17 @@ export class Transactions {
// TODO: params to add later
const r: Record<string, unknown> = {
blockHash: '0x' + txBlock.hash().toString('hex'),
blockNumber: '0x' + txBlock.header.number.toString('hex'),
blockNumber: bigIntToHex(txBlock.header.number),
from: receipt.from,
gas: Web3.utils.toHex(receipt.gas),
gas: toHex(receipt.gas),
chainId: '0xd05',
// 'gasPrice': '2000000000000', // 0x123
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: '0x' + tx.nonce.toString('hex'),
nonce: bigIntToHex(tx.nonce),
transactionIndex: this.TX_INDEX,
value: receipt.value
value: bigIntToHex(tx.value)
// "value":"0xf3dbb76162000" // 4290000000000000
// "v": "0x25", // 37
// "r": "0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea",
@ -259,7 +291,7 @@ export class Transactions {
const txIndex = payload.params[1]
const txBlock = this.vmContext.blocks[payload.params[0]]
const txHash = '0x' + txBlock.transactions[Web3.utils.toDecimal(txIndex)].hash().toString('hex')
const txHash = '0x' + txBlock.transactions[toDecimal(txIndex)].hash().toString('hex')
this.vmContext.web3().eth.getTransactionReceipt(txHash, (error, receipt) => {
if (error) {
@ -271,15 +303,15 @@ export class Transactions {
// TODO: params to add later
const r: Record<string, unknown> = {
blockHash: '0x' + txBlock.hash().toString('hex'),
blockNumber: '0x' + txBlock.header.number.toString('hex'),
blockNumber: bigIntToHex(txBlock.header.number),
from: receipt.from,
gas: Web3.utils.toHex(receipt.gas),
gas: toHex(receipt.gas),
chainId: '0xd05',
// 'gasPrice': '2000000000000', // 0x123
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: '0x' + tx.nonce.toString('hex'),
nonce: bigIntToHex(tx.nonce),
transactionIndex: this.TX_INDEX,
value: receipt.value
// "value":"0xf3dbb76162000" // 4290000000000000
@ -304,7 +336,7 @@ export class Transactions {
const txIndex = payload.params[1]
const txBlock = this.vmContext.blocks[payload.params[0]]
const txHash = '0x' + txBlock.transactions[Web3.utils.toDecimal(txIndex)].hash().toString('hex')
const txHash = '0x' + txBlock.transactions[toDecimal(txIndex)].hash().toString('hex')
this.vmContext.web3().eth.getTransactionReceipt(txHash, (error, receipt) => {
if (error) {
@ -316,15 +348,15 @@ export class Transactions {
// TODO: params to add later
const r: Record<string, unknown> = {
blockHash: '0x' + txBlock.hash().toString('hex'),
blockNumber: '0x' + txBlock.header.number.toString('hex'),
blockNumber: bigIntToHex(txBlock.header.number),
from: receipt.from,
gas: Web3.utils.toHex(receipt.gas),
gas: toHex(receipt.gas),
// 'gasPrice': '2000000000000', // 0x123
chainId: '0xd05',
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,
nonce: '0x' + tx.nonce.toString('hex'),
nonce: bigIntToHex(tx.nonce),
transactionIndex: this.TX_INDEX,
value: receipt.value
// "value":"0xf3dbb76162000" // 4290000000000000

@ -3,7 +3,7 @@ import { Blocks } from './methods/blocks'
import { info } from './utils/logs'
import merge from 'merge'
import { Accounts } from './methods/accounts'
import { Web3Accounts } from './methods/accounts'
import { Filters } from './methods/filters'
import { methods as miscMethods } from './methods/misc'
import { methods as netMethods } from './methods/net'
@ -25,7 +25,7 @@ export class Provider {
this.connected = true
this.vmContext = new VMContext(options['fork'])
this.Accounts = new Accounts(this.vmContext)
this.Accounts = new Web3Accounts(this.vmContext)
this.Transactions = new Transactions(this.vmContext)
this.methods = {}
@ -39,6 +39,7 @@ export class Provider {
}
async init () {
await this.vmContext.init()
await generateBlock(this.vmContext)
await this.Accounts.resetAccounts()
this.Transactions.init(this.Accounts.accounts)

@ -1,25 +1,45 @@
/* global ethereum */
'use strict'
import Web3 from 'web3'
import { rlp, keccak, bufferToHex } from 'ethereumjs-util'
import { execution } from '@remix-project/remix-lib'
const { LogsManager } = execution
import { VmProxy } from './VmProxy'
import VM from '@ethereumjs/vm'
import Common from '@ethereumjs/common'
import StateManager from '@ethereumjs/vm/dist/state/stateManager'
import { StorageDump } from '@ethereumjs/vm/dist/state/interface'
import { VM } from '@ethereumjs/vm'
import { Common } from '@ethereumjs/common'
import { Trie } from '@ethereumjs/trie'
import { DefaultStateManager } from '@ethereumjs/statemanager'
import { StorageDump } from '@ethereumjs/statemanager/dist/interface'
import { EVM } from '@ethereumjs/evm'
import { EEI } from '@ethereumjs/vm'
import { Blockchain } from '@ethereumjs/blockchain'
import { Block } from '@ethereumjs/block'
import { Transaction } from '@ethereumjs/tx'
import { bigIntToHex } from '@ethereumjs/util'
/**
* Options for constructing a {@link StateManager}.
*/
export interface DefaultStateManagerOpts {
/**
* A {@link Trie} instance
*/
trie?: Trie
/**
* Option to prefix codehashes in the database. This defaults to `true`.
* If this is disabled, note that it is possible to corrupt the trie, by deploying code
* which code is equal to the preimage of a trie-node.
* E.g. by putting the code `0x80` into the empty trie, will lead to a corrupted trie.
*/
prefixCodeHashes?: boolean
}
/*
extend vm state manager and instanciate VM
*/
class StateManagerCommonStorageDump extends StateManager {
class StateManagerCommonStorageDump extends DefaultStateManager {
keyHashes: { [key: string]: string }
constructor () {
super()
constructor (opts: DefaultStateManagerOpts = {}) {
super(opts)
this.keyHashes = {}
}
@ -28,6 +48,14 @@ class StateManagerCommonStorageDump extends StateManager {
return super.putContractStorage(address, key, value)
}
copy(): StateManagerCommonStorageDump {
const copyState = new StateManagerCommonStorageDump({
trie: this._trie.copy(false),
})
copyState.keyHashes = this.keyHashes
return copyState
}
async dumpStorage (address): Promise<StorageDump> {
return new Promise((resolve, reject) => {
this._getStorageTrie(address)
@ -52,18 +80,7 @@ class StateManagerCommonStorageDump extends StateManager {
})
}
async getStateRoot (force = false) {
await this._cache.flush()
const stateRoot = this._trie.root
return stateRoot
}
async setStateRoot (stateRoot) {
if (this._checkpointCount !== 0) {
throw new Error('Cannot set state root with uncommitted checkpoints')
}
await this._cache.flush()
if (!stateRoot.equals(this._trie.EMPTY_TRIE_ROOT)) {
@ -106,7 +123,7 @@ export class VMContext {
this.blockGasLimitDefault = 4300000
this.blockGasLimit = this.blockGasLimitDefault
this.currentFork = fork || 'london'
this.currentVm = this.createVm(this.currentFork)
this.blocks = {}
this.latestBlockNumber = "0x0"
this.blockByTxHash = {}
@ -115,14 +132,23 @@ export class VMContext {
this.logsManager = new LogsManager()
}
createVm (hardfork) {
async init () {
this.currentVm = await this.createVm(this.currentFork)
}
async createVm (hardfork) {
const stateManager = new StateManagerCommonStorageDump()
const common = new Common({ chain: 'mainnet', hardfork })
const vm = new VM({
const blockchain = new (Blockchain as any)({ common })
const eei = new EEI(stateManager, common, blockchain)
const evm = new EVM({ common, eei, allowUnlimitedContractSize: true })
const vm = await VM.create({
common,
activatePrecompiles: true,
stateManager,
allowUnlimitedContractSize: true
blockchain,
evm
})
// VmProxy and VMContext are very intricated.
@ -140,10 +166,6 @@ export class VMContext {
return this.currentVm.web3vm
}
blankWeb3 () {
return new Web3()
}
vm () {
return this.currentVm.vm
}
@ -153,7 +175,7 @@ export class VMContext {
}
addBlock (block: Block) {
let blockNumber = '0x' + block.header.number.toString('hex')
let blockNumber = bigIntToHex(block.header.number)
if (blockNumber === '0x') {
blockNumber = '0x0'
}

@ -18,7 +18,7 @@ describe('blocks', () => {
const block = await web3.eth.getBlock(0)
const expectedBlock = {
baseFeePerGas: '0x01',
baseFeePerGas: 1,
difficulty: '69762765929000',
extraData: '0x0',
gasLimit: 8000000,

@ -15,9 +15,9 @@
}
],
"dependencies": {
"@ethereumjs/block": "^3.5.1",
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"@ethereumjs/block": "^4.0.0",
"@ethereumjs/tx": "^4.0.0",
"@ethereumjs/vm": "^6.0.0",
"@remix-project/remix-lib": "^0.5.21",
"async": "^2.6.2",
"eslint-scope": "^5.0.0",

@ -36,10 +36,10 @@
"homepage": "https://github.com/ethereum/remix-project/tree/master/libs/remix-tests#readme",
"dependencies": {
"@erebos/bzz-node": "^0.13.0",
"@ethereumjs/block": "^3.5.1",
"@ethereumjs/common": "^2.5.0",
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"@ethereumjs/block": "^4.0.0",
"@ethereumjs/common": "^3.0.0",
"@ethereumjs/tx": "^4.0.0",
"@ethereumjs/vm": "^6.0.0",
"@remix-project/remix-lib": "^0.5.21",
"@remix-project/remix-simulator": "^0.2.21",
"@remix-project/remix-solidity": "^0.5.7",

@ -25,16 +25,13 @@ export class UnitTestRunner {
async init (web3 = null, accounts = null) {
this.web3 = await this.createWeb3Provider(web3)
this.testsAccounts = accounts || await this.web3.eth.getAccounts()
this.testsAccounts = accounts || (this.web3 && await this.web3.eth.getAccounts()) || []
this.accountsLibCode = writeTestAccountsContract(this.testsAccounts)
}
async createWeb3Provider (optWeb3) {
const web3 = optWeb3 || new Web3()
const provider: any = new Provider()
await provider.init()
web3.setProvider(provider)
extend(web3)
const web3 = optWeb3
if (web3) extend(web3)
return web3
}

@ -159,18 +159,18 @@ describe('testRunner', function () {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertEqualTest', filename: __dirname + '/examples_0/assert_equal_test.sol' },
{ type: 'testPass', debugTxHash: '0xbe77baee10f8a044a68fbb83abf57ce1ca63b8739f3b2dcd122dab0ee44fd0e9', value: 'Equal uint pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0xfc9691b0cd0a49dbefed5cd3fad32158dd229e5bb7b0eb11da3c72054eafae8b', value: 'Equal uint fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalUintFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '273:57:0', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0xbc142789e5a51841781536a9291c9022896b0c7453140fdc98996638c0d76045', value: 'Equal int pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0xcc28211a4ab3149b1122fb47f45529a4edddbafa076d2338cc3754ab0629eaa1', value: 'Equal int fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalIntFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '493:45:0', expected: '2', returned: '-1' },
{ type: 'testPass', debugTxHash: '0x4f5570fc7da86f09aafb436ff3b4c46aa885f71680a233234433d0ef0346206b', value: 'Equal bool pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x28dc2d146dee77a2d6446efb088e5f9d008a3c7a14116e798401b68470da017f', value: 'Equal bool fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalBoolFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '708:52:0', expected: false, returned: true },
{ type: 'testPass', debugTxHash: '0x0abc8fa8831efa3a8c82c758d045c1382f71b6a7f7e9135ffbe9e40059f84617', value: 'Equal address pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x5ec200fb053539b8165a6b6ab36e9229a870c4752b0d6ff2786c4d5a66d5b35d', value: 'Equal address fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalAddressFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1015:130:0', expected: '0x1c6637567229159d1eFD45f95A6675e77727E013', returned: '0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9' },
{ type: 'testPass', debugTxHash: '0xb6c34f5baa6916569d122bcb1210fcd07fb126f4b859fea58db5328e5f1dab85', value: 'Equal bytes32 pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0xb3af74a384b8b6ddacbc03a480ae48e233415b1570717ca7023530023a871be6', value: 'Equal bytes32 fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalBytes32FailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1670:48:0', expected: '0x72656d6978000000000000000000000000000000000000000000000000000000', returned: '0x72656d6979000000000000000000000000000000000000000000000000000000' },
{ type: 'testPass', debugTxHash: '0x8537e74941b511b5c745b398e55435748adcdf637659247e0d573fb681ee4833', value: 'Equal string pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x30d44498e63ac51f1412062b849144c103e19a4dc9daf81c5e84bd984ef738a6', value: 'Equal string fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalStringFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1916:81:0', expected: 'remix-tests', returned: 'remix' }
{ type: 'testPass', debugTxHash: '0x233b8d91f0fa068b1a4deae1141178bc3eb79c3d2a6786160595a358363a157c', value: 'Equal uint pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0xa5e39c78663c2e5071c08467047ba5b2650d16081b50369700d46d7f90c4d94b', value: 'Equal uint fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalUintFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '273:57:0', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x57af51c2c19db390a4ccf72fa3d32347fb3d998e70820909c7876bd8ccebf8a3', value: 'Equal int pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x710f3a54a561c009fcf0277273b8fe337b2c493e9e83e0ae02786d487339ca7b', value: 'Equal int fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalIntFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '493:45:0', expected: '2', returned: '-1' },
{ type: 'testPass', debugTxHash: '0x10c1ed8651110ad5de6adcad8e1284aa5c1fd3a998a1e863bbecc0ec855fcd7b', value: 'Equal bool pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x004871a82968f43e02278eab9dd3d7eb0bbe88b64d459efa50065e5996fe5fad', value: 'Equal bool fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalBoolFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '708:52:0', expected: false, returned: true },
{ type: 'testPass', debugTxHash: '0x64a4d4853ab7907712912cf2120ac2bfd2e08b4767b375250f0e907757546454', value: 'Equal address pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0xcf62fb76e3b2eb95d92aa2671a9e81e30fefb944f55e2fb8b97096c45fc74a38', value: 'Equal address fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalAddressFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1015:130:0', expected: '0x1c6637567229159d1eFD45f95A6675e77727E013', returned: '0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9' },
{ type: 'testPass', debugTxHash: '0x18ef613acc128a21282e09cf920b32ef3be648bb35c0299471ddbbbeeb0faf8c', value: 'Equal bytes32 pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x86fbf2f14e13d228f80a87a947841270d8c55073adddf78e8d4e2ba05d724ec6', value: 'Equal bytes32 fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalBytes32FailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1670:48:0', expected: '0x72656d6978000000000000000000000000000000000000000000000000000000', returned: '0x72656d6979000000000000000000000000000000000000000000000000000000' },
{ type: 'testPass', debugTxHash: '0x80b3465f2504b74359790baa009237ba066685b24afa65a31814f1ad1bc4f99f', value: 'Equal string pass test', filename: __dirname + '/examples_0/assert_equal_test.sol', context: 'AssertEqualTest' },
{ type: 'testFailure', debugTxHash: '0x88b035a85c5f87f54a805334817f3e4599b4190d98f25947fe14d7804facd8b7', value: 'Equal string fail test', filename: __dirname + '/examples_0/assert_equal_test.sol', errMsg: 'equalStringFailTest fails', context: 'AssertEqualTest', assertMethod: 'equal', location: '1916:81:0', expected: 'remix-tests', returned: 'remix' }
], ['time', 'web3'])
})
})
@ -200,19 +200,19 @@ describe('testRunner', function () {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertNotEqualTest', filename: __dirname + '/examples_0/assert_notEqual_test.sol' },
{ type: 'testPass', debugTxHash: '0xb0ac5cde13a5005dc1b4efbb66fb3a5d6f0697467aedd6165ed1c8ee552939bc', value: 'Not equal uint pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x69d25ed9b9a010e97e0f7282313d4018c77a8873fd5f2e0b12483701febdd6b4', value: 'Not equal uint fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualUintFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '288:63:0', expected: '1', returned: '1' },
{ type: 'testPass', debugTxHash: '0x19a743cfb44b273c78b3271d603412d31087974309a70595bc5d15097a52c5c5', value: 'Not equal int pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x8dfce61b71a9ea65fb00c471370413779626f290b71d41f8be8408674e64f4d2', value: 'Not equal int fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualIntFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '525:52:0', expected: '-2', returned: '-2' },
{ type: 'testPass', debugTxHash: '0x12bc9eb3a653ebe4c7ab954c144dab4848295c88d71d17cb86a41e8a004419ba', value: 'Not equal bool pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x901b9cd631f8f29841243a257d1914060b9c36d88ee7d8b624de76dad4a34c85', value: 'Not equal bool fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualBoolFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '760:57:0', expected: true, returned: true },
{ type: 'testPass', debugTxHash: '0xf9e48bac26d3a2871ceb92974b897cae61e60bbc4db115b7e8eff4ac0390e4a5', value: 'Not equal address pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testPass', debugTxHash: '0xdef34ec7fbc6a3e6c6ef619b424bf8ebf16db16ed3f74500d56d8170d3aeca66', value: 'Not equal uint pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0xfcbd35bc5f460e22e885951d560171d687cf90ccdffc41fb5de1beb7075fe4e9', value: 'Not equal uint fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualUintFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '288:63:0', expected: '1', returned: '1' },
{ type: 'testPass', debugTxHash: '0x7f269855c3fc5c677eca416eb85665b8f10df00d3b7ec5dcc00cbf8e6364cba4', value: 'Not equal int pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x76555e218571d4ad69496d7d10ae46d30149c4bfd8c6e15ff2a58668ab6fba62', value: 'Not equal int fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualIntFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '525:52:0', expected: '-2', returned: '-2' },
{ type: 'testPass', debugTxHash: '0x5fe790b3f32b9580c1d5f9a2dbb0e10ddcb62846037d3f5800d47a51bb67cc91', value: 'Not equal bool pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x660d0a73395e6855aea8f6d3450e63640437dc15071842b417c39f40e1d7ae61', value: 'Not equal bool fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualBoolFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '760:57:0', expected: true, returned: true },
{ type: 'testPass', debugTxHash: '0x6fddce5573bd6723acf5a3e4137d698ff78f695873a228939276c4323ddfb132', value: 'Not equal address pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
{ type: 'testFailure', debugTxHash: '0x4e83a17426bc79b147ddd30a5434a2430a8302b3ce78b6979088ac5eceac5d3c', value: 'Not equal address fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualAddressFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '1084:136:0', expected: 0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9, returned: 0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9 },
{ type: 'testPass', debugTxHash: '0xfb4b30bb8373eeb6b09e38ad07880b86654f72780b41d7cf7554a112a04a0f53', value: 'Not equal bytes32 pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x43edf8bc68229415ee63f63f5303351a0dfecf9f3eb2ec35ffd2c10c60cf7005', value: 'Not equal bytes32 fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualBytes32FailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '1756:54:0', expected: '0x72656d6978000000000000000000000000000000000000000000000000000000', returned: '0x72656d6978000000000000000000000000000000000000000000000000000000' },
{ type: 'testPass', debugTxHash: '0x712932edc040596e2b02ddc06a48b773f5fccc7346d55cefc5d1c52528ce3168', value: 'Not equal string pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x961ce7425fdd4049aeb678ea20a0441eb837c1fe26b0d010593fc07d668321e6', value: 'Not equal string fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualStringFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '2026:81:0', expected: 'remix', returned: 'remix' },
{ type: 'testFailure', debugTxHash: '0x51479e46db802fb598c61ca0dd630345b9d70cc58667b5a80aa79e8119fa7787', value: 'Not equal address fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualAddressFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '1084:136:0', expected: 0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9, returned: 0x7994f14563F39875a2F934Ce42cAbF48a93FdDA9 },
{ type: 'testPass', debugTxHash: '0xbcaf6d8977b655fdedb280e0e9221d728706d41e85e0973d00c8da1d128022c7', value: 'Not equal bytes32 pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x34008ef0ea908fedbf80471424d801f5069e6e46221f8ee4a2ee16776a6eeef6', value: 'Not equal bytes32 fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualBytes32FailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '1756:54:0', expected: '0x72656d6978000000000000000000000000000000000000000000000000000000', returned: '0x72656d6978000000000000000000000000000000000000000000000000000000' },
{ type: 'testPass', debugTxHash: '0x8e0bc9dedea6e088ca7bd82b1e9fab516be5a52f7716a26ccca8197236aae105', value: 'Not equal string pass test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', context: 'AssertNotEqualTest' },
{ type: 'testFailure', debugTxHash: '0x13c6d270c3609ef858dd6d0c79433ca0b43e47b485b2e40ffe363f18f2868ea8', value: 'Not equal string fail test', filename: __dirname + '/examples_0/assert_notEqual_test.sol', errMsg: 'notEqualStringFailTest fails', context: 'AssertNotEqualTest', assertMethod: 'notEqual', location: '2026:81:0', expected: 'remix', returned: 'remix' },
], ['time', 'web3'])
})
})
@ -239,14 +239,14 @@ describe('testRunner', function () {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertGreaterThanTest', filename: __dirname + '/examples_0/assert_greaterThan_test.sol' },
{ type: 'testPass', debugTxHash: '0x81cf46560b522280ac60bd5c8efedad4598957d33435a898c23eefb13ca6104f', value: 'Greater than uint pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0x7090dc27ac06e1afd66963992bdd9188200d0404d43b95cfa5d925bbe6eba3ed', value: 'Greater than uint fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanUintFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '303:69:0', expected: '4', returned: '1' },
{ type: 'testPass', debugTxHash: '0xd57b40ed464763baf128f8a72efcd198e825e0b8f498cef90aed23045d0196db', value: 'Greater than int pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0x6c7b84bd8fc452b7839e11129d3818fa69dfd9b914e55556b39fdc68b70fc1b5', value: 'Greater than int fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanIntFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '569:67:0', expected: '1', returned: '-1' },
{ type: 'testPass', debugTxHash: '0xc5883db70b83a1d3afff24a9f0555de3edd7776e5ec157cc2110e426e5be2594', value: 'Greater than uint int pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0xa534085a6bbdcf73a68bdef6a1421218c11ac0ec1af398f9445defeea31cea6e', value: 'Greater than uint int fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanUintIntFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '845:71:0', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x36a7139445d76f6072fab4cc0717461068276748622c0dfc3f092d548b197de8', value: 'Greater than int uint pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0x7890f7b8f2eabae581b6f70d55d2d3bfa64ddd7753d5f892dbdf86ced96945fe', value: 'Greater than int uint fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanIntUintFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '1125:76:0', expected: '115792089237316195423570985008687907853269984665640564039457584007913129639836', returned: '100' }
{ type: 'testPass', debugTxHash: '0xdc325916fd93227b76231131e52e67f8913d395098c5ac767032db9bd757a91c', value: 'Greater than uint pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0xf98eea22bb86f13e0bb4072df22b540289a46b332bdb203a1e488d7e14a1dcd4', value: 'Greater than uint fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanUintFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '303:69:0', expected: '4', returned: '1' },
{ type: 'testPass', debugTxHash: '0xef5ef38329ba6aac2f868d53d803053c52b1895a2c25b704260435c141a63bfc', value: 'Greater than int pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0x6b9430f3f12c12fb11e5a8d32fef849ab34614e644be20c6b41a25e510453440', value: 'Greater than int fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanIntFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '569:67:0', expected: '1', returned: '-1' },
{ type: 'testPass', debugTxHash: '0x4c6e10815a5e82bf2c60950606dc886317f680028a9229ba2dda17b5ea36325a', value: 'Greater than uint int pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0x989c405c32c8e270a5dea69e6250a514c05dacd6fcf018365a241abc28c2497b', value: 'Greater than uint int fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanUintIntFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '845:71:0', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x9fed670ae2061929f71780835b7ea3eb7da6d4fb553cd2d5f62950c353165861', value: 'Greater than int uint pass test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', context: 'AssertGreaterThanTest' },
{ type: 'testFailure', debugTxHash: '0xcf394fd279293cdcf58efc42f3a443595fdb171769a45df01b0c84cd76b3a9a2', value: 'Greater than int uint fail test', filename: __dirname + '/examples_0/assert_greaterThan_test.sol', errMsg: 'greaterThanIntUintFailTest fails', context: 'AssertGreaterThanTest', assertMethod: 'greaterThan', location: '1125:76:0', expected: '115792089237316195423570985008687907853269984665640564039457584007913129639836', returned: '100' }
], ['time', 'web3'])
})
})
@ -274,14 +274,14 @@ describe('testRunner', function () {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertLesserThanTest', filename: __dirname + '/examples_0/assert_lesserThan_test.sol' },
{ type: 'testPass', debugTxHash: '0x47875047c1fff8a7b1cc1603418960cd2a3afe8a9c59337b19fb463a85d6e47e', value: 'Lesser than uint pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0xf6fd459d0b28d0d85c56dd69d953331291e1c234c8a263150252e35da0ed6671', value: 'Lesser than uint fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanUintFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '298:67:0', expected: '2', returned: '4' },
{ type: 'testPass', debugTxHash: '0x761d95111764af396634474899ff1db218d5e514d6de6bc3260af15b1f5b929f', value: 'Lesser than int pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0xc17697ef2df92c22707639caa9355bdf0d98dbb18157e72b8b257bb0eb2beb4e', value: 'Lesser than int fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanIntFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '557:65:0', expected: '-1', returned: '1' },
{ type: 'testPass', debugTxHash: '0xf0721b28c547c1c64948661d677cf6afc10d139315726280162a984f2f7e5d9c', value: 'Lesser than uint int pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x0757289229b58043c101cb311df8db16d1b30944747493e1491daa9aca6aa30e', value: 'Lesser than uint int fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanUintIntFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '826:71:0', expected: '-1', returned: '115792089237316195423570985008687907853269984665640564039457584007913129639935' },
{ type: 'testPass', debugTxHash: '0x316feb8f80c04b12194262dd80b6b004232eab00d7f7c3846badf6e92684e177', value: 'Lesser than int uint pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x65c5ab3cb85f163eefe3321cc4444defa99154d3cbe415b9384bbd2627449b6a', value: 'Lesser than int uint fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanIntUintFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '1105:69:0', expected: '1', returned: '1' },
{ type: 'testPass', debugTxHash: '0x524fb46aa0e8a78bc11a99432908d422450c2933d837f858aeacba9b84706d5c', value: 'Lesser than uint pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x0551a67b10b9e13182e8bdb4e530ed92466d5054ae959f999f2c558da2c39d22', value: 'Lesser than uint fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanUintFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '298:67:0', expected: '2', returned: '4' },
{ type: 'testPass', debugTxHash: '0x6d63958d8c3230e837d0ca8335e57262c6e0c6b2c07a5b481842b9ad7329ac28', value: 'Lesser than int pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x38e96ef44f4e785db4d40a95862a9797e8cef6de0ce1d059da72ff42e2f3ca62', value: 'Lesser than int fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanIntFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '557:65:0', expected: '-1', returned: '1' },
{ type: 'testPass', debugTxHash: '0x699f9fc2bf7a14134e89b94cd9dc1c537b5d4581a1c26a34a0c3343ddede9608', value: 'Lesser than uint int pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0xce1391dcfbfdc6c611e357e6c1c9f6cd9f257153ee400cb80bd36af6d239c342', value: 'Lesser than uint int fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanUintIntFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '826:71:0', expected: '-1', returned: '115792089237316195423570985008687907853269984665640564039457584007913129639935' },
{ type: 'testPass', debugTxHash: '0x7040e6664c13e6b35ef1daaef93a8cae36a62150d818183892096a98b921800c', value: 'Lesser than int uint pass test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', context: 'AssertLesserThanTest' },
{ type: 'testFailure', debugTxHash: '0x8c58bb433ea41760dcf11114232407d703e8ebf7d5e9637e2923282eae5caee6', value: 'Lesser than int uint fail test', filename: __dirname + '/examples_0/assert_lesserThan_test.sol', errMsg: 'lesserThanIntUintFailTest fails', context: 'AssertLesserThanTest', assertMethod: 'lesserThan', location: '1105:69:0', expected: '1', returned: '1' },
], ['time', 'web3'])
})
})
@ -309,10 +309,10 @@ describe('testRunner', function () {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'MyTest', filename: __dirname + '/examples_1/simple_storage_test.sol' },
{ type: 'testPass', debugTxHash: '0x5a805403a12f0431c5dd190d31a87eb62758f09dddc0c6ee7ee6899c5e7eba71', value: 'Initial value should be100', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testPass', debugTxHash: '0xd0ae7cb5a3a0f5e8f7bf90129e3daba36f649a5c1176ad54609f7b7615bef7dd', value: 'Initial value should not be200', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testFailure', debugTxHash: '0xb0d613434f2fd7060f97d4ca8bbfd8f2deeebed83062a25044f0237bd38b3229', value: 'Should trigger one fail', filename: __dirname + '/examples_1/simple_storage_test.sol', errMsg: 'uint test 1 fails', context: 'MyTest', assertMethod: 'equal', location: '532:51:1', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x5ee675ec81b550386b2fdd359ae3530e49dd3e02145e877a4a5f68753ac4e341', value: 'Should trigger one pass', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' }
{ type: 'testPass', debugTxHash: '0xed5b6898331119c6e3d1185b9de65d87ad7329cc629a8f2d43b966cf180a5dc1', value: 'Initial value should be100', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testPass', debugTxHash: '0x79cae5c4f44edfd7ae3490e01c75df5741b107672cef5e69800e4d30d380a721', value: 'Initial value should not be200', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testFailure', debugTxHash: '0x24a20f7643e88f891e469ef495911ab0b75f99e2b09b9b091e688674910d1506', value: 'Should trigger one fail', filename: __dirname + '/examples_1/simple_storage_test.sol', errMsg: 'uint test 1 fails', context: 'MyTest', assertMethod: 'equal', location: '532:51:1', expected: '2', returned: '1' },
{ type: 'testPass', debugTxHash: '0x08b1f60c908b7e6cf2dd24fc166c755f0fe5336aebfb325cae4ce00ea9bbf932', value: 'Should trigger one pass', filename: __dirname + '/examples_1/simple_storage_test.sol', context: 'MyTest' }
], ['time', 'web3'])
})
})
@ -340,8 +340,8 @@ describe('testRunner', function () {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'MyTest', filename: __dirname + '/examples_2/simple_storage_test.sol' },
{ type: 'testPass', debugTxHash: '0xa700d29204f1ddb40ef66f151c44387f905d405b6da10380111a751451af2fe1', value: 'Initial value should be100', filename: __dirname + '/examples_2/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testPass', debugTxHash: '0x2c037b78a435e5964615f838ea65f077f3b15d8552d514b3551d0fb87419e444', value: 'Value is set200', filename: __dirname + '/examples_2/simple_storage_test.sol', context: 'MyTest' }
{ type: 'testPass', debugTxHash: '0xed5b6898331119c6e3d1185b9de65d87ad7329cc629a8f2d43b966cf180a5dc1', value: 'Initial value should be100', filename: __dirname + '/examples_2/simple_storage_test.sol', context: 'MyTest' },
{ type: 'testPass', debugTxHash: '0x8ed5b4858405b43ad4052f5690b4b711c0f6cdeb67a64f54084417d43bc54308', value: 'Value is set200', filename: __dirname + '/examples_2/simple_storage_test.sol', context: 'MyTest' }
], ['time', 'web3'])
})
})
@ -366,8 +366,8 @@ describe('testRunner', function () {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'StringTest', filename: __dirname + '/examples_3/simple_string_test.sol' },
{ type: 'testPass', debugTxHash: '0x4e160dbc81f88d3d87b39d81651c42b0ea8e3aaa10c1a57394467e073bbcb2a4', value: 'Initial value should be hello world', filename: __dirname + '/examples_3/simple_string_test.sol', context: 'StringTest' },
{ type: 'testPass', debugTxHash: '0x47030578c5bcb990d837356430697d061a02813e3322fa3323f6b5f78176eea6', value: 'Value should not be hello wordl', filename: __dirname + '/examples_3/simple_string_test.sol', context: 'StringTest' }
{ type: 'testPass', debugTxHash: '0x3567da76ffbec37e3b43a41987a7ff3e61b41b4c544f35c010d2d4b39568d6d4', value: 'Initial value should be hello world', filename: __dirname + '/examples_3/simple_string_test.sol', context: 'StringTest' },
{ type: 'testPass', debugTxHash: '0x8619b743ccc99be7d5347a064732474b2d1b69844be65b0e7754c6ac1340d275', value: 'Value should not be hello wordl', filename: __dirname + '/examples_3/simple_string_test.sol', context: 'StringTest' }
], ['time', 'web3'])
})
})
@ -392,9 +392,9 @@ describe('testRunner', function () {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'StorageResolveTest', filename: __dirname + '/examples_5/test/simple_storage_test.sol' },
{ type: 'testPass', debugTxHash: '0x85e901e9160c4a17725d020f030c7cbb020d36da1fda8422d990391df3cbfcbb', value: 'Initial value should be100', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' },
{ type: 'testPass', debugTxHash: '0x1abb2456746b416cddcaf2f3fe960103e740e9772c47a0f1d65d48394facb21a', value: 'Check if even', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' },
{ type: 'testPass', debugTxHash: '0xfcc2332a24d2780390e85a06343fab81c4dc20c12cf5455d746641a9c3e8db03', value: 'Check if odd', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' }
{ type: 'testPass', debugTxHash: '0xed5b6898331119c6e3d1185b9de65d87ad7329cc629a8f2d43b966cf180a5dc1', value: 'Initial value should be100', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' },
{ type: 'testPass', debugTxHash: '0x6893fe4f5a83cc51f03c9237ab93b93ffd826236167d58e20666be4c1b3128a4', value: 'Check if even', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' },
{ type: 'testPass', debugTxHash: '0x64e600b32be681b68926660042ddd96f22d07949b424959811b8acb56e72f719', value: 'Check if odd', filename: __dirname + '/examples_5/test/simple_storage_test.sol', context: 'StorageResolveTest' }
], ['time', 'web3'])
})
})

@ -24,7 +24,6 @@ export class ExecutionContext {
removeProvider(name: any): void;
addProvider(network: any): void;
internalWeb3(): any;
blankWeb3(): Web3;
setContext(context: any, endPointUrl: any, confirmCb: any, infoCb: any): void;
executionContextChange(value: any, endPointUrl: any, confirmCb: any, infoCb: any, cb: any): Promise<any>;
currentblockGasLimit(): number;

@ -537,7 +537,7 @@ export const SolidityUnitTesting = (props: Record<string, any>) => { // eslint-d
updateFinalResult(null, null, testFilePath)
return
}
testTab.fileManager.readFile(testFilePath).then((content: string) => {
testTab.fileManager.readFile(testFilePath).then(async (content: string) => {
const runningTests: Record<string, Record<string, string>> = {}
runningTests[testFilePath] = { content }
filesContent[testFilePath] = { content }
@ -565,7 +565,7 @@ export const SolidityUnitTesting = (props: Record<string, any>) => { // eslint-d
callback(error)
}, (url: string, cb: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
return testTab.contentImport.resolveAndSave(url).then((result: any) => cb(null, result)).catch((error: Error) => cb(error.message)) // eslint-disable-line @typescript-eslint/no-explicit-any
}, { testFilePath }
}, { testFilePath: testFilePath, web3: await testTab.call('blockchain', 'web3VM') }
)
}).catch((error: Error) => {
console.log(error)

@ -1,12 +1,12 @@
import React from 'react' // eslint-disable-line
const CheckTxStatus = ({ tx, type }) => {
if (tx.status === '0x1' || tx.status === true) {
if (tx.status === 1 || tx.status === '0x1' || tx.status === true) {
return (<i className='remix_ui_terminal_txStatus remix_ui_terminal_succeeded fas fa-check-circle'></i>)
}
if (type === 'call' || type === 'unknownCall' || type === 'unknown') {
return (<i className='remix_ui_terminal_txStatus remix_ui_terminal_call'>call</i>)
} else if (tx.status === '0x0' || tx.status === false) {
} else if (tx.status === 0 || tx.status === '0x0' || tx.status === false) {
return (<i className='remix_ui_terminal_txStatus remix_ui_terminal_failed fas fa-times-circle'></i>)
} else {
return (<i className='remix_ui_terminal_txStatus fas fa-circle-thin' title='Status not available' ></i>)

@ -19,9 +19,9 @@ const showTable = (opts, showTableHash) => {
}
if (!opts.isCall) {
if (opts.status !== undefined && opts.status !== null) {
if (opts.status === '0x0' || opts.status === false) {
if (opts.status === 0 || opts.status === '0x0' || opts.status === false) {
msg = 'Transaction mined but execution failed'
} else if (opts.status === '0x1' || opts.status === true) {
} else if (opts.status === 1 || opts.status === '0x1' || opts.status === true) {
msg = 'Transaction mined and execution succeed'
}
} else {

@ -23,7 +23,13 @@ export default async (opts) => {
// If no options is selected, opts.upgradeable will be undefined
// We do not show test file for upgradeable contract
// @ts-ignore
if (!opts || opts.upgradeable === undefined || !opts.upgradeable) filesObj['tests/MyToken_test.sol'] = (await import('raw-loader!./tests/MyToken_test.sol')).default
if (!opts || opts.upgradeable === undefined || !opts.upgradeable) {
// @ts-ignore
if(opts.mintable) filesObj['tests/MyToken_test.sol'] = (await import('raw-loader!./tests/MyToken_mintable_test.sol')).default
// @ts-ignore
else filesObj['tests/MyToken_test.sol'] = (await import('raw-loader!./tests/MyToken_test.sol')).default
}
return filesObj
}

@ -0,0 +1,104 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "remix_tests.sol";
import "remix_accounts.sol";
import "../contracts/MyToken.sol";
contract MyTokenTest is MyToken {
address acc0;
address acc1;
address acc2;
address acc3;
address acc4;
function beforeAll() public {
acc0 = TestsAccounts.getAccount(0);
acc1 = TestsAccounts.getAccount(1);
acc2 = TestsAccounts.getAccount(2);
acc3 = TestsAccounts.getAccount(3);
acc4 = TestsAccounts.getAccount(4);
}
function testTokenInitialValues() public {
Assert.equal(name(), "MyToken", "token name did not match");
Assert.equal(symbol(), "MTK", "token symbol did not match");
Assert.equal(decimals(), 18, "token decimals did not match");
Assert.equal(totalSupply(), 0, "token supply should be zero");
}
function testTokenMinting() public {
Assert.equal(balanceOf(acc0), 0, "token balance should be zero initially");
mint(acc0, 10000);
Assert.equal(balanceOf(acc0), 10000, "token balance did not match");
}
function testTotalSupply() public {
Assert.equal(totalSupply(), 10000, "total supply did not match");
}
/// #sender: account-1
function failTestTokenMintingWithWrongOwner() public {
Assert.equal(balanceOf(acc0), 0, "token balance should be zero initially");
mint(acc0, 10000);
Assert.equal(balanceOf(acc0), 10000, "token balance did not match");
}
function failTestTokenMintingForZeroAddress() public {
mint(address(0), 10000);
}
function testTokenTransfer() public {
Assert.equal(balanceOf(acc1), 0, "token balance should be zero initially");
transfer(acc1, 500);
Assert.equal(balanceOf(acc0), 9500, "token balance did not match");
Assert.equal(balanceOf(acc1), 500, "token balance did not match");
}
/// #sender: account-1
function testTokenTransferToOtherAddress() public {
Assert.equal(balanceOf(acc1), 500, "acc1 token balance did not match");
transfer(acc2, 100);
Assert.equal(balanceOf(acc1), 400, "acc1 token balance did not match");
Assert.equal(balanceOf(acc2), 100, "acc2 token balance did not match");
}
function failTestTokenTransferToZeroAddress() public {
transfer(address(0), 100);
}
/// #sender: account-2
function failTestTokenTransferMoreThanBalance() public {
transfer(acc3, 110);
}
function testTokenApprove() public {
Assert.equal(allowance(acc0, acc3), 0, "token allowance should be zero initially");
approve(acc3, 500);
Assert.equal(allowance(acc0, acc3), 500, "token allowance did not match");
}
function failTestTokenApproveForZeroSpenderAddress() public {
approve(address(0), 500);
}
/// #sender: account-3
function testTokenTransferfrom() public {
Assert.equal(allowance(acc0, acc3), 500, "token allowance did not match");
transferFrom(acc0, acc4, 400);
Assert.equal(balanceOf(acc4), 400, "acc4 token balance did not match");
Assert.equal(allowance(acc0, acc3), 100, "token allowance did not match");
}
/// #sender: account-3
function failTestTokenTransferfromForMoreThanAllowance() public {
transferFrom(acc0, acc4, 110);
}
/// #sender: account-3
function failTestTokenTransferfromForZeroToAddress() public {
transferFrom(acc0, address(0), 100);
}
}

@ -4,15 +4,12 @@ pragma solidity >=0.7.0 <0.9.0;
import "remix_tests.sol";
import "../contracts/MyToken.sol";
contract MyTokenTest {
contract MyTokenTest is MyToken {
MyToken s;
function beforeAll () public {
s = new MyToken();
}
function testTokenNameAndSymbol () public {
Assert.equal(s.name(), "MyToken", "token name did not match");
Assert.equal(s.symbol(), "MTK", "token symbol did not match");
function testTokenInitialValues() public {
Assert.equal(name(), "MyToken", "token name did not match");
Assert.equal(symbol(), "MTK", "token symbol did not match");
Assert.equal(decimals(), 18, "token decimals did not match");
Assert.equal(totalSupply(), 0, "token supply should be zero");
}
}

@ -114,12 +114,16 @@
"build-contracts": "find ./node_modules/@openzeppelin/contracts | grep -i '.sol' > libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt && find ./node_modules/@uniswap/v3-core/contracts | grep -i '.sol' >> libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt"
},
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-class-properties": "^7.16.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@erebos/bzz-node": "^0.13.0",
"@ethereumjs/block": "^3.5.1",
"@ethereumjs/common": "^2.5.0",
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"@ethereumjs/block": "^4.0.0",
"@ethereumjs/common": "^3.0.0",
"@ethereumjs/evm": "^1.0.0",
"@ethereumjs/statemanager": "^1.0.0",
"@ethereumjs/tx": "^4.0.0",
"@ethereumjs/util": "^8.0.0",
"@ethereumjs/vm": "^6.0.0",
"@ethersphere/bee-js": "^3.2.0",
"@isomorphic-git/lightning-fs": "^4.4.1",
"@monaco-editor/react": "4.4.5",
@ -146,7 +150,6 @@
"deep-equal": "^1.0.1",
"document-register-element": "1.13.1",
"eslint-config-prettier": "^8.5.0",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.4.2",
"ethjs-util": "^0.1.6",
"express": "^4.18.2",
@ -331,7 +334,6 @@
"style-loader": "^3.3.1",
"tap-spec": "^5.0.0",
"tape": "^4.13.3",
"terser-webpack-plugin": "^4.2.3",
"timers-browserify": "^2.0.12",
"ts-jest": "^29.0.3",
"ts-node": "10.9.1",

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