Compare commits

...

15 Commits

Author SHA1 Message Date
a673994de5 4.0.0 2021-03-23 12:06:54 -03:00
9b0e27c98c add missing rewrite rule in scripts/migrate-imports.js
(cherry picked from commit a3712a3288)
2021-03-22 18:08:36 +01:00
90a72f9acd Fix ERC721URIStorage in documentation
(cherry picked from commit 7c1625b0e0)
2021-03-15 16:48:43 -03:00
1ee939e7c4 4.0.0-rc.0 2021-03-09 15:38:49 +01:00
59f33c1cc1 remove extra changelog entry 2021-03-09 15:32:54 +01:00
d104ced953 fix changelog format
(cherry picked from commit 2658e01baa)
2021-03-09 15:25:22 +01:00
1fd54698ff Update lockfile (#2573)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
(cherry picked from commit 9612b891c9)
2021-03-09 15:23:05 +01:00
27fc833550 Make ERC1155.uri public (#2576)
(cherry picked from commit 5dbbda5435)
2021-03-08 17:37:25 -03:00
0b3e0d74b0 Further reorganisation of the repo (#2575)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
(cherry picked from commit f076ff5dbd)
2021-03-08 17:37:03 -03:00
d75b4cf613 Update changelog to list beta bugfix separately
(cherry picked from commit 5aab6ff81b)
2021-03-08 17:37:00 -03:00
b1e0aa487d Fix AccessControlEnumerable not tracking renounceRole (#2572)
* Fix AccessControlEnumerable not tracking renounceRole

* Updated changelog

(cherry picked from commit 7adf0d88a0)
2021-03-08 14:32:21 +01:00
6505e28c40 removes invalid character in comments (#2571)
(cherry picked from commit fc004c0ad2)
2021-03-08 14:32:09 +01:00
f07c39be8a Add ERC165 interface detection to AccessControl (#2562)
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
(cherry picked from commit 29ffe6f426)
2021-03-04 18:50:49 -03:00
69ca2ad676 Fix name of ERC721URIStorage contract in changelog
(cherry picked from commit 3d587f3043)
2021-03-03 12:50:05 -03:00
ae1e384a9a Fix prepack script
(cherry picked from commit 10c52439dd5118d4b671e12d691bfde42c987fb9)
2021-03-03 16:32:22 +01:00
28 changed files with 990 additions and 864 deletions

View File

@ -1,23 +1,29 @@
# Changelog
## 4.0.0
## 4.0.0 (2021-03-23)
* Now targeting the 0.8.x line of Solidity compilers. For 0.6.x (resp 0.7.x) support, use version 3.4.0 (resp 3.4.0-solc-0.7) of OpenZeppelin.
* `Context`: making `_msgData` return `bytes calldata` instead of `bytes memory` ([#2492](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2492))
* `ERC20`: Removed the `_setDecimals` function and the storage slot associated to decimals. ([#2502](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2502))
* `ERC20`: removed the `_setDecimals` function and the storage slot associated to decimals. ([#2502](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2502))
* `Strings`: addition of a `toHexString` function. ([#2504](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2504))
* `EnumerableMap`: change implementation to optimize for `key → value` lookups instead of enumeration. ([#2518](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2518))
* `GSN`: Deprecate GSNv1 support in favor of upcomming support for GSNv2. ([#2521](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2521))
* `ERC165`: Remove uses of storage in the base ERC165 implementation. ERC165 based contracts now use storage-less virtual functions. Old behaviour remains available in the `ERC165Storage` extension. ([#2505](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2505))
* `Initializable`: Make initializer check stricter during construction. ([#2531](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2531))
* `GSN`: deprecate GSNv1 support in favor of upcoming support for GSNv2. ([#2521](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2521))
* `ERC165`: remove uses of storage in the base ERC165 implementation. ERC165 based contracts now use storage-less virtual functions. Old behavior remains available in the `ERC165Storage` extension. ([#2505](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2505))
* `Initializable`: make initializer check stricter during construction. ([#2531](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2531))
* `ERC721`: remove enumerability of tokens from the base implementation. This feature is now provided separately through the `ERC721Enumerable` extension. ([#2511](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2511))
* `AccessControl`: removed enumerability by default for a more lightweight contract. It is now opt-in through `AccessControlEnumerable`. ([#2512](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2512))
* Meta Transactions: add `ERC2771Context` and a `MinimalForwarder` for meta-transactions. ([#2508](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2508))
* Overall reorganisation of the contract folder to improve clarity and discoverability. ([#2503](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2503))
* `ERC20Capped`: optimize gas usage of by enforcing te check directly in `_mint`. ([#2524](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2524))
* Overall reorganization of the contract folder to improve clarity and discoverability. ([#2503](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2503))
* `ERC20Capped`: optimize gas usage by enforcing the check directly in `_mint`. ([#2524](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2524))
* Rename `UpgradeableProxy` to `ERC1967Proxy`. ([#2547](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2547))
* `ERC777`: Optimize the gas costs of the constructor. ([#2551](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2551))
* `ERC721TokenUri`: Add a new extension ERC721TokenUri that implements the tokenURI behavior as it was available in 3.4.0. ([#2555](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2555))
* `ERC777`: optimize the gas costs of the constructor. ([#2551](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2551))
* `ERC721URIStorage`: add a new extension that implements the `_setTokenURI` behavior as it was available in 3.4.0. ([#2555](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2555))
* `AccessControl`: added ERC165 interface detection. ([#2562](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2562))
* `ERC1155`: make `uri` public so overloading function can call it using super. ([#2576](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2576))
### Bug fixes for beta releases
* `AccessControlEnumerable`: Fixed `renounceRole` not updating enumerable set of addresses for a role. ([#2572](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2572))
### How to upgrade from 3.x
@ -29,6 +35,10 @@ npx openzeppelin-contracts-migrate-imports
Make sure you're using git or another version control system to be able to recover from any potential error in our script.
### How to upgrade from 4.0-beta.x
Some further changes have been done between the different beta iterations. Transitions made during this period are configured in the `migrate-imports` script. Consequently, you can upgrade from any previous 4.0-beta.x version using the same script as described in the *How to upgrade from 3.x* section.
## 3.4.0 (2021-02-02)
* `BeaconProxy`: added new kind of proxy that allows simultaneous atomic upgrades. ([#2411](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2411))

View File

@ -3,6 +3,18 @@
pragma solidity ^0.8.0;
import "../utils/Context.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
/**
* @dev Contract module that allows children to implement role-based access
@ -42,7 +54,7 @@ import "../utils/Context.sol";
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context {
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping (address => bool) members;
bytes32 adminRole;
@ -79,10 +91,18 @@ abstract contract AccessControl is Context {
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId
|| super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view returns (bool) {
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
@ -92,7 +112,7 @@ abstract contract AccessControl is Context {
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view returns (bytes32) {
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
@ -106,7 +126,7 @@ abstract contract AccessControl is Context {
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) public virtual {
function grantRole(bytes32 role, address account) public virtual override {
require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to grant");
_grantRole(role, account);
@ -121,7 +141,7 @@ abstract contract AccessControl is Context {
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) public virtual {
function revokeRole(bytes32 role, address account) public virtual override {
require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to revoke");
_revokeRole(role, account);
@ -141,7 +161,7 @@ abstract contract AccessControl is Context {
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) public virtual {
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);

View File

@ -5,14 +5,30 @@ pragma solidity ^0.8.0;
import "./AccessControl.sol";
import "../utils/structs/EnumerableSet.sol";
/**
* @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
*/
interface IAccessControlEnumerable {
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}
/**
* @dev Extension of {AccessControl} that allows enumerating the members of each role.
*/
abstract contract AccessControlEnumerable is AccessControl {
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
using EnumerableSet for EnumerableSet.AddressSet;
mapping (bytes32 => EnumerableSet.AddressSet) private _roleMembers;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlEnumerable).interfaceId
|| super.supportsInterface(interfaceId);
}
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
@ -25,7 +41,7 @@ abstract contract AccessControlEnumerable is AccessControl {
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {
return _roleMembers[role].at(index);
}
@ -33,7 +49,7 @@ abstract contract AccessControlEnumerable is AccessControl {
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) public view returns (uint256) {
function getRoleMemberCount(bytes32 role) public view override returns (uint256) {
return _roleMembers[role].length();
}
@ -53,6 +69,14 @@ abstract contract AccessControlEnumerable is AccessControl {
_roleMembers[role].remove(account);
}
/**
* @dev Overload {renounceRole} to track enumerable memberships
*/
function renounceRole(bytes32 role, address account) public virtual override {
super.renounceRole(role, account);
_roleMembers[role].remove(account);
}
/**
* @dev Overload {_setupRole} to track enumerable memberships
*/

View File

@ -2,9 +2,9 @@
pragma solidity ^0.8.0;
import "./Address.sol";
import "./Context.sol";
import "./math/SafeMath.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";
import "../utils/math/SafeMath.sol";
/**
* @title PaymentSplitter

View File

@ -0,0 +1,10 @@
= Finance
[.readme-notice]
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/finance
This directory includes primitives for financial systems. We currently only offer the {PaymentSplitter} contract, but we want to grow this directory so we welcome ideas.
== PaymentSplitter
{{PaymentSplitter}}

View File

@ -1,7 +1,7 @@
= Governance
[.readme-notice]
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/access
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/governance
This directory includes primitives for on-chain governance. We currently only offer the {TimelockController} contract, that can be used as a component in a governance systems to introduce a delay between a proposal and its execution.

View File

@ -2,7 +2,7 @@
pragma solidity ^0.8.0;
import "../utils/Initializable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @title InitializableMock

View File

@ -2,7 +2,7 @@
pragma solidity ^0.8.0;
import "../utils/Initializable.sol";
import "../proxy/utils/Initializable.sol";
// Sample contracts showing upgradeability with multiple inheritance.
// Child contract inherits from Father and Mother contracts, and Father extends from Gramps.

View File

@ -2,7 +2,7 @@
pragma solidity ^0.8.0;
import "../utils/Initializable.sol";
import "../proxy/utils/Initializable.sol";
contract Implementation1 is Initializable {
uint internal _value;

View File

@ -2,7 +2,7 @@
pragma solidity ^0.8.0;
import "../utils/Initializable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @title MigratableMockV1

View File

@ -1,7 +1,7 @@
{
"name": "@openzeppelin/contracts",
"description": "Secure Smart Contract library for Solidity",
"version": "4.0.0-beta.1",
"version": "4.0.0",
"files": [
"**/*.sol",
"/build/contracts/*.json",

View File

@ -40,3 +40,7 @@ CAUTION: Using upgradeable proxies correctly and securely is a difficult task th
== Minimal Clones
{{Clones}}
== Utils
{{Initializable}}

View File

@ -3,7 +3,7 @@
// solhint-disable-next-line compiler-version
pragma solidity ^0.8.0;
import "./Address.sol";
import "../../utils/Address.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed

View File

@ -55,7 +55,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
* Clients calling this function must replace the `\{id\}` substring with the
* actual token type ID.
*/
function uri(uint256) external view virtual override returns (string memory) {
function uri(uint256) public view virtual override returns (string memory) {
return _uri;
}

View File

@ -89,6 +89,13 @@ contract ERC1155PresetMinterPauser is Context, AccessControlEnumerable, ERC1155B
_unpause();
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControlEnumerable, ERC1155) returns (bool) {
return super.supportsInterface(interfaceId);
}
function _beforeTokenTransfer(
address operator,
address from,

View File

@ -223,7 +223,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
d*
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*

View File

@ -39,7 +39,7 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel
{{ERC721Burnable}}
{{ERC721TokenUri}}
{{ERC721URIStorage}}
== Presets

View File

@ -5,7 +5,7 @@ pragma solidity ^0.8.0;
import "../ERC721.sol";
/**
* @dev ERC721 token with storage based token uri management.
* @dev ERC721 token with storage based token URI management.
*/
abstract contract ERC721URIStorage is ERC721 {
using Strings for uint256;

View File

@ -110,7 +110,7 @@ contract ERC721PresetMinterPauserAutoId is Context, AccessControlEnumerable, ERC
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721Enumerable) returns (bool) {
function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControlEnumerable, ERC721, ERC721Enumerable) returns (bool) {
return super.supportsInterface(interfaceId);
}
}

View File

@ -40,6 +40,14 @@ Finally, {Create2} contains all necessary utilities to safely use the https://bl
{{EIP712}}
== Escrow
{{ConditionalEscrow}}
{{Escrow}}
{{RefundEscrow}}
== Introspection
This set of interfaces and contracts deal with https://en.wikipedia.org/wiki/Type_introspection[type introspection] of contracts, that is, examining which functions can be called on them. This is usually referred to as a contract's _interface_.
@ -84,7 +92,3 @@ Note that, in all cases, accounts simply _declare_ their interfaces, but they ar
{{Counters}}
{{Strings}}
== Other
{{Initializable}}

1634
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{
"name": "openzeppelin-solidity",
"description": "Secure Smart Contract library for Solidity",
"version": "4.0.0-beta.1",
"version": "4.0.0",
"files": [
"/contracts/**/*.sol",
"/build/contracts/*.json",
@ -75,6 +75,5 @@
"solidity-coverage": "^0.7.11",
"solidity-docgen": "^0.5.3",
"web3": "^1.3.0"
},
"dependencies": {}
}
}

View File

@ -30,7 +30,8 @@ const pathUpdates = {
'payment/escrow/ConditionalEscrow.sol': 'utils/escrow/ConditionalEscrow.sol',
'payment/escrow/Escrow.sol': 'utils/escrow/Escrow.sol',
'payment/escrow/RefundEscrow.sol': 'utils/escrow/RefundEscrow.sol',
'payment/PaymentSplitter.sol': 'utils/PaymentSplitter.sol',
'payment/PaymentSplitter.sol': 'finance/PaymentSplitter.sol',
'utils/PaymentSplitter.sol': 'finance/PaymentSplitter.sol',
'payment/PullPayment.sol': 'security/PullPayment.sol',
'presets/ERC1155PresetMinterPauser.sol': 'token/ERC1155/presets/ERC1155PresetMinterPauser.sol',
'presets/ERC20PresetFixedSupply.sol': 'token/ERC20/presets/ERC20PresetFixedSupply.sol',
@ -40,12 +41,13 @@ const pathUpdates = {
'proxy/BeaconProxy.sol': 'proxy/beacon/BeaconProxy.sol',
// 'proxy/Clones.sol': undefined,
'proxy/IBeacon.sol': 'proxy/beacon/IBeacon.sol',
'proxy/Initializable.sol': 'utils/Initializable.sol',
'proxy/Initializable.sol': 'proxy/utils/Initializable.sol',
'utils/Initializable.sol': 'proxy/utils/Initializable.sol',
'proxy/ProxyAdmin.sol': 'proxy/transparent/ProxyAdmin.sol',
// 'proxy/Proxy.sol': undefined,
'proxy/TransparentUpgradeableProxy.sol': 'proxy/transparent/TransparentUpgradeableProxy.sol',
'proxy/UpgradeableBeacon.sol': 'proxy/beacon/UpgradeableBeacon.sol',
// 'proxy/UpgradeableProxy.sol': undefined,
'proxy/UpgradeableProxy.sol': 'proxy/ERC1967/ERC1967Proxy.sol',
'token/ERC1155/ERC1155Burnable.sol': 'token/ERC1155/extensions/ERC1155Burnable.sol',
'token/ERC1155/ERC1155Holder.sol': 'token/ERC1155/utils/ERC1155Holder.sol',
'token/ERC1155/ERC1155Pausable.sol': 'token/ERC1155/extensions/ERC1155Pausable.sol',

View File

@ -23,23 +23,21 @@ const ignorePatternsSubtrees = ignorePatterns
.concat(ignorePatterns.map(pat => path.join(pat, '**/*')))
.map(p => p.replace(/^\//, ''));
const artifactsDir = 'build/contracts';
const buildinfo = 'artifacts/build-info';
const filenames = fs.readdirSync(buildinfo);
if (filenames.length !== 1) {
throw new Error(`There should only be one file in ${buildinfo}`);
}
const solcOutput = readJSON(path.join(buildinfo, filenames[0])).output;
const artifactsDir = 'build/contracts';
let n = 0;
for (const sourcePath in solcOutput.contracts) {
const ignore = match.any(sourcePath, ignorePatternsSubtrees);
if (ignore) {
for (const contract in solcOutput.contracts[sourcePath]) {
fs.unlinkSync(path.join(artifactsDir, contract + '.json'));
n += 1;
for (const filename of filenames) {
const solcOutput = readJSON(path.join(buildinfo, filename)).output;
for (const sourcePath in solcOutput.contracts) {
const ignore = match.any(sourcePath, ignorePatternsSubtrees);
if (ignore) {
for (const contract in solcOutput.contracts[sourcePath]) {
fs.unlinkSync(path.join(artifactsDir, contract + '.json'));
n += 1;
}
}
}
}

View File

@ -1,11 +1,15 @@
const { expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
const { expect } = require('chai');
const { shouldSupportInterfaces } = require('../utils/introspection/SupportsInterface.behavior');
const DEFAULT_ADMIN_ROLE = '0x0000000000000000000000000000000000000000000000000000000000000000';
const ROLE = web3.utils.soliditySha3('ROLE');
const OTHER_ROLE = web3.utils.soliditySha3('OTHER_ROLE');
function shouldBehaveLikeAccessControl (errorPrefix, admin, authorized, other, otherAdmin, otherAuthorized) {
shouldSupportInterfaces(['AccessControl']);
describe('default admin', function () {
it('deployer has default admin role', async function () {
expect(await this.accessControl.hasRole(DEFAULT_ADMIN_ROLE, admin)).to.equal(true);
@ -156,6 +160,8 @@ function shouldBehaveLikeAccessControl (errorPrefix, admin, authorized, other, o
}
function shouldBehaveLikeAccessControlEnumerable (errorPrefix, admin, authorized, other, otherAdmin, otherAuthorized) {
shouldSupportInterfaces(['AccessControlEnumerable']);
describe('enumerating', function () {
it('role bearers can be enumerated', async function () {
await this.accessControl.grantRole(ROLE, authorized, { from: admin });
@ -173,6 +179,13 @@ function shouldBehaveLikeAccessControlEnumerable (errorPrefix, admin, authorized
expect(bearers).to.have.members([authorized, otherAuthorized]);
});
it('role enumeration should be in sync after renounceRole call', async function () {
expect(await this.accessControl.getRoleMemberCount(ROLE)).to.bignumber.equal('0');
await this.accessControl.grantRole(ROLE, admin, { from: admin });
expect(await this.accessControl.getRoleMemberCount(ROLE)).to.bignumber.equal('1');
await this.accessControl.renounceRole(ROLE, admin, { from: admin });
expect(await this.accessControl.getRoleMemberCount(ROLE)).to.bignumber.equal('0');
});
});
}

View File

@ -1,5 +1,6 @@
const { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
const { ZERO_ADDRESS } = constants;
const { shouldSupportInterfaces } = require('../../../utils/introspection/SupportsInterface.behavior');
const { expect } = require('chai');
@ -24,6 +25,8 @@ contract('ERC1155PresetMinterPauser', function (accounts) {
this.token = await ERC1155PresetMinterPauser.new(uri, { from: deployer });
});
shouldSupportInterfaces(['ERC1155', 'AccessControl', 'AccessControlEnumerable']);
it('deployer has the default admin role', async function () {
expect(await this.token.getRoleMemberCount(DEFAULT_ADMIN_ROLE)).to.be.bignumber.equal('1');
expect(await this.token.getRoleMember(DEFAULT_ADMIN_ROLE, 0)).to.equal(deployer);

View File

@ -1,5 +1,6 @@
const { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
const { ZERO_ADDRESS } = constants;
const { shouldSupportInterfaces } = require('../../../utils/introspection/SupportsInterface.behavior');
const { expect } = require('chai');
@ -19,6 +20,8 @@ contract('ERC721PresetMinterPauserAutoId', function (accounts) {
this.token = await ERC721PresetMinterPauserAutoId.new(name, symbol, baseURI, { from: deployer });
});
shouldSupportInterfaces(['ERC721', 'ERC721Enumerable', 'AccessControl', 'AccessControlEnumerable']);
it('token has correct name', async function () {
expect(await this.token.name()).to.equal(name);
});

View File

@ -39,6 +39,17 @@ const INTERFACES = {
'onERC1155Received(address,address,uint256,uint256,bytes)',
'onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)',
],
AccessControl: [
'hasRole(bytes32,address)',
'getRoleAdmin(bytes32)',
'grantRole(bytes32,address)',
'revokeRole(bytes32,address)',
'renounceRole(bytes32,address)',
],
AccessControlEnumerable: [
'getRoleMember(bytes32,uint256)',
'getRoleMemberCount(bytes32)',
],
};
const INTERFACE_IDS = {};
@ -54,7 +65,7 @@ for (const k of Object.getOwnPropertyNames(INTERFACES)) {
function shouldSupportInterfaces (interfaces = []) {
describe('Contract interface', function () {
beforeEach(function () {
this.contractUnderTest = this.mock || this.token || this.holder;
this.contractUnderTest = this.mock || this.token || this.holder || this.accessControl;
});
for (const k of interfaces) {