Migrate `AccessControl` tests (#4694)

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
pull/4707/head
Ernesto García 1 year ago committed by GitHub
parent 7c8b7a2728
commit 2ec2ed9695
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 860
      test/access/AccessControl.behavior.js
  2. 17
      test/access/AccessControl.test.js
  3. 30
      test/access/extensions/AccessControlDefaultAdminRules.test.js
  4. 19
      test/access/extensions/AccessControlEnumerable.test.js
  5. 13
      test/helpers/time.js
  6. 49
      test/utils/introspection/SupportsInterface.behavior.js

File diff suppressed because it is too large Load Diff

@ -1,12 +1,19 @@
const { ethers } = require('hardhat');
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
const { DEFAULT_ADMIN_ROLE, shouldBehaveLikeAccessControl } = require('./AccessControl.behavior.js');
const AccessControl = artifacts.require('$AccessControl');
async function fixture() {
const [defaultAdmin, ...accounts] = await ethers.getSigners();
const mock = await ethers.deployContract('$AccessControl');
await mock.$_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
return { mock, defaultAdmin, accounts };
}
contract('AccessControl', function (accounts) {
describe('AccessControl', function () {
beforeEach(async function () {
this.accessControl = await AccessControl.new({ from: accounts[0] });
await this.accessControl.$_grantRole(DEFAULT_ADMIN_ROLE, accounts[0]);
Object.assign(this, await loadFixture(fixture));
});
shouldBehaveLikeAccessControl(...accounts);
shouldBehaveLikeAccessControl();
});

@ -1,26 +1,30 @@
const { time, constants, expectRevert } = require('@openzeppelin/test-helpers');
const { ethers } = require('hardhat');
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
const { bigint: time } = require('../../helpers/time');
const {
shouldBehaveLikeAccessControl,
shouldBehaveLikeAccessControlDefaultAdminRules,
} = require('../AccessControl.behavior.js');
const AccessControlDefaultAdminRules = artifacts.require('$AccessControlDefaultAdminRules');
contract('AccessControlDefaultAdminRules', function (accounts) {
const delay = web3.utils.toBN(time.duration.hours(10));
async function fixture() {
const delay = time.duration.hours(10);
const [defaultAdmin, ...accounts] = await ethers.getSigners();
const mock = await ethers.deployContract('$AccessControlDefaultAdminRules', [delay, defaultAdmin]);
return { mock, defaultAdmin, delay, accounts };
}
describe('AccessControlDefaultAdminRules', function () {
beforeEach(async function () {
this.accessControl = await AccessControlDefaultAdminRules.new(delay, accounts[0], { from: accounts[0] });
Object.assign(this, await loadFixture(fixture));
});
it('initial admin not zero', async function () {
await expectRevert(
AccessControlDefaultAdminRules.new(delay, constants.ZERO_ADDRESS),
'AccessControlInvalidDefaultAdmin',
[constants.ZERO_ADDRESS],
);
await expect(ethers.deployContract('$AccessControlDefaultAdminRules', [this.delay, ethers.ZeroAddress]))
.to.be.revertedWithCustomError(this.mock, 'AccessControlInvalidDefaultAdmin')
.withArgs(ethers.ZeroAddress);
});
shouldBehaveLikeAccessControl(...accounts);
shouldBehaveLikeAccessControlDefaultAdminRules(delay, ...accounts);
shouldBehaveLikeAccessControl();
shouldBehaveLikeAccessControlDefaultAdminRules();
});

@ -1,17 +1,24 @@
const { ethers } = require('hardhat');
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
const {
DEFAULT_ADMIN_ROLE,
shouldBehaveLikeAccessControl,
shouldBehaveLikeAccessControlEnumerable,
} = require('../AccessControl.behavior.js');
const AccessControlEnumerable = artifacts.require('$AccessControlEnumerable');
async function fixture() {
const [defaultAdmin, ...accounts] = await ethers.getSigners();
const mock = await ethers.deployContract('$AccessControlEnumerable');
await mock.$_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
return { mock, defaultAdmin, accounts };
}
contract('AccessControlEnumerable', function (accounts) {
describe('AccessControlEnumerable', function () {
beforeEach(async function () {
this.accessControl = await AccessControlEnumerable.new({ from: accounts[0] });
await this.accessControl.$_grantRole(DEFAULT_ADMIN_ROLE, accounts[0]);
Object.assign(this, await loadFixture(fixture));
});
shouldBehaveLikeAccessControl(...accounts);
shouldBehaveLikeAccessControlEnumerable(...accounts);
shouldBehaveLikeAccessControl();
shouldBehaveLikeAccessControlEnumerable();
});

@ -1,5 +1,7 @@
const { time, mineUpTo } = require('@nomicfoundation/hardhat-network-helpers');
const mapObject = (obj, fn) => Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, fn(value)]));
module.exports = {
clock: {
blocknumber: () => time.latestBlock(),
@ -13,6 +15,15 @@ module.exports = {
},
forward: {
blocknumber: mineUpTo,
timestamp: time.increaseTo,
timestamp: (to, mine = true) => (mine ? time.increaseTo(to) : time.setNextBlockTimestamp(to)),
},
duration: time.duration,
};
// TODO: deprecate the old version in favor of this one
module.exports.bigint = {
clock: mapObject(module.exports.clock, fn => () => fn().then(BigInt)),
clockFromReceipt: mapObject(module.exports.clockFromReceipt, fn => receipt => fn(receipt).then(BigInt)),
forward: module.exports.forward,
duration: mapObject(module.exports.duration, fn => n => BigInt(fn(n))),
};

@ -1,9 +1,9 @@
const { makeInterfaceId } = require('@openzeppelin/test-helpers');
const { ethers } = require('ethers');
const { expect } = require('chai');
const { selector } = require('../../helpers/methods');
const INVALID_ID = '0xffffffff';
const INTERFACES = {
const SIGNATURES = {
ERC165: ['supportsInterface(bytes4)'],
ERC721: [
'balanceOf(address)',
@ -81,27 +81,27 @@ const INTERFACES = {
ERC2981: ['royaltyInfo(uint256,uint256)'],
};
const INTERFACE_IDS = {};
const FN_SIGNATURES = {};
for (const k of Object.getOwnPropertyNames(INTERFACES)) {
INTERFACE_IDS[k] = makeInterfaceId.ERC165(INTERFACES[k]);
for (const fnName of INTERFACES[k]) {
// the interface id of a single function is equivalent to its function signature
FN_SIGNATURES[fnName] = makeInterfaceId.ERC165([fnName]);
}
}
const INTERFACE_IDS = Object.fromEntries(
Object.entries(SIGNATURES).map(([name, signatures]) => [
name,
ethers.toBeHex(
signatures.reduce((id, fnSig) => id ^ BigInt(selector(fnSig)), 0n),
4,
),
]),
);
function shouldSupportInterfaces(interfaces = []) {
describe('ERC165', function () {
beforeEach(function () {
this.contractUnderTest = this.mock || this.token || this.holder || this.accessControl;
this.contractUnderTest = this.mock || this.token || this.holder;
});
describe('when the interfaceId is supported', function () {
it('uses less than 30k gas', async function () {
for (const k of interfaces) {
const interfaceId = INTERFACE_IDS[k] ?? k;
expect(await this.contractUnderTest.supportsInterface.estimateGas(interfaceId)).to.be.lte(30000);
const interface = INTERFACE_IDS[k] ?? k;
expect(await this.contractUnderTest.supportsInterface.estimateGas(interface)).to.be.lte(30000);
}
});
@ -126,13 +126,18 @@ function shouldSupportInterfaces(interfaces = []) {
it('all interface functions are in ABI', async function () {
for (const k of interfaces) {
// skip interfaces for which we don't have a function list
if (INTERFACES[k] === undefined) continue;
for (const fnName of INTERFACES[k]) {
const fnSig = FN_SIGNATURES[fnName];
expect(this.contractUnderTest.abi.filter(fn => fn.signature === fnSig).length).to.equal(
1,
`did not find ${fnName}`,
);
if (SIGNATURES[k] === undefined) continue;
for (const fnSig of SIGNATURES[k]) {
// TODO: Remove Truffle case when ethersjs migration is done
if (this.contractUnderTest.abi) {
const fnSelector = selector(fnSig);
return expect(this.contractUnderTest.abi.filter(fn => fn.signature === fnSelector).length).to.equal(
1,
`did not find ${fnSig}`,
);
}
expect(!!this.contractUnderTest.interface.getFunction(fnSig), `did not find ${fnSig}`).to.be.true;
}
}
});

Loading…
Cancel
Save