diff --git a/solidity/core/test/validator-manager/inboxMultisigValidatorManager.test.ts b/solidity/core/test/validator-manager/inboxMultisigValidatorManager.test.ts index c4c5387d3..89bfdaacc 100644 --- a/solidity/core/test/validator-manager/inboxMultisigValidatorManager.test.ts +++ b/solidity/core/test/validator-manager/inboxMultisigValidatorManager.test.ts @@ -81,7 +81,7 @@ describe.only('InboxMultisigValidatorManager', () => { const signatures = await getCheckpointSignatures( root, index, - [validator0], // 1/2 signer is not a quorum + [validator0], // 1/2 signers is not a quorum ); await expect( diff --git a/solidity/core/test/validator-manager/multisigValidatorManager.test.ts b/solidity/core/test/validator-manager/multisigValidatorManager.test.ts index 5181f32d4..ba7f00d1a 100644 --- a/solidity/core/test/validator-manager/multisigValidatorManager.test.ts +++ b/solidity/core/test/validator-manager/multisigValidatorManager.test.ts @@ -1,5 +1,5 @@ -import { ethers } from 'hardhat'; import { expect } from 'chai'; +import { ethers } from 'hardhat'; import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { Validator } from '@abacus-network/utils'; @@ -15,7 +15,7 @@ const OUTBOX_DOMAIN_HASH = ethers.utils.keccak256( ); const QUORUM_THRESHOLD = 1; -describe.only('MultisigValidatorManager', async () => { +describe('MultisigValidatorManager', async () => { let validatorManager: TestMultisigValidatorManager, signer: SignerWithAddress, nonOwner: SignerWithAddress, diff --git a/solidity/core/test/validator-manager/outboxMultisigValidatorManager.test.ts b/solidity/core/test/validator-manager/outboxMultisigValidatorManager.test.ts new file mode 100644 index 000000000..75adc2d84 --- /dev/null +++ b/solidity/core/test/validator-manager/outboxMultisigValidatorManager.test.ts @@ -0,0 +1,121 @@ +import { expect } from 'chai'; +import { ethers } from 'hardhat'; +import { types, utils, Validator } from '@abacus-network/utils'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; + +import { + Outbox, + Outbox__factory, + OutboxMultisigValidatorManager, + OutboxMultisigValidatorManager__factory, +} from '../../types'; +import { getCheckpointSignatures } from './utils'; + +const OUTBOX_DOMAIN = 1234; +const INBOX_DOMAIN = 4321; +const QUORUM_THRESHOLD = 2; + +describe('OutboxMultisigValidatorManager', () => { + let validatorManager: OutboxMultisigValidatorManager, + outbox: Outbox, + signer: SignerWithAddress, + validator0: Validator, + validator1: Validator; + + before(async () => { + const signers = await ethers.getSigners(); + [signer] = signers; + const [, validatorSigner0, validatorSigner1] = signers; + validator0 = await Validator.fromSigner(validatorSigner0, OUTBOX_DOMAIN); + validator1 = await Validator.fromSigner(validatorSigner1, OUTBOX_DOMAIN); + }); + + beforeEach(async () => { + const validatorManagerFactory = new OutboxMultisigValidatorManager__factory( + signer, + ); + validatorManager = await validatorManagerFactory.deploy( + OUTBOX_DOMAIN, + [validator0.address, validator1.address], + QUORUM_THRESHOLD, + ); + + const outboxFactory = new Outbox__factory(signer); + outbox = await outboxFactory.deploy(OUTBOX_DOMAIN); + await outbox.initialize(validatorManager.address); + }); + + describe('#improperCheckpoint', () => { + const root = ethers.utils.formatBytes32String('test root'); + const index = 1; + + it('accepts an improper checkpoint if there is a quorum', async () => { + const signatures = await getCheckpointSignatures( + root, + index, + [validator0, validator1], // 2/2 signers, making a quorum + ); + + // Send message with signer address as msg.sender + await expect( + validatorManager.improperCheckpoint( + outbox.address, + root, + index, + signatures, + ), + ) + .to.emit(validatorManager, 'ImproperCheckpoint') + .withArgs( + outbox.address, + root, + index, + signatures, + ); + expect(await outbox.state()).to.equal(types.AbacusState.FAILED); + }); + + it('reverts if there is not a quorum', async () => { + const signatures = await getCheckpointSignatures( + root, + index, + [validator0], // 1/2 signers is not a quorum + ); + + await expect( + validatorManager.improperCheckpoint( + outbox.address, + root, + index, + signatures + ) + ).to.be.revertedWith('!quorum'); + }); + + it('reverts if the checkpoint is not improper', async () => { + const message = `0x${Buffer.alloc(10).toString('hex')}`; + await outbox.dispatch( + INBOX_DOMAIN, + utils.addressToBytes32(signer.address), + message, + ); + await outbox.checkpoint(); + const [root, index] = await outbox.latestCheckpoint(); + + const signatures = await getCheckpointSignatures( + root, + index.toNumber(), + [validator0, validator1], // 2/2 signers, making a quorum + ); + + await expect( + validatorManager.improperCheckpoint( + outbox.address, + root, + index, + signatures + ) + ).to.be.revertedWith('!improper'); + }); + }); +});