diff --git a/contracts/mocks/CheckpointsImpl.sol b/contracts/mocks/CheckpointsImpl.sol index 5b9ec0acb..14681ca40 100644 --- a/contracts/mocks/CheckpointsImpl.sol +++ b/contracts/mocks/CheckpointsImpl.sol @@ -20,4 +20,8 @@ contract CheckpointsImpl { function push(uint256 value) public returns (uint256, uint256) { return _totalCheckpoints.push(value); } + + function length() public view returns (uint256) { + return _totalCheckpoints._checkpoints.length; + } } diff --git a/test/crosschain/CrossChainEnabled.test.js b/test/crosschain/CrossChainEnabled.test.js index 6aeb4db7d..bff955882 100644 --- a/test/crosschain/CrossChainEnabled.test.js +++ b/test/crosschain/CrossChainEnabled.test.js @@ -17,6 +17,11 @@ function shouldBehaveLikeReceiver (sender = randomAddress()) { this.receiver.crossChainRestricted(), 'NotCrossChainCall()', ); + + await expectRevertCustomError( + this.receiver.crossChainOwnerRestricted(), + 'NotCrossChainCall()', + ); }); it('should restrict to cross-chain call from a invalid sender', async function () { diff --git a/test/governance/compatibility/GovernorCompatibilityBravo.test.js b/test/governance/compatibility/GovernorCompatibilityBravo.test.js index 5f12e9fac..79950474c 100644 --- a/test/governance/compatibility/GovernorCompatibilityBravo.test.js +++ b/test/governance/compatibility/GovernorCompatibilityBravo.test.js @@ -168,6 +168,16 @@ contract('GovernorCompatibilityBravo', function (accounts) { ); }); + it('double voting is forbiden', async function () { + await this.helper.propose({ from: proposer }); + await this.helper.waitForSnapshot(); + await this.helper.vote({ support: Enums.VoteType.For }, { from: voter1 }); + await expectRevert( + this.helper.vote({ support: Enums.VoteType.For }, { from: voter1 }), + 'GovernorCompatibilityBravo: vote already cast', + ); + }); + it('with function selector and arguments', async function () { const target = this.receiver.address; this.helper.setProposal([ diff --git a/test/helpers/txpool.js b/test/helpers/txpool.js new file mode 100644 index 000000000..895246b72 --- /dev/null +++ b/test/helpers/txpool.js @@ -0,0 +1,40 @@ +const { network } = require('hardhat'); +const { promisify } = require('util'); + +const queue = promisify(setImmediate); + +async function countPendingTransactions () { + return parseInt( + await network.provider.send('eth_getBlockTransactionCountByNumber', ['pending']), + ); +} + +async function batchInBlock (txs) { + try { + // disable auto-mining + await network.provider.send('evm_setAutomine', [false]); + // send all transactions + const promises = txs.map(fn => fn()); + // wait for node to have all pending transactions + while (txs.length > await countPendingTransactions()) { + await queue(); + } + // mine one block + await network.provider.send('evm_mine'); + // fetch receipts + const receipts = await Promise.all(promises); + // Sanity check, all tx should be in the same block + const minedBlocks = new Set(receipts.map(({ receipt }) => receipt.blockNumber)); + expect(minedBlocks.size).to.equal(1); + + return receipts; + } finally { + // enable auto-mining + await network.provider.send('evm_setAutomine', [true]); + } +} + +module.exports = { + countPendingTransactions, + batchInBlock, +}; diff --git a/test/token/ERC20/extensions/ERC20Votes.test.js b/test/token/ERC20/extensions/ERC20Votes.test.js index 325f26726..be28f66f3 100644 --- a/test/token/ERC20/extensions/ERC20Votes.test.js +++ b/test/token/ERC20/extensions/ERC20Votes.test.js @@ -8,11 +8,9 @@ const { fromRpcSig } = require('ethereumjs-util'); const ethSigUtil = require('eth-sig-util'); const Wallet = require('ethereumjs-wallet').default; -const { promisify } = require('util'); -const queue = promisify(setImmediate); - const ERC20VotesMock = artifacts.require('ERC20VotesMock'); +const { batchInBlock } = require('../../../helpers/txpool'); const { EIP712Domain, domainSeparator } = require('../../../helpers/eip712'); const Delegation = [ @@ -21,37 +19,6 @@ const Delegation = [ { name: 'expiry', type: 'uint256' }, ]; -async function countPendingTransactions() { - return parseInt( - await network.provider.send('eth_getBlockTransactionCountByNumber', ['pending']) - ); -} - -async function batchInBlock (txs) { - try { - // disable auto-mining - await network.provider.send('evm_setAutomine', [false]); - // send all transactions - const promises = txs.map(fn => fn()); - // wait for node to have all pending transactions - while (txs.length > await countPendingTransactions()) { - await queue(); - } - // mine one block - await network.provider.send('evm_mine'); - // fetch receipts - const receipts = await Promise.all(promises); - // Sanity check, all tx should be in the same block - const minedBlocks = new Set(receipts.map(({ receipt }) => receipt.blockNumber)); - expect(minedBlocks.size).to.equal(1); - - return receipts; - } finally { - // enable auto-mining - await network.provider.send('evm_setAutomine', [true]); - } -} - contract('ERC20Votes', function (accounts) { const [ holder, recipient, holderDelegatee, recipientDelegatee, other1, other2 ] = accounts; diff --git a/test/token/ERC20/extensions/ERC20VotesComp.test.js b/test/token/ERC20/extensions/ERC20VotesComp.test.js index a91ff1230..b70c6d167 100644 --- a/test/token/ERC20/extensions/ERC20VotesComp.test.js +++ b/test/token/ERC20/extensions/ERC20VotesComp.test.js @@ -8,11 +8,9 @@ const { fromRpcSig } = require('ethereumjs-util'); const ethSigUtil = require('eth-sig-util'); const Wallet = require('ethereumjs-wallet').default; -const { promisify } = require('util'); -const queue = promisify(setImmediate); - const ERC20VotesCompMock = artifacts.require('ERC20VotesCompMock'); +const { batchInBlock } = require('../../../helpers/txpool'); const { EIP712Domain, domainSeparator } = require('../../../helpers/eip712'); const Delegation = [ @@ -21,37 +19,6 @@ const Delegation = [ { name: 'expiry', type: 'uint256' }, ]; -async function countPendingTransactions() { - return parseInt( - await network.provider.send('eth_getBlockTransactionCountByNumber', ['pending']) - ); -} - -async function batchInBlock (txs) { - try { - // disable auto-mining - await network.provider.send('evm_setAutomine', [false]); - // send all transactions - const promises = txs.map(fn => fn()); - // wait for node to have all pending transactions - while (txs.length > await countPendingTransactions()) { - await queue(); - } - // mine one block - await network.provider.send('evm_mine'); - // fetch receipts - const receipts = await Promise.all(promises); - // Sanity check, all tx should be in the same block - const minedBlocks = new Set(receipts.map(({ receipt }) => receipt.blockNumber)); - expect(minedBlocks.size).to.equal(1); - - return receipts; - } finally { - // enable auto-mining - await network.provider.send('evm_setAutomine', [true]); - } -} - contract('ERC20VotesComp', function (accounts) { const [ holder, recipient, holderDelegatee, recipientDelegatee, other1, other2 ] = accounts; diff --git a/test/token/common/ERC2981.behavior.js b/test/token/common/ERC2981.behavior.js index 0d906a919..2fd274765 100644 --- a/test/token/common/ERC2981.behavior.js +++ b/test/token/common/ERC2981.behavior.js @@ -66,7 +66,7 @@ function shouldBehaveLikeERC2981 () { ); await expectRevert( - this.token.setTokenRoyalty(this.tokenId1, this.account1, new BN('11000')), + this.token.setDefaultRoyalty(this.account1, new BN('11000')), 'ERC2981: royalty fee will exceed salePrice', ); }); diff --git a/test/utils/Base64.test.js b/test/utils/Base64.test.js index 5eb4f74b2..b6ee6579e 100644 --- a/test/utils/Base64.test.js +++ b/test/utils/Base64.test.js @@ -25,5 +25,9 @@ contract('Strings', function () { const input = web3.utils.asciiToHex(TEST_MESSAGE); expect(await this.base64.encode(input)).to.equal('dGVzdDEy'); }); + + it('empty bytes', async function () { + expect(await this.base64.encode([])).to.equal(''); + }); }); }); diff --git a/test/utils/Checkpoints.test.js b/test/utils/Checkpoints.test.js index 37f9013ec..9938dc35b 100644 --- a/test/utils/Checkpoints.test.js +++ b/test/utils/Checkpoints.test.js @@ -2,6 +2,8 @@ const { expectRevert, time } = require('@openzeppelin/test-helpers'); const { expect } = require('chai'); +const { batchInBlock } = require('../helpers/txpool'); + const CheckpointsImpl = artifacts.require('CheckpointsImpl'); contract('Checkpoints', function (accounts) { @@ -55,5 +57,18 @@ contract('Checkpoints', function (accounts) { 'Checkpoints: block not yet mined', ); }); + + it('multiple checkpoints in the same block', async function () { + const lengthBefore = await this.checkpoint.length(); + await batchInBlock([ + () => this.checkpoint.push(8, { gas: 100000 }), + () => this.checkpoint.push(9, { gas: 100000 }), + () => this.checkpoint.push(10, { gas: 100000 }), + ]); + const lengthAfter = await this.checkpoint.length(); + + expect(lengthAfter.toNumber()).to.be.equal(lengthBefore.toNumber() + 1); + expect(await this.checkpoint.latest()).to.be.bignumber.equal('10'); + }); }); });