logsManager and txExecution

pull/5370/head
aniket-engg 4 years ago committed by Aniket
parent 73873994c7
commit 16bf96e551
  1. 22
      libs/remix-lib/src/execution/logsManager.ts
  2. 199
      libs/remix-lib/src/execution/txExecution.ts

@ -1,7 +1,13 @@
const async = require('async') import { eachOf } from 'async'
const crypto = require('crypto') import { randomBytes } from 'crypto'
class LogsManager { export class LogsManager {
notificationCallbacks
subscriptions
filters
filterTracking
oldLogs
constructor () { constructor () {
this.notificationCallbacks = [] this.notificationCallbacks = []
@ -12,7 +18,7 @@ class LogsManager {
} }
checkBlock (blockNumber, block, web3) { checkBlock (blockNumber, block, web3) {
async.eachOf(block.transactions, (tx, i, next) => { eachOf(block.transactions, (tx, i, next) => {
let txHash = '0x' + tx.hash().toString('hex') let txHash = '0x' + tx.hash().toString('hex')
web3.eth.getTransactionReceipt(txHash, (_error, receipt) => { web3.eth.getTransactionReceipt(txHash, (_error, receipt) => {
@ -97,7 +103,7 @@ class LogsManager {
} }
subscribe (params) { subscribe (params) {
let subscriptionId = '0x' + crypto.randomBytes(16).toString('hex') let subscriptionId = '0x' + randomBytes(16).toString('hex')
this.subscriptions[subscriptionId] = params this.subscriptions[subscriptionId] = params
return subscriptionId return subscriptionId
} }
@ -107,7 +113,7 @@ class LogsManager {
} }
newFilter (filterType, params) { newFilter (filterType, params) {
const filterId = '0x' + crypto.randomBytes(16).toString('hex') const filterId = '0x' + randomBytes(16).toString('hex')
if (filterType === 'block' || filterType === 'pendingTransactions') { if (filterType === 'block' || filterType === 'pendingTransactions') {
this.filters[filterId] = { filterType } this.filters[filterId] = { filterType }
} }
@ -123,7 +129,7 @@ class LogsManager {
} }
getLogsForFilter (filterId, logsOnly) { getLogsForFilter (filterId, logsOnly) {
const {filterType, params} = this.filter[filterId] const {filterType, params} = this.filters[filterId]
const tracking = this.filterTracking[filterId] const tracking = this.filterTracking[filterId]
if (logsOnly || filterType === 'filter') { if (logsOnly || filterType === 'filter') {
@ -161,5 +167,3 @@ class LogsManager {
} }
} }
module.exports = LogsManager

@ -1,109 +1,108 @@
'use strict' 'use strict'
import { ethers } from 'ethers' import { ethers } from 'ethers'
module.exports = { /**
/** * deploy the given contract
* deploy the given contract *
* * @param {String} from - sender address
* @param {String} from - sender address * @param {String} data - data to send with the transaction ( return of txFormat.buildData(...) ).
* @param {String} data - data to send with the transaction ( return of txFormat.buildData(...) ). * @param {String} value - decimal representation of value.
* @param {String} value - decimal representation of value. * @param {String} gasLimit - decimal representation of gas limit.
* @param {String} gasLimit - decimal representation of gas limit. * @param {Object} txRunner - TxRunner.js instance
* @param {Object} txRunner - TxRunner.js instance * @param {Object} callbacks - { confirmationCb, gasEstimationForceSend, promptCb }
* @param {Object} callbacks - { confirmationCb, gasEstimationForceSend, promptCb } * [validate transaction] confirmationCb (network, tx, gasEstimation, continueTxExecution, cancelCb)
* [validate transaction] confirmationCb (network, tx, gasEstimation, continueTxExecution, cancelCb) * [transaction failed, force send] gasEstimationForceSend (error, continueTxExecution, cancelCb)
* [transaction failed, force send] gasEstimationForceSend (error, continueTxExecution, cancelCb) * [personal mode enabled, need password to continue] promptCb (okCb, cancelCb)
* [personal mode enabled, need password to continue] promptCb (okCb, cancelCb) * @param {Function} finalCallback - last callback.
* @param {Function} finalCallback - last callback. */
*/ export function createContract (from, data, value, gasLimit, txRunner, callbacks, finalCallback) {
createContract: function (from, data, value, gasLimit, txRunner, callbacks, finalCallback) { if (!callbacks.confirmationCb || !callbacks.gasEstimationForceSend || !callbacks.promptCb) {
if (!callbacks.confirmationCb || !callbacks.gasEstimationForceSend || !callbacks.promptCb) { return finalCallback('all the callbacks must have been defined')
return finalCallback('all the callbacks must have been defined') }
} const tx = { from: from, to: null, data: data, useCall: false, value: value, gasLimit: gasLimit }
const tx = { from: from, to: null, data: data, useCall: false, value: value, gasLimit: gasLimit } txRunner.rawRun(tx, callbacks.confirmationCb, callbacks.gasEstimationForceSend, callbacks.promptCb, (error, txResult) => {
txRunner.rawRun(tx, callbacks.confirmationCb, callbacks.gasEstimationForceSend, callbacks.promptCb, (error, txResult) => { // see universaldapp.js line 660 => 700 to check possible values of txResult (error case)
// see universaldapp.js line 660 => 700 to check possible values of txResult (error case) finalCallback(error, txResult)
finalCallback(error, txResult) })
}) }
},
/** /**
* call the current given contract ! that will create a transaction ! * call the current given contract ! that will create a transaction !
* *
* @param {String} from - sender address * @param {String} from - sender address
* @param {String} to - recipient address * @param {String} to - recipient address
* @param {String} data - data to send with the transaction ( return of txFormat.buildData(...) ). * @param {String} data - data to send with the transaction ( return of txFormat.buildData(...) ).
* @param {String} value - decimal representation of value. * @param {String} value - decimal representation of value.
* @param {String} gasLimit - decimal representation of gas limit. * @param {String} gasLimit - decimal representation of gas limit.
* @param {Object} txRunner - TxRunner.js instance * @param {Object} txRunner - TxRunner.js instance
* @param {Object} callbacks - { confirmationCb, gasEstimationForceSend, promptCb } * @param {Object} callbacks - { confirmationCb, gasEstimationForceSend, promptCb }
* [validate transaction] confirmationCb (network, tx, gasEstimation, continueTxExecution, cancelCb) * [validate transaction] confirmationCb (network, tx, gasEstimation, continueTxExecution, cancelCb)
* [transaction failed, force send] gasEstimationForceSend (error, continueTxExecution, cancelCb) * [transaction failed, force send] gasEstimationForceSend (error, continueTxExecution, cancelCb)
* [personal mode enabled, need password to continue] promptCb (okCb, cancelCb) * [personal mode enabled, need password to continue] promptCb (okCb, cancelCb)
* @param {Function} finalCallback - last callback. * @param {Function} finalCallback - last callback.
*/ */
callFunction: function (from, to, data, value, gasLimit, funAbi, txRunner, callbacks, finalCallback) { export function callFunction (from, to, data, value, gasLimit, funAbi, txRunner, callbacks, finalCallback) {
const useCall = funAbi.stateMutability === 'view' || funAbi.stateMutability === 'pure' || funAbi.constant const useCall = funAbi.stateMutability === 'view' || funAbi.stateMutability === 'pure' || funAbi.constant
const tx = { from, to, data, useCall, value, gasLimit } const tx = { from, to, data, useCall, value, gasLimit }
txRunner.rawRun(tx, callbacks.confirmationCb, callbacks.gasEstimationForceSend, callbacks.promptCb, (error, txResult) => { txRunner.rawRun(tx, callbacks.confirmationCb, callbacks.gasEstimationForceSend, callbacks.promptCb, (error, txResult) => {
// see universaldapp.js line 660 => 700 to check possible values of txResult (error case) // see universaldapp.js line 660 => 700 to check possible values of txResult (error case)
finalCallback(error, txResult) finalCallback(error, txResult)
}) })
}, }
/** /**
* check if the vm has errored * check if the vm has errored
* *
* @param {Object} txResult - the value returned by the vm * @param {Object} txResult - the value returned by the vm
* @return {Object} - { error: true/false, message: DOMNode } * @return {Object} - { error: true/false, message: DOMNode }
*/ */
checkVMError: function (txResult) { export function checkVMError (txResult) {
const errorCode = { const errorCode = {
OUT_OF_GAS: 'out of gas', OUT_OF_GAS: 'out of gas',
STACK_UNDERFLOW: 'stack underflow', STACK_UNDERFLOW: 'stack underflow',
STACK_OVERFLOW: 'stack overflow', STACK_OVERFLOW: 'stack overflow',
INVALID_JUMP: 'invalid JUMP', INVALID_JUMP: 'invalid JUMP',
INVALID_OPCODE: 'invalid opcode', INVALID_OPCODE: 'invalid opcode',
REVERT: 'revert', REVERT: 'revert',
STATIC_STATE_CHANGE: 'static state change', STATIC_STATE_CHANGE: 'static state change',
INTERNAL_ERROR: 'internal error', INTERNAL_ERROR: 'internal error',
CREATE_COLLISION: 'create collision', CREATE_COLLISION: 'create collision',
STOP: 'stop', STOP: 'stop',
REFUND_EXHAUSTED: 'refund exhausted' REFUND_EXHAUSTED: 'refund exhausted'
} }
const ret = { const ret = {
error: false, error: false,
message: '' message: ''
} }
if (!txResult.result.execResult.exceptionError) { if (!txResult.result.execResult.exceptionError) {
return ret
}
const exceptionError = txResult.result.execResult.exceptionError.error || ''
const error = `VM error: ${exceptionError}.\n`
let msg
if (exceptionError === errorCode.INVALID_OPCODE) {
msg = `\t\n\tThe execution might have thrown.\n`
ret.error = true
} else if (exceptionError === errorCode.OUT_OF_GAS) {
msg = `\tThe transaction ran out of gas. Please increase the Gas Limit.\n`
ret.error = true
} else if (exceptionError === errorCode.REVERT) {
const returnData = txResult.result.execResult.returnValue
// It is the hash of Error(string)
if (returnData && (returnData.slice(0, 4).toString('hex') === '08c379a0')) {
const abiCoder = new ethers.utils.AbiCoder()
const reason = abiCoder.decode(['string'], returnData.slice(4))[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.`
}
ret.error = true
} else if (exceptionError === errorCode.STATIC_STATE_CHANGE) {
msg = `\tState changes is not allowed in Static Call context\n`
ret.error = true
}
ret.message = `${error}${exceptionError}${msg}\tDebug the transaction to get more information.`
return ret return ret
} }
const exceptionError = txResult.result.execResult.exceptionError.error || ''
const error = `VM error: ${exceptionError}.\n`
let msg
if (exceptionError === errorCode.INVALID_OPCODE) {
msg = `\t\n\tThe execution might have thrown.\n`
ret.error = true
} else if (exceptionError === errorCode.OUT_OF_GAS) {
msg = `\tThe transaction ran out of gas. Please increase the Gas Limit.\n`
ret.error = true
} else if (exceptionError === errorCode.REVERT) {
const returnData = txResult.result.execResult.returnValue
// It is the hash of Error(string)
if (returnData && (returnData.slice(0, 4).toString('hex') === '08c379a0')) {
const abiCoder = new ethers.utils.AbiCoder()
const reason = abiCoder.decode(['string'], returnData.slice(4))[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.`
}
ret.error = true
} else if (exceptionError === errorCode.STATIC_STATE_CHANGE) {
msg = `\tState changes is not allowed in Static Call context\n`
ret.error = true
}
ret.message = `${error}${exceptionError}${msg}\tDebug the transaction to get more information.`
return ret
} }

Loading…
Cancel
Save