From b54d60f0f332a5b8af658bc22152b07502470c8f Mon Sep 17 00:00:00 2001 From: "justin j. moses" Date: Thu, 16 Apr 2020 16:29:42 -0400 Subject: [PATCH] Ensuring web3 is properly wrapped into testUtils --- test/contracts/AddressResolver.js | 2 +- test/contracts/DelegateApprovals.js | 2 +- test/contracts/Depot.js | 2 +- test/contracts/EtherCollateral.js | 2 +- test/contracts/ExchangeRates.js | 2 +- test/contracts/ExchangeState.js | 2 +- test/contracts/Exchanger.js | 2 +- test/contracts/ExternStateToken.js | 2 +- test/contracts/FeePool.js | 2 +- test/contracts/FeePoolState.js | 2 +- test/contracts/Issuer.js | 2 +- test/contracts/LimitedSetup.js | 2 +- test/contracts/Math.js | 2 +- test/contracts/MixinResolver.js | 2 +- test/contracts/MultiCollateralSynth.js | 2 +- test/contracts/Owned.js | 2 +- test/contracts/Pausable.js | 2 +- test/contracts/ProxyERC20.js | 2 +- test/contracts/PurgeableSynth.js | 2 +- test/contracts/RewardEscrow.js | 2 +- test/contracts/RewardsDistribution.js | 2 +- test/contracts/RewardsIntegrationTests.js | 2 +- test/contracts/SafeDecimalMath.js | 2 +- test/contracts/SelfDestructible.js | 2 +- test/contracts/SupplySchedule.js | 2 +- test/contracts/Synth.js | 2 +- test/contracts/Synthetix.js | 2 +- test/contracts/SynthetixState.js | 2 +- test/contracts/TokenState.js | 2 +- test/contracts/common.js | 2 +- test/contracts/helpers.js | 2 +- test/publish/index.js | 20 +- test/testnet/index.js | 9 +- test/utils/index.js | 911 +++++++++++----------- 34 files changed, 512 insertions(+), 490 deletions(-) diff --git a/test/contracts/AddressResolver.js b/test/contracts/AddressResolver.js index 88cf0c6773..bdc77cdfc5 100644 --- a/test/contracts/AddressResolver.js +++ b/test/contracts/AddressResolver.js @@ -6,7 +6,7 @@ const { assert } = require('./common'); const { toBytes32 } = require('../..'); const { onlyGivenAddressCanInvoke } = require('./helpers'); -const { ZERO_ADDRESS } = require('../utils'); +const { ZERO_ADDRESS } = require('../utils')(); const AddressResolver = artifacts.require('AddressResolver'); diff --git a/test/contracts/DelegateApprovals.js b/test/contracts/DelegateApprovals.js index 51bf6a0e86..e6405b4386 100644 --- a/test/contracts/DelegateApprovals.js +++ b/test/contracts/DelegateApprovals.js @@ -8,7 +8,7 @@ const EternalStorage = artifacts.require('EternalStorage'); const DelegateApprovals = artifacts.require('DelegateApprovals'); const { onlyGivenAddressCanInvoke, ensureOnlyExpectedMutativeFunctions } = require('./helpers'); const { toBytes32 } = require('../..'); -const { ZERO_ADDRESS } = require('../utils'); +const { ZERO_ADDRESS } = require('../utils')(); contract('DelegateApprovals', async accounts => { const [deployerAccount, owner, account1, account2, account3] = accounts; diff --git a/test/contracts/Depot.js b/test/contracts/Depot.js index 1f4c629d81..60169eae0f 100644 --- a/test/contracts/Depot.js +++ b/test/contracts/Depot.js @@ -11,7 +11,7 @@ const { toUnit, multiplyDecimal, divideDecimal, -} = require('../utils'); +} = require('../utils')(); const { onlyGivenAddressCanInvoke, diff --git a/test/contracts/EtherCollateral.js b/test/contracts/EtherCollateral.js index 48475eed6a..43815bbe59 100644 --- a/test/contracts/EtherCollateral.js +++ b/test/contracts/EtherCollateral.js @@ -6,7 +6,7 @@ const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); const BN = require('bn.js'); -const { fastForward, getEthBalance, toUnit, multiplyDecimal, currentTime } = require('../utils'); +const { fastForward, getEthBalance, toUnit, multiplyDecimal, currentTime } = require('../utils')(); const { mockToken, setupAllContracts } = require('./setup'); diff --git a/test/contracts/ExchangeRates.js b/test/contracts/ExchangeRates.js index b5c3384a3e..5d0516769e 100644 --- a/test/contracts/ExchangeRates.js +++ b/test/contracts/ExchangeRates.js @@ -4,7 +4,7 @@ const { artifacts, contract, web3 } = require('@nomiclabs/buidler'); const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); -const { currentTime, fastForward, toUnit, bytesToString, ZERO_ADDRESS } = require('../utils'); +const { currentTime, fastForward, toUnit, bytesToString, ZERO_ADDRESS } = require('../utils')(); const { ensureOnlyExpectedMutativeFunctions, onlyGivenAddressCanInvoke } = require('./helpers'); diff --git a/test/contracts/ExchangeState.js b/test/contracts/ExchangeState.js index c004a5d401..5615dc07f9 100644 --- a/test/contracts/ExchangeState.js +++ b/test/contracts/ExchangeState.js @@ -5,7 +5,7 @@ const { artifacts, contract } = require('@nomiclabs/buidler'); const { assert } = require('./common'); const { toBytes32 } = require('../..'); -const { toUnit } = require('../utils'); +const { toUnit } = require('../utils')(); const { onlyGivenAddressCanInvoke, ensureOnlyExpectedMutativeFunctions } = require('./helpers'); const { isBN } = require('web3-utils'); diff --git a/test/contracts/Exchanger.js b/test/contracts/Exchanger.js index 71b33d0826..9082e23a73 100644 --- a/test/contracts/Exchanger.js +++ b/test/contracts/Exchanger.js @@ -4,7 +4,7 @@ const { contract, web3 } = require('@nomiclabs/buidler'); const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); -const { currentTime, fastForward, multiplyDecimal, divideDecimal, toUnit } = require('../utils'); +const { currentTime, fastForward, multiplyDecimal, divideDecimal, toUnit } = require('../utils')(); const { setupAllContracts } = require('./setup'); diff --git a/test/contracts/ExternStateToken.js b/test/contracts/ExternStateToken.js index 351555f3cf..a874d08902 100644 --- a/test/contracts/ExternStateToken.js +++ b/test/contracts/ExternStateToken.js @@ -6,7 +6,7 @@ const ExternStateToken = artifacts.require('ExternStateToken'); const PublicEST = artifacts.require('PublicEST'); const ProxyERC20 = artifacts.require('ProxyERC20'); const TokenState = artifacts.require('TokenState'); -const { ZERO_ADDRESS, toUnit } = require('../utils'); +const { ZERO_ADDRESS, toUnit } = require('../utils')(); const { onlyGivenAddressCanInvoke, ensureOnlyExpectedMutativeFunctions } = require('./helpers'); diff --git a/test/contracts/FeePool.js b/test/contracts/FeePool.js index 12a269d86b..fdfed9d356 100644 --- a/test/contracts/FeePool.js +++ b/test/contracts/FeePool.js @@ -12,7 +12,7 @@ const { ZERO_ADDRESS, fromUnit, multiplyDecimal, -} = require('../utils'); +} = require('../utils')(); const { ensureOnlyExpectedMutativeFunctions, diff --git a/test/contracts/FeePoolState.js b/test/contracts/FeePoolState.js index 55fbe695d6..3491d5cc93 100644 --- a/test/contracts/FeePoolState.js +++ b/test/contracts/FeePoolState.js @@ -4,7 +4,7 @@ const { artifacts, contract } = require('@nomiclabs/buidler'); const { assert } = require('./common'); -const { toPreciseUnit, toUnit } = require('../utils'); +const { toPreciseUnit, toUnit } = require('../utils')(); const { onlyGivenAddressCanInvoke, ensureOnlyExpectedMutativeFunctions } = require('./helpers'); const FeePoolState = artifacts.require('FeePoolState'); diff --git a/test/contracts/Issuer.js b/test/contracts/Issuer.js index 9f7ab90d5b..310155d026 100644 --- a/test/contracts/Issuer.js +++ b/test/contracts/Issuer.js @@ -6,7 +6,7 @@ const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); const { setupAllContracts } = require('./setup'); -const { currentTime, multiplyDecimal, divideDecimal, toUnit, fastForward } = require('../utils'); +const { currentTime, multiplyDecimal, divideDecimal, toUnit, fastForward } = require('../utils')(); const { setExchangeWaitingPeriod, diff --git a/test/contracts/LimitedSetup.js b/test/contracts/LimitedSetup.js index fff7ee0ced..4058550b0d 100644 --- a/test/contracts/LimitedSetup.js +++ b/test/contracts/LimitedSetup.js @@ -4,7 +4,7 @@ const { artifacts, contract } = require('@nomiclabs/buidler'); const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); -const { currentTime, fastForward } = require('../utils'); +const { currentTime, fastForward } = require('../utils')(); const { timeIsClose } = require('./helpers'); const OneWeekSetup = artifacts.require('OneWeekSetup'); diff --git a/test/contracts/Math.js b/test/contracts/Math.js index 0e06cf41c2..eb92e0440c 100644 --- a/test/contracts/Math.js +++ b/test/contracts/Math.js @@ -7,7 +7,7 @@ const { assert } = require('./common'); const SafeDecimalMath = artifacts.require('SafeDecimalMath'); const PublicMath = artifacts.require('PublicMath'); -const { toUnit } = require('../utils'); +const { toUnit } = require('../utils')(); const { toBN } = web3.utils; diff --git a/test/contracts/MixinResolver.js b/test/contracts/MixinResolver.js index 12481a5c3d..4a041a9163 100644 --- a/test/contracts/MixinResolver.js +++ b/test/contracts/MixinResolver.js @@ -7,7 +7,7 @@ const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); const MixinResolver = artifacts.require('MixinResolver'); const AddressResolver = artifacts.require('AddressResolver'); -const { ZERO_ADDRESS } = require('../utils'); +const { ZERO_ADDRESS } = require('../utils')(); const { onlyGivenAddressCanInvoke, ensureOnlyExpectedMutativeFunctions } = require('./helpers'); diff --git a/test/contracts/MultiCollateralSynth.js b/test/contracts/MultiCollateralSynth.js index 8c90767580..f08fd2c65f 100644 --- a/test/contracts/MultiCollateralSynth.js +++ b/test/contracts/MultiCollateralSynth.js @@ -9,7 +9,7 @@ const TokenState = artifacts.require('TokenState'); const Proxy = artifacts.require('Proxy'); const { onlyGivenAddressCanInvoke, ensureOnlyExpectedMutativeFunctions } = require('./helpers'); -const { toUnit, ZERO_ADDRESS } = require('../utils'); +const { toUnit, ZERO_ADDRESS } = require('../utils')(); const { toBytes32 } = require('../..'); const { setupAllContracts } = require('./setup'); diff --git a/test/contracts/Owned.js b/test/contracts/Owned.js index c283dc52e4..d6121a87df 100644 --- a/test/contracts/Owned.js +++ b/test/contracts/Owned.js @@ -5,7 +5,7 @@ const { artifacts, contract } = require('@nomiclabs/buidler'); const { assert } = require('./common'); const Owned = artifacts.require('Owned'); -const { ZERO_ADDRESS } = require('../utils'); +const { ZERO_ADDRESS } = require('../utils')(); contract('Owned', accounts => { const [deployerAccount, account1, account2, account3, account4] = accounts; diff --git a/test/contracts/Pausable.js b/test/contracts/Pausable.js index 4e890c0ebc..a1938d7b89 100644 --- a/test/contracts/Pausable.js +++ b/test/contracts/Pausable.js @@ -9,7 +9,7 @@ const { timeIsClose, ensureOnlyExpectedMutativeFunctions, } = require('./helpers'); -const { currentTime, fastForward } = require('../utils'); +const { currentTime, fastForward } = require('../utils')(); const Pausable = artifacts.require('Pausable'); const TestablePausable = artifacts.require('TestablePausable'); diff --git a/test/contracts/ProxyERC20.js b/test/contracts/ProxyERC20.js index c54041a54e..81611cf754 100644 --- a/test/contracts/ProxyERC20.js +++ b/test/contracts/ProxyERC20.js @@ -8,7 +8,7 @@ const TokenExchanger = artifacts.require('TokenExchanger'); const { toBytes32 } = require('../..'); const { mockToken } = require('./setup'); -const { toUnit } = require('../utils'); +const { toUnit } = require('../utils')(); const { ensureOnlyExpectedMutativeFunctions, proxyThruTo } = require('./helpers'); contract('ProxyERC20', async accounts => { diff --git a/test/contracts/PurgeableSynth.js b/test/contracts/PurgeableSynth.js index 9de1443dd4..591f03dd22 100644 --- a/test/contracts/PurgeableSynth.js +++ b/test/contracts/PurgeableSynth.js @@ -8,7 +8,7 @@ const PurgeableSynth = artifacts.require('PurgeableSynth'); const TokenState = artifacts.require('TokenState'); const Proxy = artifacts.require('Proxy'); -const { currentTime, toUnit, ZERO_ADDRESS } = require('../utils'); +const { currentTime, toUnit, ZERO_ADDRESS } = require('../utils')(); const { toBytes32 } = require('../..'); const { diff --git a/test/contracts/RewardEscrow.js b/test/contracts/RewardEscrow.js index 7b8c615ea3..e4e61ddc99 100644 --- a/test/contracts/RewardEscrow.js +++ b/test/contracts/RewardEscrow.js @@ -6,7 +6,7 @@ const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); const { mockToken, setupContract } = require('./setup'); -const { currentTime, fastForward, toUnit, ZERO_ADDRESS } = require('../utils'); +const { currentTime, fastForward, toUnit, ZERO_ADDRESS } = require('../utils')(); contract('RewardEscrow', async accounts => { const SECOND = 1000; diff --git a/test/contracts/RewardsDistribution.js b/test/contracts/RewardsDistribution.js index 1f5a27f196..86981d0ddf 100644 --- a/test/contracts/RewardsDistribution.js +++ b/test/contracts/RewardsDistribution.js @@ -7,7 +7,7 @@ const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); const RewardsDistribution = artifacts.require('RewardsDistribution'); const MockRewardsRecipient = artifacts.require('MockRewardsRecipient'); -const { toUnit, ZERO_ADDRESS } = require('../utils'); +const { toUnit, ZERO_ADDRESS } = require('../utils')(); const { setupAllContracts } = require('./setup'); diff --git a/test/contracts/RewardsIntegrationTests.js b/test/contracts/RewardsIntegrationTests.js index e1bb2b6655..05da901f2a 100644 --- a/test/contracts/RewardsIntegrationTests.js +++ b/test/contracts/RewardsIntegrationTests.js @@ -6,7 +6,7 @@ const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); const { toBytes32 } = require('../..'); -const { currentTime, fastForward, toUnit, toPreciseUnit, multiplyDecimal } = require('../utils'); +const { currentTime, fastForward, toUnit, toPreciseUnit, multiplyDecimal } = require('../utils')(); const { setupAllContracts } = require('./setup'); diff --git a/test/contracts/SafeDecimalMath.js b/test/contracts/SafeDecimalMath.js index 63da0dab79..df3d56d9fa 100644 --- a/test/contracts/SafeDecimalMath.js +++ b/test/contracts/SafeDecimalMath.js @@ -7,7 +7,7 @@ const { assert } = require('./common'); const SafeDecimalMath = artifacts.require('SafeDecimalMath'); const PublicSafeDecimalMath = artifacts.require('PublicSafeDecimalMath'); -const { toUnit, fromUnit, toPreciseUnit, fromPreciseUnit } = require('../utils'); +const { toUnit, fromUnit, toPreciseUnit, fromPreciseUnit } = require('../utils')(); const { toBN } = web3.utils; diff --git a/test/contracts/SelfDestructible.js b/test/contracts/SelfDestructible.js index 70aa0c3d31..fd9755cf7d 100644 --- a/test/contracts/SelfDestructible.js +++ b/test/contracts/SelfDestructible.js @@ -6,7 +6,7 @@ const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); const SelfDestructible = artifacts.require('SelfDestructible'); -const { fastForward } = require('../utils'); +const { fastForward } = require('../utils')(); const { onlyGivenAddressCanInvoke, ensureOnlyExpectedMutativeFunctions } = require('./helpers'); diff --git a/test/contracts/SupplySchedule.js b/test/contracts/SupplySchedule.js index 72716dc3ab..daa93b7616 100644 --- a/test/contracts/SupplySchedule.js +++ b/test/contracts/SupplySchedule.js @@ -17,7 +17,7 @@ const { multiplyDecimal, powerToDecimal, ZERO_ADDRESS, -} = require('../utils'); +} = require('../utils')(); const { onlyGivenAddressCanInvoke, ensureOnlyExpectedMutativeFunctions } = require('./helpers'); diff --git a/test/contracts/Synth.js b/test/contracts/Synth.js index 5bac5efc23..6aea5253b7 100644 --- a/test/contracts/Synth.js +++ b/test/contracts/Synth.js @@ -9,7 +9,7 @@ const Synth = artifacts.require('Synth'); const { setupAllContracts } = require('./setup'); -const { currentTime, toUnit, ZERO_ADDRESS, bytesToString } = require('../utils'); +const { currentTime, toUnit, ZERO_ADDRESS, bytesToString } = require('../utils')(); const { issueSynthsToUser, ensureOnlyExpectedMutativeFunctions, diff --git a/test/contracts/Synthetix.js b/test/contracts/Synthetix.js index b356bb43e0..25c2beb8de 100644 --- a/test/contracts/Synthetix.js +++ b/test/contracts/Synthetix.js @@ -19,7 +19,7 @@ const { toUnit, fromUnit, ZERO_ADDRESS, -} = require('../utils'); +} = require('../utils')(); const { onlyGivenAddressCanInvoke, diff --git a/test/contracts/SynthetixState.js b/test/contracts/SynthetixState.js index 21aadad761..25e491634b 100644 --- a/test/contracts/SynthetixState.js +++ b/test/contracts/SynthetixState.js @@ -6,7 +6,7 @@ const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); const { setupContract } = require('./setup'); -const { toUnit } = require('../utils'); +const { toUnit } = require('../utils')(); const { onlyGivenAddressCanInvoke, ensureOnlyExpectedMutativeFunctions } = require('./helpers'); diff --git a/test/contracts/TokenState.js b/test/contracts/TokenState.js index 69c63bda63..d8e9144d6f 100644 --- a/test/contracts/TokenState.js +++ b/test/contracts/TokenState.js @@ -5,7 +5,7 @@ const { artifacts, contract } = require('@nomiclabs/buidler'); const { assert } = require('./common'); const { onlyGivenAddressCanInvoke, ensureOnlyExpectedMutativeFunctions } = require('./helpers'); -const { toUnit } = require('../utils'); +const { toUnit } = require('../utils')(); const TokenState = artifacts.require('TokenState'); diff --git a/test/contracts/common.js b/test/contracts/common.js index 9ec94bbf49..9399cbaa5e 100644 --- a/test/contracts/common.js +++ b/test/contracts/common.js @@ -16,7 +16,7 @@ const { fromUnit, takeSnapshot, restoreSnapshot, -} = require('../utils'); +} = require('../utils')(); // Helper for logging transactions console.logTransaction = transaction => { diff --git a/test/contracts/helpers.js b/test/contracts/helpers.js index 052bd66eb0..3cd52d8c26 100644 --- a/test/contracts/helpers.js +++ b/test/contracts/helpers.js @@ -4,7 +4,7 @@ const abiDecoder = require('abi-decoder'); const { assert } = require('./common'); -const { currentTime, toUnit } = require('../utils'); +const { currentTime, toUnit } = require('../utils')(); const { toBytes32 } = require('../..'); module.exports = { diff --git a/test/publish/index.js b/test/publish/index.js index b5673b83c5..bced0fd7ed 100644 --- a/test/publish/index.js +++ b/test/publish/index.js @@ -10,7 +10,7 @@ const { loadCompiledFiles } = require('../../publish/src/solidity'); const deployCmd = require('../../publish/src/commands/deploy'); const { buildPath } = deployCmd.DEFAULTS; -const { loadLocalUsers, isCompileRequired } = require('../utils'); +const testUtils = require('../utils'); const commands = { build: require('../../publish/src/commands/build').build, @@ -27,14 +27,9 @@ const { DEPLOYMENT_FILENAME, } = require('../../publish/src/constants'); -const { fastForward } = require('../utils'); - const snx = require('../..'); const { toBytes32 } = snx; -// load accounts used by local EVM -const users = loadLocalUsers(); - describe('publish scripts', function() { this.timeout(30e3); const deploymentPath = path.join(__dirname, '..', '..', 'publish', 'deployed', 'local'); @@ -56,6 +51,7 @@ describe('publish scripts', function() { let sETH; let web3; let compiledSources; + let fastForward; const resetConfigAndSynthFiles = () => { // restore the synths and config files for this env (cause removal updated it) @@ -86,6 +82,17 @@ describe('publish scripts', function() { beforeEach(async function() { console.log = (...input) => fs.appendFileSync(logfilePath, input.join(' ') + '\n'); + + web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545')); + + let loadLocalUsers; + let isCompileRequired; + + ({ loadLocalUsers, isCompileRequired, fastForward } = testUtils({ web3 })); + + // load accounts used by local EVM + const users = loadLocalUsers(); + accounts = { deployer: users[0], first: users[1], @@ -106,7 +113,6 @@ describe('publish scripts', function() { gasLimit = 5000000; [SNX, sUSD, sBTC, sETH] = ['SNX', 'sUSD', 'sBTC', 'sETH'].map(toBytes32); - web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545')); web3.eth.accounts.wallet.add(accounts.deployer.private); gasPrice = web3.utils.toWei('5', 'gwei'); }); diff --git a/test/testnet/index.js b/test/testnet/index.js index 3a72651dc8..3689072f37 100644 --- a/test/testnet/index.js +++ b/test/testnet/index.js @@ -21,8 +21,7 @@ const commands = { deploy: require('../../publish/src/commands/deploy').deploy, }; -const { loadLocalUsers, isCompileRequired } = require('../utils'); -const { currentTime, fastForward } = require('../utils'); +const testUtils = require('../utils'); const { loadConnections, confirmAction } = require('../../publish/src/util'); @@ -74,10 +73,13 @@ program let privateKey = envPrivateKey; const web3 = new Web3(new Web3.providers.HttpProvider(providerUrl)); + + const { loadLocalUsers, isCompileRequired, fastForward } = testUtils({ web3 }); + const synths = snx.getSynths({ network }); const gas = 4e6; // 4M - const gasPrice = web3.utils.toWei(gasPriceInGwei, 'gwei'); + const gasPrice = toWei(gasPriceInGwei, 'gwei'); const [sUSD, sETH] = ['sUSD', 'sETH'].map(toBytes32); const updateableSynths = synths.filter(({ name }) => ['sUSD'].indexOf(name) < 0); @@ -119,7 +121,6 @@ program snx.getSource({ network, contract: 'ExchangeRates' }).abi, snx.getTarget({ network, contract: 'ExchangeRates' }).address ); - timestamp = await currentTime(); // update rates await ExchangeRates.methods diff --git a/test/utils/index.js b/test/utils/index.js index 43b63b3e2e..e0f6fdefa4 100644 --- a/test/utils/index.js +++ b/test/utils/index.js @@ -1,11 +1,21 @@ const { assert } = require('chai'); +const buidler = require('@nomiclabs/buidler'); + const { - web3, network: { config: { accounts }, }, -} = require('@nomiclabs/buidler'); +} = buidler; + +// const Web3 = require('web3'); +// // web3 is injected to the global scope via truffle test, but +// // we need this here for test/publish which bypasses truffle altogether. +// // Note: providing the connection string 'http://127.0.0.1:8545' seems to break +// // RewardEscrow Stress Tests - it is not clear why however. +// if (typeof web3 === 'undefined') { +// global.web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545')); +// } const BN = require('bn.js'); @@ -22,477 +32,482 @@ const { CONTRACTS_FOLDER } = require('../../publish/src/constants'); const deployCmd = require('../../publish/src/commands/deploy'); const { buildPath } = deployCmd.DEFAULTS; -/** - * Sets default properties on the jsonrpc object and promisifies it so we don't have to copy/paste everywhere. - */ -const send = payload => { - if (!payload.jsonrpc) payload.jsonrpc = '2.0'; - if (!payload.id) payload.id = new Date().getTime(); +module.exports = ({ web3 } = {}) => { + // allow non-buidler based test tasks to pass thru web3 + web3 = web3 || buidler.web3; - return new Promise((resolve, reject) => { - web3.currentProvider.send(payload, (error, result) => { - if (error) return reject(error); + /** + * Sets default properties on the jsonrpc object and promisifies it so we don't have to copy/paste everywhere. + */ + const send = payload => { + if (!payload.jsonrpc) payload.jsonrpc = '2.0'; + if (!payload.id) payload.id = new Date().getTime(); - return resolve(result); - }); - }); -}; + return new Promise((resolve, reject) => { + web3.currentProvider.send(payload, (error, result) => { + if (error) return reject(error); -/** - * Mines a single block in Ganache (evm_mine is non-standard) - */ -const mineBlock = () => send({ method: 'evm_mine' }); - -/** - * Gets the time of the last block. - */ -const currentTime = async () => { - const { timestamp } = await web3.eth.getBlock('latest'); - return timestamp; -}; - -/** - * Increases the time in the EVM. - * @param seconds Number of seconds to increase the time by - */ -const fastForward = async seconds => { - // It's handy to be able to be able to pass big numbers in as we can just - // query them from the contract, then send them back. If not changed to - // a number, this causes much larger fast forwards than expected without error. - if (BN.isBN(seconds)) seconds = seconds.toNumber(); - - // And same with strings. - if (typeof seconds === 'string') seconds = parseFloat(seconds); - - await send({ - method: 'evm_increaseTime', - params: [seconds], - }); - - await mineBlock(); -}; - -/** - * Increases the time in the EVM to as close to a specific date as possible - * NOTE: Because this operation figures out the amount of seconds to jump then applies that to the EVM, - * sometimes the result can vary by a second or two depending on how fast or slow the local EVM is responding. - * @param time Date object representing the desired time at the end of the operation - */ -const fastForwardTo = async time => { - if (typeof time === 'string') time = parseInt(time); - - const timestamp = await currentTime(); - const now = new Date(timestamp * 1000); - if (time < now) - throw new Error( - `Time parameter (${time}) is less than now ${now}. You can only fast forward to times in the future.` - ); - - const secondsBetween = Math.floor((time.getTime() - now.getTime()) / 1000); - - await fastForward(secondsBetween); -}; + return resolve(result); + }); + }); + }; + + /** + * Mines a single block in Ganache (evm_mine is non-standard) + */ + const mineBlock = () => send({ method: 'evm_mine' }); + + /** + * Gets the time of the last block. + */ + const currentTime = async () => { + const { timestamp } = await web3.eth.getBlock('latest'); + return timestamp; + }; + + /** + * Increases the time in the EVM. + * @param seconds Number of seconds to increase the time by + */ + const fastForward = async seconds => { + // It's handy to be able to be able to pass big numbers in as we can just + // query them from the contract, then send them back. If not changed to + // a number, this causes much larger fast forwards than expected without error. + if (BN.isBN(seconds)) seconds = seconds.toNumber(); + + // And same with strings. + if (typeof seconds === 'string') seconds = parseFloat(seconds); + + await send({ + method: 'evm_increaseTime', + params: [seconds], + }); -/** - * Takes a snapshot and returns the ID of the snapshot for restoring later. - */ -const takeSnapshot = async () => { - const { result } = await send({ method: 'evm_snapshot' }); - await mineBlock(); + await mineBlock(); + }; + + /** + * Increases the time in the EVM to as close to a specific date as possible + * NOTE: Because this operation figures out the amount of seconds to jump then applies that to the EVM, + * sometimes the result can vary by a second or two depending on how fast or slow the local EVM is responding. + * @param time Date object representing the desired time at the end of the operation + */ + const fastForwardTo = async time => { + if (typeof time === 'string') time = parseInt(time); + + const timestamp = await currentTime(); + const now = new Date(timestamp * 1000); + if (time < now) + throw new Error( + `Time parameter (${time}) is less than now ${now}. You can only fast forward to times in the future.` + ); + + const secondsBetween = Math.floor((time.getTime() - now.getTime()) / 1000); + + await fastForward(secondsBetween); + }; + + /** + * Takes a snapshot and returns the ID of the snapshot for restoring later. + */ + const takeSnapshot = async () => { + const { result } = await send({ method: 'evm_snapshot' }); + await mineBlock(); + + return result; + }; + + /** + * Restores a snapshot that was previously taken with takeSnapshot + * @param id The ID that was returned when takeSnapshot was called. + */ + const restoreSnapshot = async id => { + await send({ + method: 'evm_revert', + params: [id], + }); + await mineBlock(); + }; + + /** + * Translates an amount to our cononical unit. We happen to use 10^18, which means we can + * use the built in web3 method for convenience, but if unit ever changes in our contracts + * we should be able to update the conversion factor here. + * @param amount The amount you want to re-base to UNIT + */ + const toUnit = amount => toBN(toWei(amount.toString(), 'ether')); + const fromUnit = amount => fromWei(amount, 'ether'); + + /** + * Translates an amount to our cononical precise unit. We happen to use 10^27, which means we can + * use the built in web3 method for convenience, but if precise unit ever changes in our contracts + * we should be able to update the conversion factor here. + * @param amount The amount you want to re-base to PRECISE_UNIT + */ + const PRECISE_UNIT_STRING = '1000000000000000000000000000'; + const PRECISE_UNIT = toBN(PRECISE_UNIT_STRING); + + const toPreciseUnit = amount => { + // Code is largely lifted from the guts of web3 toWei here: + // https://github.com/ethjs/ethjs-unit/blob/master/src/index.js + const amountString = amount.toString(); + + // Is it negative? + var negative = amountString.substring(0, 1) === '-'; + if (negative) { + amount = amount.substring(1); + } - return result; -}; + if (amount === '.') { + throw new Error(`Error converting number ${amount} to precise unit, invalid value`); + } -/** - * Restores a snapshot that was previously taken with takeSnapshot - * @param id The ID that was returned when takeSnapshot was called. - */ -const restoreSnapshot = async id => { - await send({ - method: 'evm_revert', - params: [id], - }); - await mineBlock(); -}; + // Split it into a whole and fractional part + // eslint-disable-next-line prefer-const + let [whole, fraction, ...rest] = amount.split('.'); + if (rest.length > 0) { + throw new Error(`Error converting number ${amount} to precise unit, too many decimal points`); + } -/** - * Translates an amount to our cononical unit. We happen to use 10^18, which means we can - * use the built in web3 method for convenience, but if unit ever changes in our contracts - * we should be able to update the conversion factor here. - * @param amount The amount you want to re-base to UNIT - */ -const toUnit = amount => toBN(toWei(amount.toString(), 'ether')); -const fromUnit = amount => fromWei(amount, 'ether'); - -/** - * Translates an amount to our cononical precise unit. We happen to use 10^27, which means we can - * use the built in web3 method for convenience, but if precise unit ever changes in our contracts - * we should be able to update the conversion factor here. - * @param amount The amount you want to re-base to PRECISE_UNIT - */ -const PRECISE_UNIT_STRING = '1000000000000000000000000000'; -const PRECISE_UNIT = toBN(PRECISE_UNIT_STRING); - -const toPreciseUnit = amount => { - // Code is largely lifted from the guts of web3 toWei here: - // https://github.com/ethjs/ethjs-unit/blob/master/src/index.js - const amountString = amount.toString(); - - // Is it negative? - var negative = amountString.substring(0, 1) === '-'; - if (negative) { - amount = amount.substring(1); - } - - if (amount === '.') { - throw new Error(`Error converting number ${amount} to precise unit, invalid value`); - } - - // Split it into a whole and fractional part - // eslint-disable-next-line prefer-const - let [whole, fraction, ...rest] = amount.split('.'); - if (rest.length > 0) { - throw new Error(`Error converting number ${amount} to precise unit, too many decimal points`); - } - - if (!whole) { - whole = '0'; - } - if (!fraction) { - fraction = '0'; - } - if (fraction.length > PRECISE_UNIT_STRING.length - 1) { - throw new Error(`Error converting number ${amount} to precise unit, too many decimal places`); - } - - while (fraction.length < PRECISE_UNIT_STRING.length - 1) { - fraction += '0'; - } - - whole = new BN(whole); - fraction = new BN(fraction); - let result = whole.mul(PRECISE_UNIT).add(fraction); - - if (negative) { - result = result.mul(new BN('-1')); - } - - return result; -}; + if (!whole) { + whole = '0'; + } + if (!fraction) { + fraction = '0'; + } + if (fraction.length > PRECISE_UNIT_STRING.length - 1) { + throw new Error(`Error converting number ${amount} to precise unit, too many decimal places`); + } -const fromPreciseUnit = amount => { - // Code is largely lifted from the guts of web3 fromWei here: - // https://github.com/ethjs/ethjs-unit/blob/master/src/index.js - const negative = amount.lt(new BN('0')); + while (fraction.length < PRECISE_UNIT_STRING.length - 1) { + fraction += '0'; + } - if (negative) { - amount = amount.mul(new BN('-1')); - } + whole = new BN(whole); + fraction = new BN(fraction); + let result = whole.mul(PRECISE_UNIT).add(fraction); - let fraction = amount.mod(PRECISE_UNIT).toString(); + if (negative) { + result = result.mul(new BN('-1')); + } - while (fraction.length < PRECISE_UNIT_STRING.length - 1) { - fraction = `0${fraction}`; - } + return result; + }; - // Chop zeros off the end if there are extras. - fraction = fraction.replace(/0+$/, ''); + const fromPreciseUnit = amount => { + // Code is largely lifted from the guts of web3 fromWei here: + // https://github.com/ethjs/ethjs-unit/blob/master/src/index.js + const negative = amount.lt(new BN('0')); - const whole = amount.div(PRECISE_UNIT).toString(); - let value = `${whole}${fraction === '' ? '' : `.${fraction}`}`; + if (negative) { + amount = amount.mul(new BN('-1')); + } - if (negative) { - value = `-${value}`; - } + let fraction = amount.mod(PRECISE_UNIT).toString(); - return value; -}; + while (fraction.length < PRECISE_UNIT_STRING.length - 1) { + fraction = `0${fraction}`; + } -/* - * Multiplies x and y interpreting them as fixed point decimal numbers. - */ -const multiplyDecimal = (x, y, unit = UNIT) => { - const xBN = BN.isBN(x) ? x : new BN(x); - const yBN = BN.isBN(y) ? y : new BN(y); - return xBN.mul(yBN).div(unit); -}; + // Chop zeros off the end if there are extras. + fraction = fraction.replace(/0+$/, ''); -/* - * Multiplies x and y interpreting them as fixed point decimal numbers. - */ -const divideDecimal = (x, y, unit = UNIT) => { - const xBN = BN.isBN(x) ? x : new BN(x); - const yBN = BN.isBN(y) ? y : new BN(y); - return xBN.mul(unit).div(yBN); -}; + const whole = amount.div(PRECISE_UNIT).toString(); + let value = `${whole}${fraction === '' ? '' : `.${fraction}`}`; -/* - * Exponentiation by squares of x^n, interpreting them as fixed point decimal numbers. - */ -const powerToDecimal = (x, n, unit = UNIT) => { - let xBN = BN.isBN(x) ? x : new BN(x); - let temp = unit; - while (n > 0) { - if (n % 2 !== 0) { - temp = temp.mul(xBN).div(unit); + if (negative) { + value = `-${value}`; } - xBN = xBN.mul(xBN).div(unit); - n = parseInt(n / 2); - } - return temp; -}; - -/** - * Convenience method to assert that an event matches a shape - * @param actualEventOrTransaction The transaction receipt, or event as returned in the event logs from web3 - * @param expectedEvent The event name you expect - * @param expectedArgs The args you expect in object notation, e.g. { newOracle: '0x...', updatedAt: '...' } - */ -const assertEventEqual = (actualEventOrTransaction, expectedEvent, expectedArgs) => { - // If they pass in a whole transaction we need to extract the first log, otherwise we already have what we need - const event = Array.isArray(actualEventOrTransaction.logs) - ? actualEventOrTransaction.logs[0] - : actualEventOrTransaction; - - if (!event) { - assert.fail(new Error('No event was generated from this transaction')); - } - - // Assert the names are the same. - assert.strictEqual(event.event, expectedEvent); - - assertDeepEqual(event.args, expectedArgs); - // Note: this means that if you don't assert args they'll pass regardless. - // Ensure you pass in all the args you need to assert on. -}; -/** - * Converts a hex string of bytes into a UTF8 string with \0 characters (from padding) removed - */ -const bytesToString = bytes => { - const result = hexToAscii(bytes); - return result.replace(/\0/g, ''); -}; + return value; + }; + + /* + * Multiplies x and y interpreting them as fixed point decimal numbers. + */ + const multiplyDecimal = (x, y, unit = UNIT) => { + const xBN = BN.isBN(x) ? x : new BN(x); + const yBN = BN.isBN(y) ? y : new BN(y); + return xBN.mul(yBN).div(unit); + }; + + /* + * Multiplies x and y interpreting them as fixed point decimal numbers. + */ + const divideDecimal = (x, y, unit = UNIT) => { + const xBN = BN.isBN(x) ? x : new BN(x); + const yBN = BN.isBN(y) ? y : new BN(y); + return xBN.mul(unit).div(yBN); + }; + + /* + * Exponentiation by squares of x^n, interpreting them as fixed point decimal numbers. + */ + const powerToDecimal = (x, n, unit = UNIT) => { + let xBN = BN.isBN(x) ? x : new BN(x); + let temp = unit; + while (n > 0) { + if (n % 2 !== 0) { + temp = temp.mul(xBN).div(unit); + } + xBN = xBN.mul(xBN).div(unit); + n = parseInt(n / 2); + } + return temp; + }; + + /** + * Convenience method to assert that an event matches a shape + * @param actualEventOrTransaction The transaction receipt, or event as returned in the event logs from web3 + * @param expectedEvent The event name you expect + * @param expectedArgs The args you expect in object notation, e.g. { newOracle: '0x...', updatedAt: '...' } + */ + const assertEventEqual = (actualEventOrTransaction, expectedEvent, expectedArgs) => { + // If they pass in a whole transaction we need to extract the first log, otherwise we already have what we need + const event = Array.isArray(actualEventOrTransaction.logs) + ? actualEventOrTransaction.logs[0] + : actualEventOrTransaction; + + if (!event) { + assert.fail(new Error('No event was generated from this transaction')); + } -const assertEventsEqual = (transaction, ...expectedEventsAndArgs) => { - if (expectedEventsAndArgs.length % 2 > 0) - throw new Error('Please call assert.eventsEqual with names and args as pairs.'); - if (expectedEventsAndArgs.length <= 2) - throw new Error( - "Expected events and args can be called with just assert.eventEqual as there's only one event." + // Assert the names are the same. + assert.strictEqual(event.event, expectedEvent); + + assertDeepEqual(event.args, expectedArgs); + // Note: this means that if you don't assert args they'll pass regardless. + // Ensure you pass in all the args you need to assert on. + }; + + /** + * Converts a hex string of bytes into a UTF8 string with \0 characters (from padding) removed + */ + const bytesToString = bytes => { + const result = hexToAscii(bytes); + return result.replace(/\0/g, ''); + }; + + const assertEventsEqual = (transaction, ...expectedEventsAndArgs) => { + if (expectedEventsAndArgs.length % 2 > 0) + throw new Error('Please call assert.eventsEqual with names and args as pairs.'); + if (expectedEventsAndArgs.length <= 2) + throw new Error( + "Expected events and args can be called with just assert.eventEqual as there's only one event." + ); + + for (let i = 0; i < expectedEventsAndArgs.length; i += 2) { + const log = transaction.logs[Math.floor(i / 2)]; + + assert.strictEqual(log.event, expectedEventsAndArgs[i], 'Event name mismatch'); + assertDeepEqual(log.args, expectedEventsAndArgs[i + 1], 'Event args mismatch'); + } + }; + + /** + * Convenience method to assert that two BN.js instances are equal. + * @param actualBN The BN.js instance you received + * @param expectedBN The BN.js amount you expected to receive + * @param context The description to log if we fail the assertion + */ + const assertBNEqual = (actualBN, expectedBN, context) => { + assert.strictEqual(actualBN.toString(), expectedBN.toString(), context); + }; + + /** + * Convenience method to assert that two BN.js instances are NOT equal. + * @param actualBN The BN.js instance you received + * @param expectedBN The BN.js amount you expected NOT to receive + * @param context The description to log if we fail the assertion + */ + const assertBNNotEqual = (actualBN, expectedBN) => { + assert.notStrictEqual(actualBN.toString(), expectedBN.toString(), context); + }; + + /** + * Convenience method to assert that two BN.js instances are within 100 units of each other. + * @param actualBN The BN.js instance you received + * @param expectedBN The BN.js amount you expected to receive, allowing a varience of +/- 100 units + */ + const assertBNClose = (actualBN, expectedBN, varianceParam = '10') => { + const actual = BN.isBN(actualBN) ? actualBN : new BN(actualBN); + const expected = BN.isBN(expectedBN) ? expectedBN : new BN(expectedBN); + const variance = BN.isBN(varianceParam) ? varianceParam : new BN(varianceParam); + const actualDelta = expected.sub(actual).abs(); + + assert.ok( + actual.gte(expected.sub(variance)), + `Number is too small to be close (Delta between actual and expected is ${actualDelta.toString()}, but variance was only ${variance.toString()}` ); - - for (let i = 0; i < expectedEventsAndArgs.length; i += 2) { - const log = transaction.logs[Math.floor(i / 2)]; - - assert.strictEqual(log.event, expectedEventsAndArgs[i], 'Event name mismatch'); - assertDeepEqual(log.args, expectedEventsAndArgs[i + 1], 'Event args mismatch'); - } -}; - -/** - * Convenience method to assert that two BN.js instances are equal. - * @param actualBN The BN.js instance you received - * @param expectedBN The BN.js amount you expected to receive - * @param context The description to log if we fail the assertion - */ -const assertBNEqual = (actualBN, expectedBN, context) => { - assert.strictEqual(actualBN.toString(), expectedBN.toString(), context); -}; - -/** - * Convenience method to assert that two BN.js instances are NOT equal. - * @param actualBN The BN.js instance you received - * @param expectedBN The BN.js amount you expected NOT to receive - * @param context The description to log if we fail the assertion - */ -const assertBNNotEqual = (actualBN, expectedBN) => { - assert.notStrictEqual(actualBN.toString(), expectedBN.toString(), context); -}; - -/** - * Convenience method to assert that two BN.js instances are within 100 units of each other. - * @param actualBN The BN.js instance you received - * @param expectedBN The BN.js amount you expected to receive, allowing a varience of +/- 100 units - */ -const assertBNClose = (actualBN, expectedBN, varianceParam = '10') => { - const actual = BN.isBN(actualBN) ? actualBN : new BN(actualBN); - const expected = BN.isBN(expectedBN) ? expectedBN : new BN(expectedBN); - const variance = BN.isBN(varianceParam) ? varianceParam : new BN(varianceParam); - const actualDelta = expected.sub(actual).abs(); - - assert.ok( - actual.gte(expected.sub(variance)), - `Number is too small to be close (Delta between actual and expected is ${actualDelta.toString()}, but variance was only ${variance.toString()}` - ); - assert.ok( - actual.lte(expected.add(variance)), - `Number is too large to be close (Delta between actual and expected is ${actualDelta.toString()}, but variance was only ${variance.toString()})` - ); -}; - -/** - * Convenience method to assert that two objects or arrays which contain nested BN.js instances are equal. - * @param actual What you received - * @param expected The shape you expected - */ -const assertDeepEqual = (actual, expected, context) => { - // Check if it's a value type we can assert on straight away. - if (BN.isBN(actual) || BN.isBN(expected)) { - assertBNEqual(actual, expected, context); - } else if ( - typeof expected === 'string' || - typeof actual === 'string' || - typeof expected === 'number' || - typeof actual === 'number' || - typeof expected === 'boolean' || - typeof actual === 'boolean' - ) { - assert.strictEqual(actual, expected, context); - } - // Otherwise dig through the deeper object and recurse - else if (Array.isArray(expected)) { - for (let i = 0; i < expected.length; i++) { - assertDeepEqual(actual[i], expected[i], `(array index: ${i}) `); + assert.ok( + actual.lte(expected.add(variance)), + `Number is too large to be close (Delta between actual and expected is ${actualDelta.toString()}, but variance was only ${variance.toString()})` + ); + }; + + /** + * Convenience method to assert that two objects or arrays which contain nested BN.js instances are equal. + * @param actual What you received + * @param expected The shape you expected + */ + const assertDeepEqual = (actual, expected, context) => { + // Check if it's a value type we can assert on straight away. + if (BN.isBN(actual) || BN.isBN(expected)) { + assertBNEqual(actual, expected, context); + } else if ( + typeof expected === 'string' || + typeof actual === 'string' || + typeof expected === 'number' || + typeof actual === 'number' || + typeof expected === 'boolean' || + typeof actual === 'boolean' + ) { + assert.strictEqual(actual, expected, context); } - } else { - for (const key of Object.keys(expected)) { - assertDeepEqual(actual[key], expected[key], `(key: ${key}) `); + // Otherwise dig through the deeper object and recurse + else if (Array.isArray(expected)) { + for (let i = 0; i < expected.length; i++) { + assertDeepEqual(actual[i], expected[i], `(array index: ${i}) `); + } + } else { + for (const key of Object.keys(expected)) { + assertDeepEqual(actual[key], expected[key], `(key: ${key}) `); + } } - } -}; - -/** - * Convenience method to assert that an amount of ether (or other 10^18 number) was received from a contract. - * @param actualWei The value retrieved from a smart contract or wallet in wei - * @param expectedAmount The amount you expect e.g. '1' - * @param expectedUnit The unit you expect e.g. 'gwei'. Defaults to 'ether' - */ -const assertUnitEqual = (actualWei, expectedAmount, expectedUnit = 'ether') => { - assertBNEqual(actualWei, toWei(expectedAmount, expectedUnit)); -}; - -/** - * Convenience method to assert that an amount of ether (or other 10^18 number) was NOT received from a contract. - * @param actualWei The value retrieved from a smart contract or wallet in wei - * @param expectedAmount The amount you expect NOT to be equal to e.g. '1' - * @param expectedUnit The unit you expect e.g. 'gwei'. Defaults to 'ether' - */ -const assertUnitNotEqual = (actualWei, expectedAmount, expectedUnit = 'ether') => { - assertBNNotEqual(actualWei, toWei(expectedAmount, expectedUnit)); -}; - -/** - * Convenience method to assert that the return of the given block when invoked or promise causes a - * revert to occur, with an optional revert message. - * @param blockOrPromise The JS block (i.e. function that when invoked returns a promise) or a promise itself - * @param reason Optional reason string to search for in revert message - */ -const assertRevert = async (blockOrPromise, reason) => { - let errorCaught = false; - try { - const result = typeof blockOrPromise === 'function' ? blockOrPromise() : blockOrPromise; - await result; - } catch (error) { - assert.include(error.message, 'revert'); - if (reason) { - assert.include(error.message, reason); + }; + + /** + * Convenience method to assert that an amount of ether (or other 10^18 number) was received from a contract. + * @param actualWei The value retrieved from a smart contract or wallet in wei + * @param expectedAmount The amount you expect e.g. '1' + * @param expectedUnit The unit you expect e.g. 'gwei'. Defaults to 'ether' + */ + const assertUnitEqual = (actualWei, expectedAmount, expectedUnit = 'ether') => { + assertBNEqual(actualWei, toWei(expectedAmount, expectedUnit)); + }; + + /** + * Convenience method to assert that an amount of ether (or other 10^18 number) was NOT received from a contract. + * @param actualWei The value retrieved from a smart contract or wallet in wei + * @param expectedAmount The amount you expect NOT to be equal to e.g. '1' + * @param expectedUnit The unit you expect e.g. 'gwei'. Defaults to 'ether' + */ + const assertUnitNotEqual = (actualWei, expectedAmount, expectedUnit = 'ether') => { + assertBNNotEqual(actualWei, toWei(expectedAmount, expectedUnit)); + }; + + /** + * Convenience method to assert that the return of the given block when invoked or promise causes a + * revert to occur, with an optional revert message. + * @param blockOrPromise The JS block (i.e. function that when invoked returns a promise) or a promise itself + * @param reason Optional reason string to search for in revert message + */ + const assertRevert = async (blockOrPromise, reason) => { + let errorCaught = false; + try { + const result = typeof blockOrPromise === 'function' ? blockOrPromise() : blockOrPromise; + await result; + } catch (error) { + assert.include(error.message, 'revert'); + if (reason) { + assert.include(error.message, reason); + } + errorCaught = true; } - errorCaught = true; - } - - assert.strictEqual(errorCaught, true, 'Operation did not revert as expected'); -}; - -const assertInvalidOpcode = async blockOrPromise => { - let errorCaught = false; - try { - const result = typeof blockOrPromise === 'function' ? blockOrPromise() : blockOrPromise; - await result; - } catch (error) { - // Note: commented out until fixed in: https://github.com/nomiclabs/buidler/issues/506 - // assert.include(error.message, 'invalid opcode); - errorCaught = true; - } - - assert.strictEqual( - errorCaught, - true, - 'Operation did not cause an invalid opcode error as expected' - ); -}; - -/** - * Gets the ETH balance for the account address - * @param account Ethereum wallet address - */ -const getEthBalance = account => web3.eth.getBalance(account); - -const [SNX, sUSD, sAUD, sEUR, sBTC, iBTC, sETH, ETH] = [ - 'SNX', - 'sUSD', - 'sAUD', - 'sEUR', - 'sBTC', - 'iBTC', - 'sETH', - 'ETH', -].map(toBytes32); - -const defaultCurrencyKeys = [SNX, sUSD, sAUD, sEUR, sBTC, iBTC, sETH, ETH]; - -const loadLocalUsers = () => { - return accounts.map(({ privateKey }) => ({ - private: privateKey, - public: web3.eth.accounts.privateKeyToAccount(privateKey).address, - })); -}; - -const isCompileRequired = () => { - // get last modified sol file - const latestSolTimestamp = getLatestSolTimestamp(CONTRACTS_FOLDER); - // get last build - const { earliestCompiledTimestamp } = loadCompiledFiles({ buildPath }); - - return latestSolTimestamp > earliestCompiledTimestamp; -}; + assert.strictEqual(errorCaught, true, 'Operation did not revert as expected'); + }; + + const assertInvalidOpcode = async blockOrPromise => { + let errorCaught = false; + try { + const result = typeof blockOrPromise === 'function' ? blockOrPromise() : blockOrPromise; + await result; + } catch (error) { + // Note: commented out until fixed in: https://github.com/nomiclabs/buidler/issues/506 + // assert.include(error.message, 'invalid opcode); + errorCaught = true; + } -module.exports = { - ZERO_ADDRESS, - - mineBlock, - fastForward, - fastForwardTo, - takeSnapshot, - restoreSnapshot, - currentTime, - multiplyDecimal, - divideDecimal, - powerToDecimal, - - toUnit, - fromUnit, - - toPreciseUnit, - fromPreciseUnit, - - assertEventEqual, - assertEventsEqual, - assertBNEqual, - assertBNNotEqual, - assertBNClose, - assertDeepEqual, - assertInvalidOpcode, - assertUnitEqual, - assertUnitNotEqual, - assertRevert, - - getEthBalance, - bytesToString, - - defaultCurrencyKeys, - - loadLocalUsers, - isCompileRequired, + assert.strictEqual( + errorCaught, + true, + 'Operation did not cause an invalid opcode error as expected' + ); + }; + + /** + * Gets the ETH balance for the account address + * @param account Ethereum wallet address + */ + const getEthBalance = account => web3.eth.getBalance(account); + + const [SNX, sUSD, sAUD, sEUR, sBTC, iBTC, sETH, ETH] = [ + 'SNX', + 'sUSD', + 'sAUD', + 'sEUR', + 'sBTC', + 'iBTC', + 'sETH', + 'ETH', + ].map(toBytes32); + + const defaultCurrencyKeys = [SNX, sUSD, sAUD, sEUR, sBTC, iBTC, sETH, ETH]; + + const loadLocalUsers = () => { + return accounts.map(({ privateKey }) => ({ + private: privateKey, + public: web3.eth.accounts.privateKeyToAccount(privateKey).address, + })); + }; + + const isCompileRequired = () => { + // get last modified sol file + const latestSolTimestamp = getLatestSolTimestamp(CONTRACTS_FOLDER); + + // get last build + const { earliestCompiledTimestamp } = loadCompiledFiles({ buildPath }); + + return latestSolTimestamp > earliestCompiledTimestamp; + }; + + return { + ZERO_ADDRESS, + + mineBlock, + fastForward, + fastForwardTo, + takeSnapshot, + restoreSnapshot, + currentTime, + multiplyDecimal, + divideDecimal, + powerToDecimal, + + toUnit, + fromUnit, + + toPreciseUnit, + fromPreciseUnit, + + assertEventEqual, + assertEventsEqual, + assertBNEqual, + assertBNNotEqual, + assertBNClose, + assertDeepEqual, + assertInvalidOpcode, + assertUnitEqual, + assertUnitNotEqual, + assertRevert, + + getEthBalance, + bytesToString, + + defaultCurrencyKeys, + + loadLocalUsers, + isCompileRequired, + }; };