Explorar el Código

Migrate `AccessControl` tests (#4694)

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
Ernesto García hace 1 año
padre
commit
2ec2ed9695

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 329 - 361
test/access/AccessControl.behavior.js


+ 12 - 5
test/access/AccessControl.test.js

@@ -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();
 });

+ 17 - 13
test/access/extensions/AccessControlDefaultAdminRules.test.js

@@ -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();
 });

+ 13 - 6
test/access/extensions/AccessControlEnumerable.test.js

@@ -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();
 });

+ 12 - 1
test/helpers/time.js

@@ -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))),
 };

+ 27 - 22
test/utils/introspection/SupportsInterface.behavior.js

@@ -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;
         }
       }
     });

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio