From d230def639fee35a726ce2a895e0c23db9985651 Mon Sep 17 00:00:00 2001 From: cgewecke Date: Tue, 10 Nov 2020 11:26:09 -0800 Subject: [PATCH] Set network "from" / fix HH trace logic --- lib/api.js | 5 +- lib/collector.js | 2 +- plugins/hardhat.plugin.js | 4 +- plugins/resources/nomiclabs.utils.js | 15 ++- test/sources/js/account-one.js | 9 ++ test/sources/js/account-zero.js | 9 ++ .../sources/solidity/contracts/app/Simple.sol | 4 +- test/units/hardhat/standard.js | 91 ++++++++++++++++++- test/util/integration.js | 3 +- 9 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 test/sources/js/account-one.js create mode 100644 test/sources/js/account-zero.js diff --git a/lib/api.js b/lib/api.js index 3af504ff..ddcc620b 100644 --- a/lib/api.js +++ b/lib/api.js @@ -269,8 +269,9 @@ class API { } hardhatTraceHandler(trace, isTraceFromCall){ - if (trace.bytecode && trace.bytecode.instructions){ - for (const instruction of trace.bytecode.instructions){ + for (const step of trace.steps){ + if (trace.bytecode && trace.bytecode._pcToInstruction){ + const instruction = trace.bytecode._pcToInstruction.get(step.pc) this.collector.trackHardhatEVMInstruction(instruction) } } diff --git a/lib/collector.js b/lib/collector.js index 29a2a8a9..7c4f2011 100644 --- a/lib/collector.js +++ b/lib/collector.js @@ -33,7 +33,7 @@ class DataCollector { * @param {HardhatEVMTraceInstruction} instruction */ trackHardhatEVMInstruction(instruction){ - if (instruction.pushData){ + if (instruction && instruction.pushData){ let hash = `0x` + instruction.pushData.toString('hex'); this._registerHash(hash) } diff --git a/plugins/hardhat.plugin.js b/plugins/hardhat.plugin.js index 021cf643..e50af4b2 100644 --- a/plugins/hardhat.plugin.js +++ b/plugins/hardhat.plugin.js @@ -162,8 +162,8 @@ async function plugin(args, env) { ]); } - // Set default account - network.from = accounts[0]; + // Set default account (if not already configured) + nomiclabsUtils.setNetworkFrom(network.config, accounts); // Run post-launch server hook; await api.onServerReady(config); diff --git a/plugins/resources/nomiclabs.utils.js b/plugins/resources/nomiclabs.utils.js index 24a3b2ba..67a16b7b 100644 --- a/plugins/resources/nomiclabs.utils.js +++ b/plugins/resources/nomiclabs.utils.js @@ -166,6 +166,18 @@ async function getNodeInfo(provider){ return provider.send("web3_clientVersion", []) } +/** + * Sets the default `from` account field in the network that will be used. + * This needs to be done after accounts are fetched from the launched client. + * @param {env} config + * @param {Array} accounts + */ +function setNetworkFrom(networkConfig, accounts){ + if (!networkConfig.from){ + networkConfig.from = accounts[0]; + } +} + // TODO: Hardhat cacheing?? /** * Generates a path to a temporary compilation cache directory @@ -205,6 +217,7 @@ module.exports = { setupHardhatNetwork: setupHardhatNetwork, getTestFilePaths: getTestFilePaths, getAccounts: getAccounts, - getNodeInfo: getNodeInfo + getNodeInfo: getNodeInfo, + setNetworkFrom: setNetworkFrom } diff --git a/test/sources/js/account-one.js b/test/sources/js/account-one.js new file mode 100644 index 00000000..9abcd287 --- /dev/null +++ b/test/sources/js/account-one.js @@ -0,0 +1,9 @@ +const Simple = artifacts.require('Simple'); + +contract('Simple', () => { + it('should use 0xe7a46b209a65baadc11bf973c0f4d5f19465ae83', async function(){ + const simple = await Simple.new() + const result = await simple.test(5); + assert.equal(result.receipt.from, "0xe7a46b209a65baadc11bf973c0f4d5f19465ae83") + }); +}); diff --git a/test/sources/js/account-zero.js b/test/sources/js/account-zero.js new file mode 100644 index 00000000..cae7e7bf --- /dev/null +++ b/test/sources/js/account-zero.js @@ -0,0 +1,9 @@ +const Simple = artifacts.require('Simple'); + +contract('Simple', () => { + it('should use 0x42ecc9ab31d7c0240532992682ee3533421dd7f5', async function(){ + const simple = await Simple.new() + const result = await simple.test(5); + assert.equal(result.receipt.from, "0x42ecc9ab31d7c0240532992682ee3533421dd7f5") + }); +}); diff --git a/test/sources/solidity/contracts/app/Simple.sol b/test/sources/solidity/contracts/app/Simple.sol index bfbd6d2e..2aee6270 100644 --- a/test/sources/solidity/contracts/app/Simple.sol +++ b/test/sources/solidity/contracts/app/Simple.sol @@ -2,9 +2,9 @@ pragma solidity ^0.5.3; contract Simple { uint x = 0; - + function test(uint val) public { - x = x + val; + x = x + val; } function getX() public view returns (uint){ diff --git a/test/units/hardhat/standard.js b/test/units/hardhat/standard.js index 445622c1..8d88aeb1 100644 --- a/test/units/hardhat/standard.js +++ b/test/units/hardhat/standard.js @@ -18,7 +18,10 @@ describe('Hardhat Plugin: standard use cases', function() { mock.clean(); mock.loggerOutput.val = ''; - solcoverConfig = { skipFiles: ['Migrations.sol']}; + solcoverConfig = { + skipFiles: ['Migrations.sol'], + istanbulReporter: [ "json-summary", "text"] + }; hardhatConfig = mock.getDefaultHardhatConfig(); verify.cleanInitialState(); }) @@ -287,7 +290,7 @@ describe('Hardhat Plugin: standard use cases', function() { const expected = [ { file: mock.pathToContract(hardhatConfig, 'ContractA.sol'), - pct: 92.31 + pct: 61.54 }, { file: mock.pathToContract(hardhatConfig, 'ContractB.sol'), @@ -295,7 +298,7 @@ describe('Hardhat Plugin: standard use cases', function() { }, { file: mock.pathToContract(hardhatConfig, 'B_Wallet.sol'), - pct: 100, + pct: 80, }, ]; @@ -310,4 +313,86 @@ describe('Hardhat Plugin: standard use cases', function() { await this.env.run("coverage"); }); + + it('uses account[0] as default "from" (ganache)', async function(){ + const mnemonic = "purity blame spice arm main narrow olive roof science verb parrot flash"; + const account0 = "0x42ecc9ab31d7c0240532992682ee3533421dd7f5" + const taskArgs = { + network: "development" + } + + solcoverConfig.providerOptions = { + mnemonic: mnemonic + }; + + mock.install('Simple', 'account-zero.js', solcoverConfig); + mock.hardhatSetupEnv(this); + + await this.env.run("coverage", taskArgs); + + const expected = [ + { + file: mock.pathToContract(hardhatConfig, 'Simple.sol'), + pct: 50 + } + ]; + + verify.lineCoverage(expected); + }) + + it('inherits network defined "from" (ganache)', async function(){ + const mnemonic = "purity blame spice arm main narrow olive roof science verb parrot flash"; + const account1 = "0xe7a46b209a65baadc11bf973c0f4d5f19465ae83" + const taskArgs = { + network: "development" + } + + solcoverConfig.providerOptions = { + mnemonic: mnemonic + }; + + const hardhatConfig = mock.getDefaultHardhatConfig() + hardhatConfig.networks.development.from = account1; + + mock.install('Simple', 'account-one.js', solcoverConfig, hardhatConfig); + mock.hardhatSetupEnv(this); + + await this.env.run("coverage", taskArgs); + + const expected = [ + { + file: mock.pathToContract(hardhatConfig, 'Simple.sol'), + pct: 50 + } + ]; + + verify.lineCoverage(expected); + }) + + it('inherits network defined "from" (hardhat)', async function(){ + const mnemonic = "purity blame spice arm main narrow olive roof science verb parrot flash"; + const account1 = "0xe7a46b209a65baadc11bf973c0f4d5f19465ae83" + + const hardhatConfig = mock.getDefaultHardhatConfig() + hardhatConfig.networks.hardhat = { + from: account1, + accounts: { + mnemonic: mnemonic + } + } + + mock.install('Simple', 'account-one.js', solcoverConfig, hardhatConfig); + mock.hardhatSetupEnv(this); + + await this.env.run("coverage"); + + const expected = [ + { + file: mock.pathToContract(hardhatConfig, 'Simple.sol'), + pct: 50 + } + ]; + + verify.lineCoverage(expected); + }) }) diff --git a/test/util/integration.js b/test/util/integration.js index f857c1e0..a6d82549 100644 --- a/test/util/integration.js +++ b/test/util/integration.js @@ -38,7 +38,8 @@ function decacheConfigs(){ `${process.cwd()}/${temp}/${buidlerConfigName}`, `${process.cwd()}/${temp}/${hardhatConfigName}`, `${process.cwd()}/${temp}/contracts/Simple.sol`, - `${process.cwd()}/${temp}/test/simple.js` + `${process.cwd()}/${temp}/test/simple.js`, + `${process.cwd()}/${temp}/test/account-one.js` ]; paths.forEach(pth => {