Skip to content

Commit

Permalink
Fetch revert reason for sendSignedTransaction (#3420)
Browse files Browse the repository at this point in the history
* Fetch revert reason for sendSignedTransaction

* Update changelog

* Update sendSignedTransaction TS to include Revert error type
  • Loading branch information
cgewecke committed Apr 7, 2020
1 parent 0ffac4b commit 2a5c5cb
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ Released with 1.0.0-beta.37 code base.

### Added

- Add revert reason support to sendSignedTransaction
- ENS module extended with the possibility to add a custom registry (#3301)
- Missing ENS Registry methods and Resolver.supportsInterface method added (#3325)

Expand Down
30 changes: 28 additions & 2 deletions packages/web3-core-method/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,13 @@ Method.prototype._confirmTransaction = function (defer, result, payload) {
params: 2,
inputFormatter: [formatters.inputAddressFormatter, formatters.inputDefaultBlockNumberFormatter]
}),
new Method({
name: 'getTransactionByHash',
call: 'eth_getTransactionByHash',
params: 1,
inputFormatter: [null],
outputFormatter: formatters.outputTransactionFormatter
}),
new Subscriptions({
name: 'subscribe',
type: 'eth',
Expand Down Expand Up @@ -421,10 +428,29 @@ Method.prototype._confirmTransaction = function (defer, result, payload) {
try {
var revertMessage = null;

if (method.handleRevert && method.call === 'eth_sendTransaction') {
if ( method.handleRevert &&
(method.call === 'eth_sendTransaction' || method.call === 'eth_sendRawTransaction'))
{
var txReplayOptions = payload.params[0];

// If send was raw, fetch the transaction and reconstitute the
// original params so they can be replayed with `eth_call`
if (method.call === 'eth_sendRawTransaction'){
var txToReplay = await _ethereumCall.getTransactionByHash(receipt.transactionHash);

txReplayOptions = formatters.inputTransactionFormatter({
data: txToReplay.input,
to: txToReplay.to,
from: txToReplay.from,
gas: txToReplay.gas,
gasPrice: txToReplay.gasPrice,
value: txToReplay.value
})
}

// Get revert reason string with eth_call
revertMessage = await method.getRevertReason(
payload.params[0],
txReplayOptions,
receipt.blockNumber
);

Expand Down
3 changes: 2 additions & 1 deletion packages/web3-eth/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,8 @@ var Eth = function Eth() {
name: 'sendSignedTransaction',
call: 'eth_sendRawTransaction',
params: 1,
inputFormatter: [null]
inputFormatter: [null],
abiCoder: abi
}),
new Method({
name: 'signTransaction',
Expand Down
2 changes: 1 addition & 1 deletion packages/web3-eth/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ export class Eth {
sendSignedTransaction(
signedTransactionData: string,
callback?: (error: Error, hash: string) => void
): PromiEvent<TransactionReceipt>;
): PromiEvent<TransactionReceipt | TransactionRevertInstructionError>;

sign(
dataToSign: string,
Expand Down
4 changes: 2 additions & 2 deletions packages/web3-eth/types/tests/eth.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,9 @@ eth.sendTransaction(
(error: Error, hash: string) => {}
);

// $ExpectType PromiEvent<TransactionReceipt>
// $ExpectType PromiEvent<TransactionReceipt | TransactionRevertInstructionError>
eth.sendSignedTransaction('0xf889808609184e72a0008227109');
// $ExpectType PromiEvent<TransactionReceipt>
// $ExpectType PromiEvent<TransactionReceipt | TransactionRevertInstructionError>
eth.sendSignedTransaction(
'0xf889808609184e72a0008227109',
(error: Error, hash: string) => {}
Expand Down
29 changes: 29 additions & 0 deletions test/e2e.method.signing.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,35 @@ describe('transaction and message signing [ @E2E ]', function() {
}
});

it('sendSignedTransaction reverts with reason', async function(){
const data = instance
.methods
.reverts()
.encodeABI();

const source = wallet[0].address;
const txCount = await web3.eth.getTransactionCount(source);

const txObject = {
nonce: web3.utils.toHex(txCount),
to: instance.options.address,
gasLimit: web3.utils.toHex(400000),
gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
data: data
};

const signed = await web3.eth.accounts.signTransaction(txObject, wallet[0].privateKey);

web3.eth.handleRevert = true;
try {
await web3.eth.sendSignedTransaction(signed.rawTransaction);
assert.fail();
} catch(err){
assert.equal(err.receipt.status, false);
assert.equal(err.reason, "REVERTED WITH REVERT");
}
});

it('transactions sent with wallet error correctly (OOG)', function(done){
const data = instance
.methods
Expand Down

0 comments on commit 2a5c5cb

Please sign in to comment.