-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor getRevertReason
and add tests
#5844
Conversation
Bundle StatsHey there, this message comes from a github action that helps you and reviewers to understand how these changes affect the size of this project's bundle. As this PR is updated, I'll keep you updated on how the bundle size is impacted. Total
View detailed bundle breakdownAdded
Removed No assets were removed Bigger
Smaller
Unchanged
|
Deploying with
|
Latest commit: |
28a3d84
|
Status: | ✅ Deploy successful! |
Preview URL: | https://f43fd401.web3-js-docs.pages.dev |
Branch Preview URL: | https://wyatt-4-x-5841-return-revert.web3-js-docs.pages.dev |
import { decodeParameters } from './api/parameters_api'; | ||
import { jsonInterfaceMethodToString } from './utils'; | ||
|
||
export const decodeContractErrorData = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method was moved from web3-eth-contract
package to web3-eth-abi
to avoid a circular dependency issue between web3-eth-contract
and web3-eth
since it's now being used inside web3-eth
's getRevertReason
util method. It was also renamed from decodeErrorData
} else { | ||
this._eventEmitter.emit('message', response, undefined); | ||
requestItem?.deferredPromise.reject(new ResponseError(response)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed this code and the tests from packages/web3-providers-ws/test/unit/web_socket_provider.test.ts
because I couldn't get an error to actually trigger this code because any error resulting from a failed network request was emitted by _onError and any RPC response with an error is now being resolved. As the only tests written for this code were for RPC response errors, I don't think this code is needed anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change also fixes #5838
@@ -28,7 +28,7 @@ import { BasicAbi, BasicBytecode } from '../shared_fixtures/build/Basic'; | |||
|
|||
Error.stackTraceLimit = Infinity; | |||
|
|||
describe('eth', () => { | |||
describe.skip('eth', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order for these tests to pass with the expected error, #5839 and #5840 need to be addressed. This is because previously when sendTransaction
was called getRevertReason
we were throwing the reason making the sendTransaction
promise to reject
with the revert reason. Now that we're returning the reason, sendTransaction
rejects at the requestManager
(#5840) giving sendTransaction
no opportunity to throw an error with the retrieved revert reason - we will need to re-enable and refactor these tests after #5840 and #5839
For context, the following is the result of running these tests with this PR's changes:
$ jest --config=./test/integration/jest.config.js --forceExit test/integration/handle_revert.test.ts
FAIL test/integration/handle_revert.test.ts
● eth › handleRevert › should get revert reason
expect(received).rejects.toThrow(expected)
- Expected message - 2
+ Received message + 1
- Transaction has been reverted by the EVM:
- undefined
+ Error happened while trying to execute a function inside a smart contract
440 | // However, more processing will happen at a higher level to decode the error data,
441 | // according to the Error ABI, if it was available as of EIP-838.
> 442 | if (error?.message.includes('revert')) throw new ContractExecutionError(error);
| ^
443 |
444 | return false;
445 | }
at Function._isReverted (../web3-core/src/web3_request_manager.ts:442:48)
at Web3RequestManager._processJsonRpcResponse (../web3-core/src/web3_request_manager.ts:371:35)
at Web3RequestManager.<anonymous> (../web3-core/src/web3_request_manager.ts:216:16)
at fulfilled (../web3-core/lib/web3_request_manager.js:5:58)
89 | it('should get revert reason', async () => {
90 | contract.handleRevert = true;
> 91 | await expect(contract.methods.reverts().send({ from: accounts[0] })).rejects.toThrow(
| ^
92 | new TransactionRevertError(
93 | 'Returned error: execution reverted: REVERTED WITH REVERT',
94 | ),
at Object.toThrow (../../node_modules/expect/build/index.js:241:22)
at test/integration/handle_revert.test.ts:91:81
at test/integration/handle_revert.test.ts:8:71
at Object.<anonymous>.__awaiter (test/integration/handle_revert.test.ts:4:12)
at Object.<anonymous> (test/integration/handle_revert.test.ts:89:45)
● eth › handleRevert › should get revert reason for eth tx
expect(received).rejects.toThrow(expected)
- Expected message - 2
+ Received message + 1
- Transaction has been reverted by the EVM:
- undefined
+ Returned error: invalid argument 0: json: cannot unmarshal invalid hex string into Go struct field TransactionArgs.data of type hexutil.Bytes
370 | }
371 | } else if (!Web3RequestManager._isReverted(response)) {
> 372 | throw new InvalidResponseError<ErrorType>(response);
| ^
373 | }
374 | }
375 |
at Web3RequestManager._processJsonRpcResponse (../web3-core/src/web3_request_manager.ts:372:11)
at Web3RequestManager.<anonymous> (../web3-core/src/web3_request_manager.ts:216:16)
at fulfilled (../web3-core/lib/web3_request_manager.js:5:58)
112 | s: '0x39f77e0b68d5524826e4385ad4e1f01e748f32c177840184ae65d9592fdfe5c',
113 | }),
> 114 | ).rejects.toThrow(
| ^
115 | new TransactionRevertError(
116 | 'Returned error: invalid argument 0: json: cannot unmarshal invalid hex string into Go struct field TransactionArgs.data of type hexutil.Bytes',
117 | ),
at Object.toThrow (../../node_modules/expect/build/index.js:241:22)
at test/integration/handle_revert.test.ts:114:14
at test/integration/handle_revert.test.ts:8:71
at Object.<anonymous>.__awaiter (test/integration/handle_revert.test.ts:4:12)
at Object.<anonymous> (test/integration/handle_revert.test.ts:98:56)
Test Suites: 1 failed, 1 total
Tests: 2 failed, 1 passed, 3 total
Snapshots: 0 total
Time: 1.873 s
Ran all test suites matching /test\/integration\/handle_revert.test.ts/i.
Force exiting Jest: Have you considered using `--detectOpenHandles` to detect async operations that kept running after all tests finished?
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be part of RC.0 @mconnelly8
return error.innerError.message; | ||
} | ||
|
||
return error instanceof Error ? error.message : error; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case of generic error ( that is not due to failed tx reverted ) , we should throw it and remove string
from return typePromise<undefined | RevertReason | RevertReasonWithCustomError | string | unknown>
.
Because for getRevertReason
function call with eth_call rpc in case of generic errors:
- neither tx eth_call was reverted with reason.
- nor it succeeded with out any revert reason,
but request for looking any of above answers failed, that user should catch. It will also make return types homogeneous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated via this commit, however string
is still a possible return type because of
if (
error instanceof InvalidResponseError &&
!Array.isArray(error.innerError) &&
error.innerError !== undefined
) {
return error.innerError.message;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if InvalidResponseError is also not categorizable under 1 and 2, shouldn't it also be thrown?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jdevcs The code snippet above is for errors such as:
InvalidResponseError: Returned error: err: intrinsic gas too low: have 0, want 21544 (supplied gas 0)
at Web3RequestManager._processJsonRpcResponse (/home/anon/Public/code/ChainSafe/git-repos/web3.js/packages/web3-core/src/web3_request_manager.ts:372:11)
at Web3RequestManager.<anonymous> (/home/anon/Public/code/ChainSafe/git-repos/web3.js/packages/web3-core/src/web3_request_manager.ts:216:16)
at Generator.next (<anonymous>)
at fulfilled (/home/anon/Public/code/ChainSafe/git-repos/web3.js/packages/web3-core/lib/web3_request_manager.js:5:58)
at processTicksAndRejections (node:internal/process/task_queues:95:5) {
innerError: {
code: -32000,
message: 'err: intrinsic gas too low: have 0, want 21544 (supplied gas 0)'
},
code: 101,
data: undefined
}
keep in mind that this method is now an internal method to be used by devs to further process why transactions failed before returning an error to the end user with more context
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also it can be generic error like :
throw new InvalidResponseError({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jdevcs That's a good point. I think the error in the chunk parser should remain InvalidResponseError
, but errors like the gas too low from above should be renamed to something like RpcError
. The gas too low isn't an InvalidResponse
it's just an error returned from the EVM because the transaction was invalid
If you agree, I can create an issue for it, merge this PR, then make the error name change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure. Good work @spacesailor24
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good, Thanks Wyatt. I posted a change for getRevertReason return behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great Job, Thx!
web3-eth-abi
Added
decodeErrorData
fromweb3-eth-contract
is now exported from this package and was renamed todecodeContractErrorData
(RefactorgetRevertReason
and add tests #5844)web3-eth-contract
Removed
decodeErrorData
is no longer exported (method was moved toweb3-eth-abi
and renameddecodeContractErrorData
) (RefactorgetRevertReason
and add tests #5844)web3-eth
Removed
getRevertReason
is no longer exported (RefactorgetRevertReason
and add tests #5844)web3-utils
Changed
SocketProvider
abstract class now resolves JSON RPC response errors instead of rejecting them (RefactorgetRevertReason
and add tests #5844)closes #5841 #5838