Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Fix #114: Return error message if vmErrorsOnRPCResponse is disabled #115

Merged
merged 1 commit into from
May 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions lib/provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ Provider.prototype.send = function(payload, callback) {
if (self.options.verbose) {
self.options.logger.log(" < " + JSON.stringify(response, null, 2).split("\n").join("\n < "));
}

callback(response.error ? err : null, response);
};

Expand Down Expand Up @@ -184,7 +183,7 @@ Provider.prototype.cleanUpErrorObject = function(err, response) {
return _.merge(response, errorObject)
}

// helper list of RPC methods which execute code and respond with a transaction has as their result
// helper list of RPC methods which execute code and respond with a transaction hash as their result
let transactionMethods = [
'eth_sendTransaction',
'eth_sendRawTransaction',
Expand All @@ -204,7 +203,6 @@ Provider.prototype.reportErrorInResponse = function(request, err, response) {
// field to prevent poorly-written clients which assume that the existence of
// the "result" field implies no errors from breaking.
if (self._isTransactionRequest(request)) {

if (err instanceof RuntimeError) {
// Make sure we always return the transaction hash on failed transactions so
// the caller can get their tx receipt. This breaks JSONRPC 2.0, but it's how
Expand All @@ -222,6 +220,20 @@ Provider.prototype.reportErrorInResponse = function(request, err, response) {
}
}

if (request.method === 'eth_call') {
if (err instanceof RuntimeError) {
if (self.options.vmErrorsOnRPCResponse) {
if(!response.error.data) {
response.error.data = {}
}
response.error.data[err.hashes[0]] = err.results[err.hashes[0]]
} else {
response.result = err.results[err.hashes[0]].return || '0x'
delete response.error
}
}
}

return self.cleanUpErrorObject(err, response)
}

Expand Down
3 changes: 2 additions & 1 deletion lib/utils/runtimeerror.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ RuntimeError.prototype.combine = function(transactions, vm_output) {

this.results[hash] = {
error: result.vm.exceptionError.error || result.vm.exceptionError,
program_counter: result.vm.runState.programCounter
program_counter: result.vm.runState.programCounter,
return: to.hex(result.vm.return)
};
}
}
Expand Down
20 changes: 10 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"prepend-file": "^1.3.1",
"seedrandom": "~2.4.2",
"shebang-loader": "0.0.1",
"solc": "0.4.18",
"solc": "0.4.24",
"temp": "^0.8.3",
"tmp": "0.0.31",
"web3": "^1.0.0-beta.30",
Expand Down
7 changes: 7 additions & 0 deletions test/RuntimeError.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ contract RuntimeError {
throw;
}

function errorWithMessage() {
for (uint i = 0; i < 3; ) {
i++;
}
revert("Message");
}

function success() {

}
Expand Down
2 changes: 1 addition & 1 deletion test/debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ describe("Debug", function() {

assert.equal(lastop.op, "STOP");
assert.equal(lastop.gasCost, 1);
assert.equal(lastop.pc, 141);
assert.equal(lastop.pc, 145);
assert.equal(lastop.storage['0000000000000000000000000000000000000000000000000000000000000000'], '000000000000000000000000000000000000000000000000000000000000001a')
assert.equal(lastop.storage['0000000000000000000000000000000000000000000000000000000000000001'], '000000000000000000000000000000000000000000000000000000000000001f')

Expand Down
5 changes: 3 additions & 2 deletions test/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ var async = require("async");
var util = require("util")

var source = " \
pragma solidity ^0.4.2; \
pragma solidity ^0.4.24; \
contract EventTest { \
event ExampleEvent(uint indexed first, uint indexed second); \
\
function triggerEvent(uint _first, uint _second) public { \
ExampleEvent(_first, _second); \
emit ExampleEvent(_first, _second); \
} \
}"

Expand Down Expand Up @@ -40,6 +40,7 @@ var tests = function(web3, EventTest) {

if (result.errors != null) {
done(result.errors[0])
return
}

var abi = JSON.parse(result.contracts[":EventTest"].interface);
Expand Down
6 changes: 3 additions & 3 deletions test/requests.js
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ var tests = function(web3) {

web3.eth.estimateGas(tx_data, function(err, result) {
if (err) return done(err);
assert.equal(result, 27682);
assert.equal(result, 27693);

web3.eth.getBlockNumber(function(err, result) {
if (err) return done(err);
Expand All @@ -673,7 +673,7 @@ var tests = function(web3) {

web3.eth.estimateGas(tx_data, function(err, result) {
if (err) return done(err);
assert.equal(result, 27682);
assert.equal(result, 27693);
done();
});
});
Expand All @@ -687,7 +687,7 @@ var tests = function(web3) {

web3.eth.estimateGas(tx_data, function(err, result) {
if (err) return done(err);
assert.equal(result, 27682);
assert.equal(result, 27693);
done();
});
});
Expand Down
64 changes: 63 additions & 1 deletion test/runtime_errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,68 @@ function runTests(web3, provider, extraTests) {
});
});

it("should have correct return value when calling a method that reverts without message", function(done) {
provider.send({
jsonrpc: '2.0',
id: new Date().getTime(),
method: 'eth_call',
params: [{
from: testState.accounts[0],
to: testState.errorInstance.options.address,
// calls error()
data: '0xc79f8b62',
gas: to.hex(3141592)
}]
}, function(err, response) {
if (provider.options.vmErrorsOnRPCResponse) {
// null & undefined are equivalent for equality tests, but I'm being
// pedantic here for readability's sake
assert(response.error !== null)
assert(response.error !== undefined)
assert(response.result === undefined || response.result === null)

assert(/revert/.test(response.error.message), `Expected error message (${response.error.message}) to contain 'revert'`);

} else {
assert(response.error === undefined)
assert(response.result === "0x0")
}

done();
});
});

it("should have correct return value when calling a method that reverts with message", function(done) {
provider.send({
jsonrpc: '2.0',
id: new Date().getTime(),
method: 'eth_call',
params: [{
from: testState.accounts[0],
to: testState.errorInstance.options.address,
// calls error()
data: '0xcd4aed30',
gas: to.hex(3141592)
}]
}, function(err, response) {
if (provider.options.vmErrorsOnRPCResponse) {
// null & undefined are equivalent for equality tests, but I'm being
// pedantic here for readability's sake
assert(response.error !== null)
assert(response.error !== undefined)
assert(response.result === undefined || response.result === null)

assert(/revert/.test(response.error.message), `Expected error message (${response.error.message}) to contain 'revert'`);

} else {
assert(response.error === undefined)
assert(response.result === "0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000074d65737361676500000000000000000000000000000000000000000000000000")
}

done();
});
});

if (extraTests) {
extraTests(testState)
}
Expand Down Expand Up @@ -153,7 +215,7 @@ describe("Runtime Errors with vmErrorsOnRPCResponse = true:", function() {

assert(response.error);
assert(response.error.data[txHash]);
assert.equal(response.error.data[txHash].program_counter, 77); // magic number, will change if compiler changes.
assert.equal(response.error.data[txHash].program_counter, 91); // magic number, will change if compiler changes.
done();
});
});
Expand Down
1 change: 0 additions & 1 deletion test/vm.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ describe("revert opcode", function() {
it("should return a transaction receipt with status 0 on REVERT", function() {
var revertCode = testContext.revertContract.binary;
var revertAbi = JSON.parse(testContext.revertContract.abi);
var callCount = 0;

var RevertContract = new web3.eth.Contract(revertAbi);
RevertContract._code = revertCode;
Expand Down