Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit 93070a7

Browse files
authored
add tx.chainId if tx.common.chainId not provided (#4293)
* add tx.chainId if tx.common not provided * tx.common.customChain.chainId checks * test: dnt look for chainId if common given * test: get ChainId if common not provided * change log * customChain is not optional in common * tx.common safety checks for runtime * formatting / readability * doc update
1 parent 7e10eb4 commit 93070a7

File tree

5 files changed

+84
-10
lines changed

5 files changed

+84
-10
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,5 @@ Released with 1.0.0-beta.37 code base.
450450
## [Unreleased]
451451

452452
## [1.5.4]
453+
### Changed
454+
- Not considering `tx.chainId` if `tx.common.customChain.chainId` is provided for `web3.eth.accounts.signTransaction` function (#4293)

docs/web3-eth-accounts.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ Parameters
151151

152152
1. ``tx`` - ``Object``: The transaction object as follows:
153153
- ``nonce`` - ``String``: (optional) The nonce to use when signing this transaction. Default will use :ref:`web3.eth.getTransactionCount() <eth-gettransactioncount>`.
154-
- ``chainId`` - ``String``: (optional) The chain id to use when signing this transaction. Default will use :ref:`web3.eth.net.getId() <net-getid>`.
154+
- ``chainId`` - ``String``: (optional) The chain id to use when signing this transaction. Default will use :ref:`web3.eth.net.getId() <net-getid>`. Web3 will ignore this field if `common.customChain.chainId` is provided.
155155
- ``to`` - ``String``: (optional) The recevier of the transaction, can be empty when deploying a contract.
156156
- ``data`` - ``String``: (optional) The call data of the transaction, can be empty for simple value transfers.
157157
- ``value`` - ``String``: (optional) The value of the transaction in wei.

packages/web3-eth-accounts/src/index.js

+36-7
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ var isNot = function(value) {
3939
return (typeof value === 'undefined') || value === null;
4040
};
4141

42+
var isExist = function(value) {
43+
return (typeof value !== 'undefined') && value !== null;
44+
};
45+
4246
var Accounts = function Accounts() {
4347
var _this = this;
4448

@@ -154,6 +158,27 @@ Accounts.prototype.signTransaction = function signTransaction(tx, privateKey, ca
154158
return Promise.reject(error);
155159
}
156160

161+
if (isExist(tx.common) && isNot(tx.common.customChain)) {
162+
error = new Error('If tx.common is provided it must have tx.common.customChain');
163+
164+
callback(error);
165+
return Promise.reject(error);
166+
}
167+
168+
if (isExist(tx.common) && isNot(tx.common.customChain.chainId)) {
169+
error = new Error('If tx.common is provided it must have tx.common.customChain and tx.common.customChain.chainId');
170+
171+
callback(error);
172+
return Promise.reject(error);
173+
}
174+
175+
if (isExist(tx.common) && isExist(tx.common.customChain.chainId) && isExist(tx.chainId) && tx.chainId !== tx.common.customChain.chainId) {
176+
error = new Error('Chain Id doesnt match in tx.chainId tx.common.customChain.chainId');
177+
178+
callback(error);
179+
return Promise.reject(error);
180+
}
181+
157182
function signed(tx) {
158183
const error = _validateTransactionForSigning(tx);
159184

@@ -264,21 +289,25 @@ Accounts.prototype.signTransaction = function signTransaction(tx, privateKey, ca
264289

265290
// Otherwise, get the missing info from the Ethereum Node
266291
return Promise.all([
267-
isNot(tx.chainId) ? _this._ethereumCall.getChainId() : tx.chainId,
292+
((isNot(tx.common) || isNot(tx.common.customChain.chainId)) ? //tx.common.customChain.chainId is not optional inside tx.common if tx.common is provided
293+
( isNot(tx.chainId) ? _this._ethereumCall.getChainId() : tx.chainId)
294+
: undefined ),
268295
isNot(tx.nonce) ? _this._ethereumCall.getTransactionCount(_this.privateKeyToAccount(privateKey).address) : tx.nonce,
269296
isNot(hasTxSigningOptions) ? _this._ethereumCall.getNetworkId() : 1,
270297
_handleTxPricing(_this, tx)
271298
]).then(function(args) {
272-
if (isNot(args[0]) || isNot(args[1]) || isNot(args[2]) || isNot(args[3])) {
299+
const [txchainId, txnonce, txnetworkId, txgasInfo] = args;
300+
301+
if ( (isNot(txchainId) && isNot(tx.common) && isNot(tx.common.customChain.chainId)) || isNot(txnonce) || isNot(txnetworkId) || isNot(txgasInfo)) {
273302
throw new Error('One of the values "chainId", "networkId", "gasPrice", or "nonce" couldn\'t be fetched: ' + JSON.stringify(args));
274303
}
275-
304+
276305
return signed({
277306
...tx,
278-
chainId: args[0],
279-
nonce: args[1],
280-
networkId: args[2],
281-
...args[3] // Will either be gasPrice or maxFeePerGas and maxPriorityFeePerGas
307+
... ((isNot(tx.common) || isNot(tx.common.customChain.chainId) ) ? {chainId: txchainId}:{}), // if common.customChain.chainId is provided no need to add tx.chainId
308+
nonce: txnonce,
309+
networkId: txnetworkId,
310+
...txgasInfo // Will either be gasPrice or maxFeePerGas and maxPriorityFeePerGas
282311
});
283312
});
284313
};

test/e2e.method.signing.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,13 @@ describe('transaction and message signing [ @E2E ]', function() {
281281
gasLimit: web3.utils.toHex(21000),
282282
gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
283283
chain: "ropsten",
284-
common: {},
284+
common: {
285+
customChain: {
286+
name: 'custom-network',
287+
networkId: 1,
288+
chainId: 1,
289+
}
290+
},
285291
hardfork: "istanbul"
286292
};
287293

test/eth.accounts.signTransaction.js

+38-1
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,42 @@ describe("eth", function () {
878878
});
879879

880880

881-
it("signTransaction will call for chainId", function(done) {
881+
it("signTransaction should not call for chainId if common.customChain.chainId provided", function(done) {
882+
var provider = new FakeHttpProvider();
883+
var web3 = new Web3(provider);
884+
885+
provider.injectResult(
886+
test.transaction.common.hardfork === 'london' ?
887+
postEip1559Block:
888+
preEip1559Block
889+
);
890+
provider.injectValidation(function (payload) {
891+
assert.equal(payload.jsonrpc, '2.0');
892+
assert.equal(payload.method, 'eth_getBlockByNumber');
893+
assert.deepEqual(payload.params, ['latest', false]);
894+
});
895+
896+
var ethAccounts = new Accounts(web3);
897+
898+
var testAccount = ethAccounts.privateKeyToAccount(test.privateKey);
899+
assert.equal(testAccount.address, test.address);
900+
901+
var transaction = clone(test.transaction);
902+
delete transaction.chainId;
903+
testAccount.signTransaction(transaction)
904+
.then(function (tx) {
905+
assert.isObject(tx);
906+
assert.isString(tx.rawTransaction);
907+
908+
done();
909+
})
910+
.catch(e => {
911+
console.log(i, e)
912+
done(e);
913+
});
914+
});
915+
916+
it("signTransaction should call for chainId if common.customChain.chainId not provided", function(done) {
882917
var provider = new FakeHttpProvider();
883918
var web3 = new Web3(provider);
884919

@@ -888,6 +923,7 @@ describe("eth", function () {
888923
assert.equal(payload.method, 'eth_chainId');
889924
assert.deepEqual(payload.params, []);
890925
});
926+
891927
provider.injectResult(
892928
test.transaction.common.hardfork === 'london' ?
893929
postEip1559Block:
@@ -906,6 +942,7 @@ describe("eth", function () {
906942

907943
var transaction = clone(test.transaction);
908944
delete transaction.chainId;
945+
delete transaction.common;
909946
testAccount.signTransaction(transaction)
910947
.then(function (tx) {
911948
assert.isObject(tx);

0 commit comments

Comments
 (0)