diff --git a/contracts/0.8.9/test_helpers/oracle/HashConsensusTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/HashConsensusTimeTravellable.sol index cb7cda2f5..238cc9506 100644 --- a/contracts/0.8.9/test_helpers/oracle/HashConsensusTimeTravellable.sol +++ b/contracts/0.8.9/test_helpers/oracle/HashConsensusTimeTravellable.sol @@ -72,4 +72,12 @@ contract HashConsensusTimeTravellable is HashConsensus { function advanceTimeByEpochs(uint256 numEpochs) external { _time += SECONDS_PER_SLOT * SLOTS_PER_EPOCH * numEpochs; } + + function getReportProcessor() external view returns (address) { + return _reportProcessor; + } + + function getConsensusVersion() external view returns (uint256) { + return _getConsensusVersion(); + } } diff --git a/test/0.8.9/oracle/hash-consensus-deploy.test.js b/test/0.8.9/oracle/hash-consensus-deploy.test.js index a9c66f89b..5aa0b7a97 100644 --- a/test/0.8.9/oracle/hash-consensus-deploy.test.js +++ b/test/0.8.9/oracle/hash-consensus-deploy.test.js @@ -34,6 +34,7 @@ const CONSENSUS_VERSION = 1 async function deployHashConsensus(admin, { reportProcessor = null, + reportProcessorAddress = null, slotsPerEpoch = SLOTS_PER_EPOCH, secondsPerSlot = SECONDS_PER_SLOT, genesisTime = GENESIS_TIME, @@ -41,7 +42,7 @@ async function deployHashConsensus(admin, { fastLaneLengthSlots = 0, initialEpoch = 1 } = {}) { - if (!reportProcessor) { + if (!reportProcessor && !reportProcessorAddress) { reportProcessor = await MockReportProcessor.new(CONSENSUS_VERSION, { from: admin }) } @@ -53,7 +54,7 @@ async function deployHashConsensus(admin, { initialEpoch, fastLaneLengthSlots, admin, - reportProcessor.address, + reportProcessorAddress || reportProcessor.address, { from: admin } ) diff --git a/test/0.8.9/oracle/hash-consensus-report-processor.test.js b/test/0.8.9/oracle/hash-consensus-report-processor.test.js new file mode 100644 index 000000000..25790e55b --- /dev/null +++ b/test/0.8.9/oracle/hash-consensus-report-processor.test.js @@ -0,0 +1,120 @@ +const { assert, getAccessControlMessage } = require('../../helpers/assert') +const { toNum } = require('../../helpers/utils') +const { assertBn, assertEvent, assertAmountOfEvents } = require('@aragon/contract-helpers-test/src/asserts') +const { assertRevert } = require('../../helpers/assertThrow') +const { ZERO_ADDRESS, bn } = require('@aragon/contract-helpers-test') + +const { + SLOTS_PER_EPOCH, SECONDS_PER_SLOT, GENESIS_TIME, EPOCHS_PER_FRAME, + SECONDS_PER_EPOCH, SECONDS_PER_FRAME, SLOTS_PER_FRAME, + computeSlotAt, computeEpochAt, computeEpochFirstSlot, computeEpochFirstSlotAt, + computeTimestampAtSlot, computeTimestampAtEpoch, + ZERO_HASH, HASH_1, HASH_2, HASH_3, HASH_4, HASH_5, + CONSENSUS_VERSION, deployHashConsensus} = require('./hash-consensus-deploy.test') + +const CONSENSUS_VERSION_2 = 2 + +const HashConsensus = artifacts.require('HashConsensusTimeTravellable') +const MockReportProcessor = artifacts.require('MockReportProcessor') + +contract('HashConsensus', ([admin, member1, member2, member3, member4, member5, stranger]) => { + let consensus + let reportProcessor + + context('Report Processor', () => { + let consensus + let reportProcessor1 + let reportProcessor2 + + const deploy = async (options = undefined) => { + const deployed = await deployHashConsensus(admin, options) + consensus = deployed.consensus + reportProcessor1 = deployed.reportProcessor + reportProcessor2 = await MockReportProcessor.new(CONSENSUS_VERSION_2, { from: admin }) + } + + const deployProcessorZero = async () => { + await deploy({ reportProcessorAddress: ZERO_ADDRESS }) + } + + context('without initial processor', () => { + before(deployProcessorZero) + + it('has no initial processor', async () => { + assert.addressEqual( + await consensus.getReportProcessor(), + ZERO_ADDRESS, + 'there should be zero address for processor', + ) + }) + + it('consensus version equals zero', async () => { + assert.equal( + await consensus.getConsensusVersion(), + 0, + ) + }) + }) + + context('with initial processor', () => { + before(deploy) + + it('properly set initial report processor', async () => { + assert.addressEqual( + await consensus.getReportProcessor(), + reportProcessor1.address, + 'processor address differs', + ) + }) + + context('method setReportProcessor', () => { + before(deploy) + + it('checks next processor is not zero', async () => { + await assertRevert( + consensus.setReportProcessor(ZERO_ADDRESS), + 'AddressCannotBeZero()', + ) + }) + + it('checks next processor is not the same as previous', async () => { + await assertRevert( + consensus.setReportProcessor(reportProcessor1.address), + 'NewProcessorCannotBeTheSame()', + ) + }) + + it('checks tx sender for MANAGE_REPORT_PROCESSOR_ROLE', async () => { + await assertRevert( + consensus.setReportProcessor(reportProcessor2.address, {from: stranger}), + getAccessControlMessage(stranger.toLowerCase(), await consensus.MANAGE_REPORT_PROCESSOR_ROLE()) + ) + }) + + it('emits ReportProcessorSet event', async () => { + const tx = await consensus.setReportProcessor(reportProcessor2.address) + assertEvent(tx, 'ReportProcessorSet', {expectedArgs: {processor: reportProcessor2.address, prevProcessor: reportProcessor1.address}}) + }) + }) + + context('consensus version', () => { + beforeEach(deploy) + + it('equals to version of initial processor', async () => { + assert.equal( + await consensus.getConsensusVersion(), + CONSENSUS_VERSION, + ) + }) + + it('equals to new processor version after it was changed', async () => { + await consensus.setReportProcessor(reportProcessor2.address) + assert.equal( + await consensus.getConsensusVersion(), + CONSENSUS_VERSION_2, + ) + }) + }) + }) + }) +}) diff --git a/test/helpers/assert.js b/test/helpers/assert.js index 3c312a3aa..6976856a9 100644 --- a/test/helpers/assert.js +++ b/test/helpers/assert.js @@ -55,6 +55,10 @@ chai.util.addMethod(chai.assert, 'notEquals', function (actual, expected, errorM this.notEqual(actual.toString(), expected.toString(), `${errorMsg || ""} expected ${expected.toString()} to not equal ${actual.toString()}`) }) +chai.util.addMethod(chai.assert, 'addressEqual', function (actual, expected, errorMsg) { + assert.equal(toChecksumAddress(actual), toChecksumAddress(expected), errorMsg) +}) + chai.util.addMethod(chai.assert, 'revertsWithCustomError', async function (receipt, reason) { try { await receipt @@ -104,4 +108,8 @@ function normalizeArg(arg) { return arg } -module.exports = { assert: chai.assert } +function getAccessControlMessage(address, role) { + return `AccessControl: account ${address} is missing role ${role}` +} + +module.exports = { assert: chai.assert, getAccessControlMessage }