From 4ad1278cf412fe64558d62a2e24657fb73a10c77 Mon Sep 17 00:00:00 2001 From: Wyatt Barnes Date: Mon, 29 Aug 2022 17:54:20 -1000 Subject: [PATCH 1/4] Update contract class to not mutate options object --- packages/web3-eth-contract/src/index.js | 17 +++++++++-------- test/contract.js | 12 ++++++++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/web3-eth-contract/src/index.js b/packages/web3-eth-contract/src/index.js index c04758d22ea..6ee2b25e30c 100644 --- a/packages/web3-eth-contract/src/index.js +++ b/packages/web3-eth-contract/src/index.js @@ -379,19 +379,20 @@ Contract.prototype._checkListener = function(type, event){ * @return {Object} the options with gaps filled by defaults */ Contract.prototype._getOrSetDefaultOptions = function getOrSetDefaultOptions(options) { - var gasPrice = options.gasPrice ? String(options.gasPrice): null; - var from = options.from ? utils.toChecksumAddress(formatters.inputAddressFormatter(options.from)) : null; + var _options = { ...options }; + var gasPrice = _options.gasPrice ? String(_options.gasPrice): null; + var from = _options.from ? utils.toChecksumAddress(formatters.inputAddressFormatter(_options.from)) : null; - options.data = options.data || this.options.data; + _options.data = _options.data || this.options.data; - options.from = from || this.options.from; - options.gasPrice = gasPrice || this.options.gasPrice; - options.gas = options.gas || options.gasLimit || this.options.gas; + _options.from = from || this.options.from; + _options.gasPrice = gasPrice || this.options.gasPrice; + _options.gas = _options.gas || _options.gasLimit || this.options.gas; // TODO replace with only gasLimit? - delete options.gasLimit; + delete _options.gasLimit; - return options; + return _options; }; diff --git a/test/contract.js b/test/contract.js index 9a7fa16894d..53efa6d9201 100644 --- a/test/contract.js +++ b/test/contract.js @@ -3152,6 +3152,18 @@ var runTests = function(contractFactory) { describe('typical usage', function() { runTests(getEthContractInstance); + it('should not mutate options object', function () { + var provider = new FakeHttpProvider(); + + var eth = new Eth(provider); + var contract = new eth.Contract(abi, address); + var options = { from: address }; + var expectedOptions = { from: address }; + + contract.methods.balance(address).call(options); + assert.deepEqual(options, expectedOptions); + }); + it('should update contract instance provider when assigned a provider to eth instance that contract instance came from', function () { var provider1 = new FakeIpcProvider(); var provider2 = new FakeHttpProvider(); From 33da3dd3c481174cd5e655d905acaaebcaf0b4b8 Mon Sep 17 00:00:00 2001 From: Wyatt Barnes Date: Mon, 29 Aug 2022 18:04:15 -1000 Subject: [PATCH 2/4] Add .send test for options mutation test --- test/contract.js | 68 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/test/contract.js b/test/contract.js index 53efa6d9201..d44c0a2d126 100644 --- a/test/contract.js +++ b/test/contract.js @@ -5,6 +5,7 @@ var sha3 = require('../packages/web3-utils').sha3; var FakeIpcProvider = require('./helpers/FakeIpcProvider'); var FakeHttpProvider = require('./helpers/FakeHttpProvider'); var StandAloneContract = require('../packages/web3-eth-contract'); +const { done } = require('fetch-mock'); var abi = [{ "type": "constructor", @@ -3152,16 +3153,75 @@ var runTests = function(contractFactory) { describe('typical usage', function() { runTests(getEthContractInstance); - it('should not mutate options object', function () { + it('should not mutate options object - call', function (done) { var provider = new FakeHttpProvider(); + provider.injectResult('0x0000000000000000000000000000000000000000000000000000000000000032'); + var eth = new Eth(provider); var contract = new eth.Contract(abi, address); var options = { from: address }; - var expectedOptions = { from: address }; + var expectedOptions = { ...options }; + + contract.methods.balance(address).call(options) + .then(function () { + assert.deepEqual(options, expectedOptions); + done(); + }); + }); + + it('should not mutate options object - send', function (done) { + var provider = new FakeHttpProvider(); + + provider.injectResult('0x1234000000000000000000000000000000000000000000000000000000056789'); + provider.injectResult({ + contractAddress: null, + cumulativeGasUsed: '0xa', + transactionIndex: '0x3', + transactionHash: '0x1234', + blockNumber: '0xa', + blockHash: '0x1234', + gasUsed: '0x0', + logs: [{ + address: address, + topics: [ + sha3('Unchanged(uint256,address,uint256)'), + '0x0000000000000000000000000000000000000000000000000000000000000002', + '0x000000000000000000000000'+ addressLowercase.replace('0x','') + ], + blockNumber: '0xa', + transactionHash: '0x1234', + transactionIndex: '0x0', + blockHash: '0x1345', + logIndex: '0x4', + data: '0x0000000000000000000000000000000000000000000000000000000000000005' + },{ + address: address, + topics: [ + sha3('Changed(address,uint256,uint256,uint256)'), + '0x000000000000000000000000'+ addressLowercase.replace('0x',''), + '0x0000000000000000000000000000000000000000000000000000000000000001' + ], + blockNumber: '0xa', + transactionHash: '0x1234', + transactionIndex: '0x0', + blockHash: '0x1345', + logIndex: '0x4', + data: '0x0000000000000000000000000000000000000000000000000000000000000001' + + '0000000000000000000000000000000000000000000000000000000000000008' + }] + }); - contract.methods.balance(address).call(options); - assert.deepEqual(options, expectedOptions); + var eth = new Eth(provider); + var contract = new eth.Contract(abi, address); + var options = { from: address, gasPrice: '21345678654321' }; + var expectedOptions = { ...options }; + + contract.methods.mySend(address, 10).send(options) + .on('receipt', function () { + assert.deepEqual(options, expectedOptions); + done(); + }); }); it('should update contract instance provider when assigned a provider to eth instance that contract instance came from', function () { From c30077c7a7f5f7efab826ea23c1fe4377db0dfc1 Mon Sep 17 00:00:00 2001 From: Wyatt Barnes Date: Mon, 29 Aug 2022 18:04:28 -1000 Subject: [PATCH 3/4] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 017b0d7c6e8..163b86ef7fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -593,3 +593,4 @@ Released with 1.0.0-beta.37 code base. ### Fixed - Browser builds support polyfills (#5031) (#5053) (#4659) (#4767) - Start incrementing jsonrpc.id from random number (#5327) +- `web3-eth-contract`'s `call` and `send` methods no longer mutate `options` argument (#5394) From 763417e25502c09e7f85c77f86377a20343784be Mon Sep 17 00:00:00 2001 From: Wyatt Barnes Date: Mon, 29 Aug 2022 18:08:15 -1000 Subject: [PATCH 4/4] Remove errounous import --- test/contract.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/contract.js b/test/contract.js index d44c0a2d126..33675d39c3b 100644 --- a/test/contract.js +++ b/test/contract.js @@ -5,7 +5,6 @@ var sha3 = require('../packages/web3-utils').sha3; var FakeIpcProvider = require('./helpers/FakeIpcProvider'); var FakeHttpProvider = require('./helpers/FakeHttpProvider'); var StandAloneContract = require('../packages/web3-eth-contract'); -const { done } = require('fetch-mock'); var abi = [{ "type": "constructor",