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 # 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. * 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)) * `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)) * `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)) * `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)) * `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 behaviour remains available in the `ERC165Storage` extension. ([#2505](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2505)) * `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)) * `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)) * `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)) * `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)) * 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)) * Overall reorganization 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)) * `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)) * 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)) * `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)) * `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 ### 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. 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) ## 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)) * `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; pragma solidity ^0.8.0;
import "../utils/Context.sol"; 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 * @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 * grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. * accounts that have been granted it.
*/ */
abstract contract AccessControl is Context { abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData { struct RoleData {
mapping (address => bool) members; mapping (address => bool) members;
bytes32 adminRole; bytes32 adminRole;
@ -79,10 +91,18 @@ abstract contract AccessControl is Context {
*/ */
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); 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`. * @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]; return _roles[role].members[account];
} }
@ -92,7 +112,7 @@ abstract contract AccessControl is Context {
* *
* To change a role's admin, use {_setRoleAdmin}. * 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; return _roles[role].adminRole;
} }
@ -106,7 +126,7 @@ abstract contract AccessControl is Context {
* *
* - the caller must have ``role``'s admin role. * - 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"); require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to grant");
_grantRole(role, account); _grantRole(role, account);
@ -121,7 +141,7 @@ abstract contract AccessControl is Context {
* *
* - the caller must have ``role``'s admin role. * - 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"); require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to revoke");
_revokeRole(role, account); _revokeRole(role, account);
@ -141,7 +161,7 @@ abstract contract AccessControl is Context {
* *
* - the caller must be `account`. * - 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"); require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account); _revokeRole(role, account);

View File

@ -5,14 +5,30 @@ pragma solidity ^0.8.0;
import "./AccessControl.sol"; import "./AccessControl.sol";
import "../utils/structs/EnumerableSet.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. * @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; using EnumerableSet for EnumerableSet.AddressSet;
mapping (bytes32 => EnumerableSet.AddressSet) private _roleMembers; 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 * @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive. * 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] * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information. * 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); 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 * @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role. * 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(); return _roleMembers[role].length();
} }
@ -53,6 +69,14 @@ abstract contract AccessControlEnumerable is AccessControl {
_roleMembers[role].remove(account); _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 * @dev Overload {_setupRole} to track enumerable memberships
*/ */

View File

@ -2,9 +2,9 @@
pragma solidity ^0.8.0; pragma solidity ^0.8.0;
import "./Address.sol"; import "../utils/Address.sol";
import "./Context.sol"; import "../utils/Context.sol";
import "./math/SafeMath.sol"; import "../utils/math/SafeMath.sol";
/** /**
* @title PaymentSplitter * @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 = Governance
[.readme-notice] [.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. 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; pragma solidity ^0.8.0;
import "../utils/Initializable.sol"; import "../proxy/utils/Initializable.sol";
/** /**
* @title InitializableMock * @title InitializableMock

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
// solhint-disable-next-line compiler-version // solhint-disable-next-line compiler-version
pragma solidity ^0.8.0; 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 * @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 * Clients calling this function must replace the `\{id\}` substring with the
* actual token type ID. * 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; return _uri;
} }

View File

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

View File

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

View File

@ -5,7 +5,7 @@ pragma solidity ^0.8.0;
import "../ERC721.sol"; 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 { abstract contract ERC721URIStorage is ERC721 {
using Strings for uint256; using Strings for uint256;

View File

@ -110,7 +110,7 @@ contract ERC721PresetMinterPauserAutoId is Context, AccessControlEnumerable, ERC
/** /**
* @dev See {IERC165-supportsInterface}. * @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); return super.supportsInterface(interfaceId);
} }
} }

View File

@ -40,6 +40,14 @@ Finally, {Create2} contains all necessary utilities to safely use the https://bl
{{EIP712}} {{EIP712}}
== Escrow
{{ConditionalEscrow}}
{{Escrow}}
{{RefundEscrow}}
== Introspection == 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_. 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}} {{Counters}}
{{Strings}} {{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", "name": "openzeppelin-solidity",
"description": "Secure Smart Contract library for Solidity", "description": "Secure Smart Contract library for Solidity",
"version": "4.0.0-beta.1", "version": "4.0.0",
"files": [ "files": [
"/contracts/**/*.sol", "/contracts/**/*.sol",
"/build/contracts/*.json", "/build/contracts/*.json",
@ -75,6 +75,5 @@
"solidity-coverage": "^0.7.11", "solidity-coverage": "^0.7.11",
"solidity-docgen": "^0.5.3", "solidity-docgen": "^0.5.3",
"web3": "^1.3.0" "web3": "^1.3.0"
}, }
"dependencies": {}
} }

View File

@ -30,7 +30,8 @@ const pathUpdates = {
'payment/escrow/ConditionalEscrow.sol': 'utils/escrow/ConditionalEscrow.sol', 'payment/escrow/ConditionalEscrow.sol': 'utils/escrow/ConditionalEscrow.sol',
'payment/escrow/Escrow.sol': 'utils/escrow/Escrow.sol', 'payment/escrow/Escrow.sol': 'utils/escrow/Escrow.sol',
'payment/escrow/RefundEscrow.sol': 'utils/escrow/RefundEscrow.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', 'payment/PullPayment.sol': 'security/PullPayment.sol',
'presets/ERC1155PresetMinterPauser.sol': 'token/ERC1155/presets/ERC1155PresetMinterPauser.sol', 'presets/ERC1155PresetMinterPauser.sol': 'token/ERC1155/presets/ERC1155PresetMinterPauser.sol',
'presets/ERC20PresetFixedSupply.sol': 'token/ERC20/presets/ERC20PresetFixedSupply.sol', 'presets/ERC20PresetFixedSupply.sol': 'token/ERC20/presets/ERC20PresetFixedSupply.sol',
@ -40,12 +41,13 @@ const pathUpdates = {
'proxy/BeaconProxy.sol': 'proxy/beacon/BeaconProxy.sol', 'proxy/BeaconProxy.sol': 'proxy/beacon/BeaconProxy.sol',
// 'proxy/Clones.sol': undefined, // 'proxy/Clones.sol': undefined,
'proxy/IBeacon.sol': 'proxy/beacon/IBeacon.sol', '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/ProxyAdmin.sol': 'proxy/transparent/ProxyAdmin.sol',
// 'proxy/Proxy.sol': undefined, // 'proxy/Proxy.sol': undefined,
'proxy/TransparentUpgradeableProxy.sol': 'proxy/transparent/TransparentUpgradeableProxy.sol', 'proxy/TransparentUpgradeableProxy.sol': 'proxy/transparent/TransparentUpgradeableProxy.sol',
'proxy/UpgradeableBeacon.sol': 'proxy/beacon/UpgradeableBeacon.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/ERC1155Burnable.sol': 'token/ERC1155/extensions/ERC1155Burnable.sol',
'token/ERC1155/ERC1155Holder.sol': 'token/ERC1155/utils/ERC1155Holder.sol', 'token/ERC1155/ERC1155Holder.sol': 'token/ERC1155/utils/ERC1155Holder.sol',
'token/ERC1155/ERC1155Pausable.sol': 'token/ERC1155/extensions/ERC1155Pausable.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, '**/*'))) .concat(ignorePatterns.map(pat => path.join(pat, '**/*')))
.map(p => p.replace(/^\//, '')); .map(p => p.replace(/^\//, ''));
const artifactsDir = 'build/contracts';
const buildinfo = 'artifacts/build-info'; const buildinfo = 'artifacts/build-info';
const filenames = fs.readdirSync(buildinfo); 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; let n = 0;
for (const sourcePath in solcOutput.contracts) { for (const filename of filenames) {
const ignore = match.any(sourcePath, ignorePatternsSubtrees); const solcOutput = readJSON(path.join(buildinfo, filename)).output;
if (ignore) { for (const sourcePath in solcOutput.contracts) {
for (const contract in solcOutput.contracts[sourcePath]) { const ignore = match.any(sourcePath, ignorePatternsSubtrees);
fs.unlinkSync(path.join(artifactsDir, contract + '.json')); if (ignore) {
n += 1; 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 { expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
const { expect } = require('chai'); const { expect } = require('chai');
const { shouldSupportInterfaces } = require('../utils/introspection/SupportsInterface.behavior');
const DEFAULT_ADMIN_ROLE = '0x0000000000000000000000000000000000000000000000000000000000000000'; const DEFAULT_ADMIN_ROLE = '0x0000000000000000000000000000000000000000000000000000000000000000';
const ROLE = web3.utils.soliditySha3('ROLE'); const ROLE = web3.utils.soliditySha3('ROLE');
const OTHER_ROLE = web3.utils.soliditySha3('OTHER_ROLE'); const OTHER_ROLE = web3.utils.soliditySha3('OTHER_ROLE');
function shouldBehaveLikeAccessControl (errorPrefix, admin, authorized, other, otherAdmin, otherAuthorized) { function shouldBehaveLikeAccessControl (errorPrefix, admin, authorized, other, otherAdmin, otherAuthorized) {
shouldSupportInterfaces(['AccessControl']);
describe('default admin', function () { describe('default admin', function () {
it('deployer has default admin role', async function () { it('deployer has default admin role', async function () {
expect(await this.accessControl.hasRole(DEFAULT_ADMIN_ROLE, admin)).to.equal(true); 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) { function shouldBehaveLikeAccessControlEnumerable (errorPrefix, admin, authorized, other, otherAdmin, otherAuthorized) {
shouldSupportInterfaces(['AccessControlEnumerable']);
describe('enumerating', function () { describe('enumerating', function () {
it('role bearers can be enumerated', async function () { it('role bearers can be enumerated', async function () {
await this.accessControl.grantRole(ROLE, authorized, { from: admin }); await this.accessControl.grantRole(ROLE, authorized, { from: admin });
@ -173,6 +179,13 @@ function shouldBehaveLikeAccessControlEnumerable (errorPrefix, admin, authorized
expect(bearers).to.have.members([authorized, otherAuthorized]); 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 { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
const { ZERO_ADDRESS } = constants; const { ZERO_ADDRESS } = constants;
const { shouldSupportInterfaces } = require('../../../utils/introspection/SupportsInterface.behavior');
const { expect } = require('chai'); const { expect } = require('chai');
@ -24,6 +25,8 @@ contract('ERC1155PresetMinterPauser', function (accounts) {
this.token = await ERC1155PresetMinterPauser.new(uri, { from: deployer }); this.token = await ERC1155PresetMinterPauser.new(uri, { from: deployer });
}); });
shouldSupportInterfaces(['ERC1155', 'AccessControl', 'AccessControlEnumerable']);
it('deployer has the default admin role', async function () { 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.getRoleMemberCount(DEFAULT_ADMIN_ROLE)).to.be.bignumber.equal('1');
expect(await this.token.getRoleMember(DEFAULT_ADMIN_ROLE, 0)).to.equal(deployer); 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 { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
const { ZERO_ADDRESS } = constants; const { ZERO_ADDRESS } = constants;
const { shouldSupportInterfaces } = require('../../../utils/introspection/SupportsInterface.behavior');
const { expect } = require('chai'); const { expect } = require('chai');
@ -19,6 +20,8 @@ contract('ERC721PresetMinterPauserAutoId', function (accounts) {
this.token = await ERC721PresetMinterPauserAutoId.new(name, symbol, baseURI, { from: deployer }); this.token = await ERC721PresetMinterPauserAutoId.new(name, symbol, baseURI, { from: deployer });
}); });
shouldSupportInterfaces(['ERC721', 'ERC721Enumerable', 'AccessControl', 'AccessControlEnumerable']);
it('token has correct name', async function () { it('token has correct name', async function () {
expect(await this.token.name()).to.equal(name); expect(await this.token.name()).to.equal(name);
}); });

View File

@ -39,6 +39,17 @@ const INTERFACES = {
'onERC1155Received(address,address,uint256,uint256,bytes)', 'onERC1155Received(address,address,uint256,uint256,bytes)',
'onERC1155BatchReceived(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 = {}; const INTERFACE_IDS = {};
@ -54,7 +65,7 @@ for (const k of Object.getOwnPropertyNames(INTERFACES)) {
function shouldSupportInterfaces (interfaces = []) { function shouldSupportInterfaces (interfaces = []) {
describe('Contract interface', function () { describe('Contract interface', function () {
beforeEach(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) { for (const k of interfaces) {