From b38f00dc02fa60e23d24d5e99137e1afa003f059 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Thu, 12 Oct 2023 17:00:05 +0200 Subject: [PATCH 1/4] getRevertReason update for signed Txs (#6497) * checkRevertBeforeSending without v r s part * unit test * changelog * linter fix --- packages/web3-eth/CHANGELOG.md | 1 + packages/web3-eth/src/rpc_method_wrappers.ts | 5 ++- .../send_signed_transaction.test.ts | 37 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 8ebcda52b5f..9a0c99f76f2 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -200,6 +200,7 @@ Documentation: ### Fixed - Ensure provider.supportsSubscriptions exists before watching by subscription (#6440) +- Fixed param sent to `checkRevertBeforeSending` in `sendSignedTransaction` ### Added diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 542b1b36d88..9a36f2dc405 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -627,8 +627,11 @@ export function sendSignedTransaction< }; try { + const { v , r , s, + ...txWithoutSigParams} = unSerializedTransactionWithFrom; + await sendTxHelper.checkRevertBeforeSending( - unSerializedTransactionWithFrom as TransactionCall, + txWithoutSigParams as TransactionCall, ); sendTxHelper.emitSending(signedTransactionFormattedHex); diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/send_signed_transaction.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/send_signed_transaction.test.ts index 9cdb71a7019..4a741c46646 100644 --- a/packages/web3-eth/test/unit/rpc_method_wrappers/send_signed_transaction.test.ts +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/send_signed_transaction.test.ts @@ -28,6 +28,7 @@ import { testData, } from './fixtures/send_signed_transaction'; import { transactionReceiptSchema } from '../../../src/schemas'; +import { SendTxHelper } from '../../../src/utils/send_tx_helper'; jest.mock('web3-rpc-methods'); jest.mock('../../../src/utils/wait_for_transaction_receipt'); @@ -45,6 +46,42 @@ describe('sendTransaction', () => { afterEach(() => jest.resetAllMocks()); + it.each(testData)( + `should remove signature part in transaction before checkRevertBeforeSending`, + async (_, inputSignedTransaction) => { + ( + WaitForTransactionReceipt.waitForTransactionReceipt as jest.Mock + ).mockResolvedValueOnce(expectedTransactionReceipt); + + const checkRevertBeforeSendingSpy = jest.fn().mockImplementation((transaction) => { + expect(transaction).toBeDefined(); + + // verify signature part is removed before sending to revert check function + expect(transaction).not.toHaveProperty('v'); + expect(transaction).not.toHaveProperty('r'); + expect(transaction).not.toHaveProperty('s'); + }); + + SendTxHelper.prototype.checkRevertBeforeSending = checkRevertBeforeSendingSpy; + + const inputSignedTransactionFormatted = format( + { format: 'bytes' }, + inputSignedTransaction, + DEFAULT_RETURN_FORMAT, + ); + await sendSignedTransaction(web3Context, inputSignedTransaction, DEFAULT_RETURN_FORMAT); + + // verify original tx params are intact + expect(ethRpcMethods.sendRawTransaction).toHaveBeenCalledWith( + web3Context.requestManager, + inputSignedTransactionFormatted, + ); + + expect(checkRevertBeforeSendingSpy).toHaveBeenCalledTimes(1); + + }, + ); + it.each(testData)( `sending event should emit with inputSignedTransaction\n ${testMessage}`, async (_, inputSignedTransaction) => { From 6e43d1b78940d795c22d62fc431e09d10ffcab92 Mon Sep 17 00:00:00 2001 From: xiaolou86 <20718693+xiaolou86@users.noreply.github.com> Date: Fri, 13 Oct 2023 02:08:51 +0800 Subject: [PATCH 2/4] Fix typos (#6494) --- .../guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md | 4 ++-- docs/src/theme/SearchBar/algolia.css | 2 +- packages/web3-eth/test/e2e/e2e_utils.ts | 2 +- packages/web3/test/e2e/e2e_utils.ts | 2 +- scripts/test-runner.sh | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md b/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md index e97578d1c84..10b57e1d261 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md +++ b/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md @@ -176,7 +176,7 @@ await web3.eth.getFeeHistory('0x1', 'latest', []); #### sending -- In 1.x, the event listener would receive a `payload` object as an argument. In 4.x, just the sent transaction object is recieved +- In 1.x, the event listener would receive a `payload` object as an argument. In 4.x, just the sent transaction object is received ```typescript // in 1.x @@ -211,7 +211,7 @@ web3.eth.sendTransaction({ ... }).on('sending', (sendTransactionObject) => { ... #### sent -- In 1.x, the event listener would receive a `payload` object as an argument. In 4.x just the sent transaction object is recieved +- In 1.x, the event listener would receive a `payload` object as an argument. In 4.x just the sent transaction object is received ```typescript // in 1.x diff --git a/docs/src/theme/SearchBar/algolia.css b/docs/src/theme/SearchBar/algolia.css index c5590cfa486..8c3782ba827 100644 --- a/docs/src/theme/SearchBar/algolia.css +++ b/docs/src/theme/SearchBar/algolia.css @@ -10,7 +10,7 @@ .algolia-docsearch-suggestion--highlight { color: #3a33d1; } -/* Highligted search terms in the main category headers */ +/* Highlighted search terms in the main category headers */ .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--highlight { background-color: #4d47d5; diff --git a/packages/web3-eth/test/e2e/e2e_utils.ts b/packages/web3-eth/test/e2e/e2e_utils.ts index 6cc6d49e60e..56989fc927d 100644 --- a/packages/web3-eth/test/e2e/e2e_utils.ts +++ b/packages/web3-eth/test/e2e/e2e_utils.ts @@ -28,7 +28,7 @@ import { getSystemTestBackend } from '../fixtures/system_test_utils'; import secrets from '../../../../.secrets.json'; export const getSystemE2ETestProvider = (): string => { - if (process.env.WEB3_SYTEM_TEST_MODE === 'http') { + if (process.env.WEB3_SYSTEM_TEST_MODE === 'http') { return getSystemTestBackend() === 'sepolia' ? process.env.INFURA_SEPOLIA_HTTP ?? secrets.SEPOLIA.HTTP : process.env.INFURA_MAINNET_HTTP ?? secrets.MAINNET.HTTP; diff --git a/packages/web3/test/e2e/e2e_utils.ts b/packages/web3/test/e2e/e2e_utils.ts index 8001e72fc55..cfb680d8b81 100644 --- a/packages/web3/test/e2e/e2e_utils.ts +++ b/packages/web3/test/e2e/e2e_utils.ts @@ -28,7 +28,7 @@ import { getSystemTestBackend } from '../shared_fixtures/system_tests_utils'; import secrets from '../../../../.secrets.json'; export const getSystemE2ETestProvider = (): string => { - if (process.env.WEB3_SYTEM_TEST_MODE === 'http') { + if (process.env.WEB3_SYSTEM_TEST_MODE === 'http') { return getSystemTestBackend() === 'sepolia' ? process.env.INFURA_SEPOLIA_HTTP ?? secrets.SEPOLIA.HTTP : process.env.INFURA_MAINNET_HTTP ?? secrets.MAINNET.HTTP; diff --git a/scripts/test-runner.sh b/scripts/test-runner.sh index 5b60f75b59f..cdb3798e461 100755 --- a/scripts/test-runner.sh +++ b/scripts/test-runner.sh @@ -38,7 +38,7 @@ fi echo "Node software used for tests: " $BACKEND echo "Node running on: " "$MODE://127.0.0.1:$WEB3_SYSTEM_TEST_PORT" -export WEB3_SYTEM_TEST_MODE=$MODE +export WEB3_SYSTEM_TEST_MODE=$MODE export WEB3_SYSTEM_TEST_PROVIDER="$MODE://127.0.0.1:$WEB3_SYSTEM_TEST_PORT" export WEB3_SYSTEM_TEST_BACKEND=$BACKEND export WEB3_SYSTEM_TEST_ENGINE=$ENGINE From e760667d2595deafcf7606c84b15bda9b472c5a7 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 12 Oct 2023 21:56:40 -0400 Subject: [PATCH 3/4] update tests (#6474) --- .../integration/local_account/contract_erc721.test.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/web3-eth-contract/test/integration/local_account/contract_erc721.test.ts b/packages/web3-eth-contract/test/integration/local_account/contract_erc721.test.ts index 2b50e735257..d9226c580f1 100644 --- a/packages/web3-eth-contract/test/integration/local_account/contract_erc721.test.ts +++ b/packages/web3-eth-contract/test/integration/local_account/contract_erc721.test.ts @@ -19,7 +19,6 @@ along with web3.js. If not, see . import Web3 from 'web3'; // eslint-disable-next-line import/no-extraneous-dependencies import { Web3Account } from 'web3-eth-accounts'; -import { EventLog } from 'web3-types'; import { Contract } from '../../../src'; import { ERC721TokenAbi, ERC721TokenBytecode } from '../../shared_fixtures/build/ERC721Token'; import { getSystemTestProvider, createLocalAccount } from '../../fixtures/system_test_utils'; @@ -80,8 +79,7 @@ describe('contract', () => { tempAccount.address.toLowerCase(), ); - const logs = await contractDeployed.getPastEvents('Transfer'); - const tokenId = (logs[0] as EventLog)?.returnValues?.tokenId as string; + const tokenId = awardReceipt.events?.Transfer.returnValues?.tokenId as string; expect( toUpperCaseHex( @@ -113,8 +111,7 @@ describe('contract', () => { tempAccount.address.toLowerCase(), ); - const logs = await contractDeployed.getPastEvents('Transfer'); - const tokenId = (logs[0] as EventLog)?.returnValues?.tokenId as string; + const tokenId = awardReceipt.events?.Transfer.returnValues?.tokenId as string; const transferFromReceipt = await contractDeployed.methods .transferFrom(tempAccount.address, toAccount.address, tokenId) .send({ @@ -186,8 +183,7 @@ describe('contract', () => { tempAccount.address.toLowerCase(), ); - const logs = await contractDeployed.getPastEvents('Transfer'); - const tokenId = (logs[0] as EventLog)?.returnValues?.tokenId as string; + const tokenId = awardReceipt.events?.Transfer.returnValues?.tokenId as string; const approveReceipt = await contractDeployed.methods .approve(toAccount.address, tokenId) From 42502b6599c3c8149721a5679fcbf56c79deeebd Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Mon, 16 Oct 2023 12:56:11 +0200 Subject: [PATCH 4/4] Avoid using `**` with `BigInt` (#6506) * user static numbers to avoid `**` at web3-utils converters.ts * fill `numberLimits` in a loop without using ** * implement `bigintPower` to avoid `**` with `bigint` * update CHANGELOG.md files --- packages/web3-eth-abi/CHANGELOG.md | 6 +- .../web3-eth-abi/src/coders/base/number.ts | 20 +------ .../src/coders/base/numbersLimits.ts | 39 +++++++++++++ packages/web3-utils/CHANGELOG.md | 3 +- packages/web3-utils/src/converters.ts | 56 +++++++++---------- .../web3-utils/src/string_manipulation.ts | 6 +- packages/web3-validator/CHANGELOG.md | 3 +- .../web3-validator/src/validation/numbers.ts | 17 +++++- 8 files changed, 93 insertions(+), 57 deletions(-) create mode 100644 packages/web3-eth-abi/src/coders/base/numbersLimits.ts diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 908a451032e..0765c91d578 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -142,4 +142,8 @@ Documentation: - Dependencies updated -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Fixed + +- Fix issue with default config with babel (and React): "TypeError: Cannot convert a BigInt value to a number #6187" (#6506) diff --git a/packages/web3-eth-abi/src/coders/base/number.ts b/packages/web3-eth-abi/src/coders/base/number.ts index 317ecd3780f..a86ee4f6acd 100644 --- a/packages/web3-eth-abi/src/coders/base/number.ts +++ b/packages/web3-eth-abi/src/coders/base/number.ts @@ -21,6 +21,7 @@ import { padLeft, toBigInt } from 'web3-utils'; import { utils } from 'web3-validator'; import { DecoderResult, EncoderResult } from '../types.js'; import { WORD_SIZE } from '../utils.js'; +import { numberLimits } from './numbersLimits.js'; // eslint-disable-next-line no-bitwise const mask = BigInt(1) << BigInt(256); @@ -43,25 +44,6 @@ function uint8ArrayToBigInt(value: Uint8Array, max: bigint): bigint { return result - mask; } -const numberLimits = new Map(); - -// precalculate all the limits -for (let i = 8; i <= 256; i += 8) { - numberLimits.set(`uint${i}`, { - min: BigInt(0), - max: BigInt(2) ** BigInt(i) - BigInt(1), - }); - numberLimits.set(`int${i}`, { - min: -(BigInt(2) ** BigInt(i - 1)), - max: BigInt(2) ** BigInt(i - 1) - BigInt(1), - }); -} - -// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -numberLimits.set(`int`, numberLimits.get('int256')!); -// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -numberLimits.set(`uint`, numberLimits.get('uint256')!); - export function encodeNumber(param: AbiParameter, input: unknown): EncoderResult { let value; try { diff --git a/packages/web3-eth-abi/src/coders/base/numbersLimits.ts b/packages/web3-eth-abi/src/coders/base/numbersLimits.ts new file mode 100644 index 00000000000..29f11462843 --- /dev/null +++ b/packages/web3-eth-abi/src/coders/base/numbersLimits.ts @@ -0,0 +1,39 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +/* + * this variable contains the precalculated limits for all the numbers for uint and int types +*/ +export const numberLimits = new Map(); + +let base = BigInt(256); // 2 ^ 8 = 256 +for (let i = 8; i <= 256; i += 8) { + numberLimits.set(`uint${i}`, { + min: BigInt(0), + max: base - BigInt(1), + }); + numberLimits.set(`int${i}`, { + min: -base / BigInt(2), + max: base / BigInt(2) - BigInt(1), + }); + base *= BigInt(256); +} + +// eslint-disable-next-line @typescript-eslint/no-non-null-assertion +numberLimits.set(`int`, numberLimits.get('int256')!); +// eslint-disable-next-line @typescript-eslint/no-non-null-assertion +numberLimits.set(`uint`, numberLimits.get('uint256')!); diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 5db90f9426b..c46f98df69f 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -162,4 +162,5 @@ Documentation: ### Added -- As a replacment of the node EventEmitter, a custom `EventEmitter` has been implemented and exported. (#6398) +- As a replacement of the node EventEmitter, a custom `EventEmitter` has been implemented and exported. (#6398) +- Fix issue with default config with babel (and React): "TypeError: Cannot convert a BigInt value to a number #6187" (#6506) diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts index eed4e5caa1a..4e5f8592f77 100644 --- a/packages/web3-utils/src/converters.ts +++ b/packages/web3-utils/src/converters.ts @@ -38,39 +38,37 @@ import { InvalidUnitError, } from 'web3-errors'; -const base = BigInt(10); -const expo10 = (expo: number) => base ** BigInt(expo); - // Ref: https://ethdocs.org/en/latest/ether.html +// Note: this could be simplified using ** operator, but babel does not handle it well (https://github.com/babel/babel/issues/13109) /** @internal */ export const ethUnitMap = { - noether: BigInt('0'), + noether: BigInt(0), wei: BigInt(1), - kwei: expo10(3), - Kwei: expo10(3), - babbage: expo10(3), - femtoether: expo10(3), - mwei: expo10(6), - Mwei: expo10(6), - lovelace: expo10(6), - picoether: expo10(6), - gwei: expo10(9), - Gwei: expo10(9), - shannon: expo10(9), - nanoether: expo10(9), - nano: expo10(9), - szabo: expo10(12), - microether: expo10(12), - micro: expo10(12), - finney: expo10(15), - milliether: expo10(15), - milli: expo10(15), - ether: expo10(18), - kether: expo10(21), - grand: expo10(21), - mether: expo10(24), - gether: expo10(27), - tether: expo10(30), + kwei: BigInt(1000), + Kwei: BigInt(1000), + babbage: BigInt(1000), + femtoether: BigInt(1000), + mwei: BigInt(1000000), + Mwei: BigInt(1000000), + lovelace: BigInt(1000000), + picoether: BigInt(1000000), + gwei: BigInt(1000000000), + Gwei: BigInt(1000000000), + shannon: BigInt(1000000000), + nanoether: BigInt(1000000000), + nano: BigInt(1000000000), + szabo: BigInt(1000000000000), + microether: BigInt(1000000000000), + micro: BigInt(1000000000000), + finney: BigInt(1000000000000000), + milliether: BigInt(1000000000000000), + milli: BigInt(1000000000000000), + ether: BigInt('1000000000000000000'), + kether: BigInt('1000000000000000000000'), + grand: BigInt('1000000000000000000000'), + mether: BigInt('1000000000000000000000000'), + gether: BigInt('1000000000000000000000000000'), + tether: BigInt('1000000000000000000000000000000'), }; export type EtherUnits = keyof typeof ethUnitMap; diff --git a/packages/web3-utils/src/string_manipulation.ts b/packages/web3-utils/src/string_manipulation.ts index 7719afeba42..b7d0371d0b1 100644 --- a/packages/web3-utils/src/string_manipulation.ts +++ b/packages/web3-utils/src/string_manipulation.ts @@ -17,7 +17,7 @@ along with web3.js. If not, see . import { Numbers } from 'web3-types'; import { NibbleWidthError } from 'web3-errors'; -import { isHexStrict, validator, utils as validatorUtils } from 'web3-validator'; +import { isHexStrict, validator, utils as validatorUtils, bigintPower } from 'web3-validator'; import { numberToHex, toHex, toNumber } from './converters.js'; /** @@ -115,7 +115,7 @@ export const toTwosComplement = (value: Numbers, nibbleWidth = 64): string => { if (val >= 0) return padLeft(toHex(val), nibbleWidth); - const largestBit = BigInt(2) ** BigInt(nibbleWidth * 4); + const largestBit = bigintPower(BigInt(2), BigInt(nibbleWidth * 4)); if (-val >= largestBit) { throw new NibbleWidthError(`value: ${value}, nibbleWidth: ${nibbleWidth}`); } @@ -156,7 +156,7 @@ export const fromTwosComplement = (value: Numbers, nibbleWidth = 64): number | b // check the largest bit to see if negative if (nibbleWidth * 4 !== largestBit) return val; - const complement = BigInt(2) ** (BigInt(nibbleWidth) * BigInt(4)); + const complement = bigintPower(BigInt(2), BigInt(nibbleWidth) * BigInt(4)); return toNumber(BigInt(val) - complement); }; diff --git a/packages/web3-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md index fea00e98075..54cfe6080fd 100644 --- a/packages/web3-validator/CHANGELOG.md +++ b/packages/web3-validator/CHANGELOG.md @@ -151,4 +151,5 @@ Documentation: ## Fixed -- Multi-dimensional arrays are now handled properly when parsing ABIs +- Multi-dimensional arrays are now handled properly when parsing ABIs (#6435) +- Fix issue with default config with babel (and React): "TypeError: Cannot convert a BigInt value to a number #6187" (#6506) diff --git a/packages/web3-validator/src/validation/numbers.ts b/packages/web3-validator/src/validation/numbers.ts index 5ad606a5fe2..276fb84dd1e 100644 --- a/packages/web3-validator/src/validation/numbers.ts +++ b/packages/web3-validator/src/validation/numbers.ts @@ -24,6 +24,17 @@ import { isHexStrict } from './string.js'; */ export const isBigInt = (value: ValidInputTypes): boolean => typeof value === 'bigint'; +// Note: this could be simplified using ** operator, but babel does not handle it well +// you can find more at: https://github.com/babel/babel/issues/13109 and https://github.com/web3/web3.js/issues/6187 +/** @internal */ +export const bigintPower = (base: bigint, expo: bigint) => { + let res = base; + for (let index = 1; index < expo; index += 1) { + res *= base; + } + return res; +}; + export const isUInt = ( value: ValidInputTypes, options: { abiType: string; bitSize?: never } | { bitSize: number; abiType?: never } = { @@ -49,7 +60,7 @@ export const isUInt = ( size = options.bitSize; } - const maxSize = BigInt(2) ** BigInt(size ?? 256) - BigInt(1); + const maxSize = bigintPower(BigInt(2), BigInt(size ?? 256)) - BigInt(1); try { const valueToCheck = @@ -94,8 +105,8 @@ export const isInt = ( size = options.bitSize; } - const maxSize = BigInt(2) ** BigInt((size ?? 256) - 1); - const minSize = BigInt(-1) * BigInt(2) ** BigInt((size ?? 256) - 1); + const maxSize = bigintPower(BigInt(2), BigInt((size ?? 256) - 1)); + const minSize = BigInt(-1) * bigintPower(BigInt(2), BigInt((size ?? 256) - 1)); try { const valueToCheck =