From 9edee8a7a89b846c6c0000ce1ca2734a4c26226a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 3 Apr 2020 17:15:40 -0300 Subject: [PATCH 01/24] Fix linter errors --- scripts/gen-nav.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/gen-nav.js b/scripts/gen-nav.js index c796dea6c..14d5ce99a 100644 --- a/scripts/gen-nav.js +++ b/scripts/gen-nav.js @@ -13,13 +13,13 @@ const files = proc.execFileSync( console.log('.API'); const links = files.map((file) => { - const doc = file.replace(baseDir, ''); - const title = path.parse(file).name; + const doc = file.replace(baseDir, ''); + const title = path.parse(file).name; - return { - xref: `* xref:${doc}[${startCase(title)}]`, - title, - }; + return { + xref: `* xref:${doc}[${startCase(title)}]`, + title, + }; }); // Case-insensitive sort based on titles (so 'token/ERC20' gets sorted as 'erc20') @@ -28,5 +28,5 @@ const sortedLinks = links.sort(function (a, b) { }); for (const link of sortedLinks) { - console.log(link.xref); + console.log(link.xref); } From 0292d793f3b3566cf7780207653f75d0ccff4d36 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 3 Apr 2020 20:51:14 -0300 Subject: [PATCH 02/24] add passthrough delimiters to avoid italics from underscores (#2169) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolás Venturo --- docs/contract.hbs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/contract.hbs b/docs/contract.hbs index 11ec18246..632289511 100644 --- a/docs/contract.hbs +++ b/docs/contract.hbs @@ -1,14 +1,14 @@ {{~#*inline "typed-variable-array"~}} -{{#each .}}[.var-type]#{{typeName}}#{{#if name}} [.var-name]#{{name}}#{{/if}}{{#unless @last}}, {{/unless}}{{/each}} +{{#each .}}++[.var-type]#++{{typeName}}++#++{{#if name}} ++[.var-name]#++{{name}}++#++{{/if}}{{#unless @last}}, {{/unless}}{{/each}} {{~/inline~}} {{#each linkable}} -:{{name}}: pass:normal[xref:#{{anchor}}[`{{name}}`]] +:{{name}}: pass:normal[xref:#{{anchor}}[`++{{name}}++`]] {{/each}} [.contract] [[{{anchor}}]] -=== `{{name}}` +=== `++{{name}}++` {{natspec.devdoc}} @@ -22,7 +22,7 @@ .{{contract.name}} {{/unless}} {{#each modifiers}} -* {xref-{{slug fullName~}} }[`{{name}}({{args.names}})`] +* {xref-{{slug fullName~}} }[`++{{name}}({{args.names}})++`] {{/each}} {{/each}} @@ -39,7 +39,7 @@ .{{contract.name}} {{/unless}} {{#each functions}} -* {xref-{{slug fullName~}} }[`{{name}}({{args.names}})`] +* {xref-{{slug fullName~}} }[`++{{name}}({{args.names}})++`] {{/each}} {{/each}} @@ -56,7 +56,7 @@ .{{contract.name}} {{/unless}} {{#each events}} -* {xref-{{slug fullName~}} }[`{{name}}({{args.names}})`] +* {xref-{{slug fullName~}} }[`++{{name}}({{args.names}})++`] {{/each}} {{/each}} @@ -66,7 +66,7 @@ {{#each ownModifiers}} [.contract-item] [[{{anchor}}]] -==== `{{name}}({{> typed-variable-array args}})` [.item-kind]#modifier# +==== `++{{name}}({{> typed-variable-array args}})++` [.item-kind]#modifier# {{natspec.devdoc}} @@ -75,7 +75,7 @@ {{#each ownFunctions}} [.contract-item] [[{{anchor}}]] -==== `{{name}}({{> typed-variable-array args}}){{#if outputs}} → {{> typed-variable-array outputs}}{{/if}}` [.item-kind]#{{visibility}}# +==== `++{{name}}({{> typed-variable-array args}}){{#if outputs}} → {{> typed-variable-array outputs}}{{/if}}++` [.item-kind]#{{visibility}}# {{natspec.devdoc}} @@ -84,7 +84,7 @@ {{#each ownEvents}} [.contract-item] [[{{anchor}}]] -==== `{{name}}({{> typed-variable-array args}})` [.item-kind]#event# +==== `++{{name}}({{> typed-variable-array args}})++` [.item-kind]#event# {{natspec.devdoc}} From 885378e421f6121bc79f1b7afe0fdef250e27a5b Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 3 Apr 2020 21:13:55 -0300 Subject: [PATCH 03/24] Fix some of the code formatting in docs --- CHANGELOG.md | 2 +- contracts/GSN/IRelayHub.sol | 2 +- contracts/GSN/IRelayRecipient.sol | 2 +- contracts/access/AccessControl.sol | 6 +++--- contracts/introspection/IERC1820Registry.sol | 2 +- contracts/token/ERC20/ERC20.sol | 6 +++--- contracts/token/ERC20/ERC20Burnable.sol | 2 +- contracts/token/ERC721/ERC721.sol | 4 ++-- contracts/token/ERC721/IERC721.sol | 2 +- contracts/token/ERC777/ERC777.sol | 4 ++-- docs/modules/ROOT/pages/erc777.adoc | 4 ++-- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f29774455..ce48a7730 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -127,7 +127,7 @@ Refer to the table below to adjust your inheritance list. ### Improvements * Upgraded the minimum compiler version to v0.5.2: this removes many Solidity warnings that were false positives. ([#1606](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1606)) * `ECDSA`: `recover` no longer accepts malleable signatures (those using upper-range values for `s`, or 0/1 for `v`). ([#1622](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1622)) - * `ERC721`'s transfers are now more gas efficient due to removal of unnecessary `SafeMath` calls. ([#1610](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1610)) + * ``ERC721``'s transfers are now more gas efficient due to removal of unnecessary `SafeMath` calls. ([#1610](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1610)) * Fixed variable shadowing issues. ([#1606](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1606)) ### Bugfixes diff --git a/contracts/GSN/IRelayHub.sol b/contracts/GSN/IRelayHub.sol index 520aa374c..46005cc9b 100644 --- a/contracts/GSN/IRelayHub.sol +++ b/contracts/GSN/IRelayHub.sol @@ -250,7 +250,7 @@ interface IRelayHub { function penalizeRepeatedNonce(bytes calldata unsignedTx1, bytes calldata signature1, bytes calldata unsignedTx2, bytes calldata signature2) external; /** - * @dev Penalize a relay that sent a transaction that didn't target `RelayHub`'s {registerRelay} or {relayCall}. + * @dev Penalize a relay that sent a transaction that didn't target ``RelayHub``'s {registerRelay} or {relayCall}. */ function penalizeIllegalTransaction(bytes calldata unsignedTx, bytes calldata signature) external; diff --git a/contracts/GSN/IRelayRecipient.sol b/contracts/GSN/IRelayRecipient.sol index cb5e6513e..9ae14f5a6 100644 --- a/contracts/GSN/IRelayRecipient.sol +++ b/contracts/GSN/IRelayRecipient.sol @@ -17,7 +17,7 @@ interface IRelayRecipient { * * The relay request was originated by `from` and will be served by `relay`. `encodedFunction` is the relayed call * calldata, so its first four bytes are the function selector. The relayed call will be forwarded `gasLimit` gas, - * and the transaction executed with a gas price of at least `gasPrice`. `relay`'s fee is `transactionFee`, and the + * and the transaction executed with a gas price of at least `gasPrice`. ``relay``'s fee is `transactionFee`, and the * recipient will be charged at most `maxPossibleCharge` (in wei). `nonce` is the sender's (`from`) nonce for * replay attack protection in {IRelayHub}, and `approvalData` is a optional parameter that can be used to hold a signature * over all or some of the previous values. diff --git a/contracts/access/AccessControl.sol b/contracts/access/AccessControl.sol index 90a8f1a98..00f2efc98 100644 --- a/contracts/access/AccessControl.sol +++ b/contracts/access/AccessControl.sol @@ -114,7 +114,7 @@ abstract contract AccessControl is Context { * * Requirements: * - * - the caller must have `role`'s admin role. + * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual { require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant"); @@ -129,7 +129,7 @@ abstract contract AccessControl is Context { * * Requirements: * - * - the caller must have `role`'s admin role. + * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual { require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke"); @@ -174,7 +174,7 @@ abstract contract AccessControl is Context { } /** - * @dev Sets `adminRole` as `role`'s admin role. + * @dev Sets `adminRole` as ``role``'s admin role. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { _roles[role].adminRole = adminRole; diff --git a/contracts/introspection/IERC1820Registry.sol b/contracts/introspection/IERC1820Registry.sol index 618b6ef2b..28e23dac7 100644 --- a/contracts/introspection/IERC1820Registry.sol +++ b/contracts/introspection/IERC1820Registry.sol @@ -38,7 +38,7 @@ interface IERC1820Registry { function getManager(address account) external view returns (address); /** - * @dev Sets the `implementer` contract as `account`'s implementer for + * @dev Sets the `implementer` contract as ``account``'s implementer for * `interfaceHash`. * * `account` being the zero address is an alias for the caller's address. diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index dee5b916b..ac514c483 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -145,7 +145,7 @@ contract ERC20 is Context, IERC20 { * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. - * - the caller must have allowance for `sender`'s tokens of at least + * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { @@ -294,10 +294,10 @@ contract ERC20 is Context, IERC20 { * * Calling conditions: * - * - when `from` and `to` are both non-zero, `amount` of `from`'s tokens + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. - * - when `to` is zero, `amount` of `from`'s tokens will be burned. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks]. diff --git a/contracts/token/ERC20/ERC20Burnable.sol b/contracts/token/ERC20/ERC20Burnable.sol index c7a95e3e2..83cbb5ff0 100644 --- a/contracts/token/ERC20/ERC20Burnable.sol +++ b/contracts/token/ERC20/ERC20Burnable.sol @@ -26,7 +26,7 @@ abstract contract ERC20Burnable is Context, ERC20 { * * Requirements: * - * - the caller must have allowance for `accounts`'s tokens of at least + * - the caller must have allowance for ``accounts``'s tokens of at least * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 17f7efff6..9aba35129 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -501,10 +501,10 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable * * Calling conditions: * - * - when `from` and `to` are both non-zero, `from`'s `tokenId` will be + * - when `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - when `from` is zero, `tokenId` will be minted for `to`. - * - when `to` is zero, `from`'s `tokenId` will be burned. + * - when `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks]. diff --git a/contracts/token/ERC721/IERC721.sol b/contracts/token/ERC721/IERC721.sol index c630b0157..88a1cd2c8 100644 --- a/contracts/token/ERC721/IERC721.sol +++ b/contracts/token/ERC721/IERC721.sol @@ -11,7 +11,7 @@ interface IERC721 is IERC165 { event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** - * @dev Returns the number of NFTs in `owner`'s account. + * @dev Returns the number of NFTs in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); diff --git a/contracts/token/ERC777/ERC777.sol b/contracts/token/ERC777/ERC777.sol index d76276377..7f130ee59 100644 --- a/contracts/token/ERC777/ERC777.sol +++ b/contracts/token/ERC777/ERC777.sol @@ -482,10 +482,10 @@ contract ERC777 is Context, IERC777, IERC20 { * * Calling conditions: * - * - when `from` and `to` are both non-zero, `from`'s `tokenId` will be + * - when `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - when `from` is zero, `tokenId` will be minted for `to`. - * - when `to` is zero, `from`'s `tokenId` will be burned. + * - when `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks]. diff --git a/docs/modules/ROOT/pages/erc777.adoc b/docs/modules/ROOT/pages/erc777.adoc index 9d32a53d5..242b15f0e 100644 --- a/docs/modules/ROOT/pages/erc777.adoc +++ b/docs/modules/ROOT/pages/erc777.adoc @@ -37,7 +37,7 @@ contract GLDToken is ERC777 { In this case, we'll be extending from the xref:api:token/ERC777.adoc#ERC777[`ERC777`] contract, which provides an implementation with compatibility support for ERC20. The API is quite similar to that of xref:api:token/ERC777.adoc#ERC777[`ERC777`], and we'll once again make use of xref:api:token/ERC777.adoc#ERC777-_mint-address-address-uint256-bytes-bytes-[`_mint`] to assign the `initialSupply` to the deployer account. Unlike xref:api:token/ERC20.adoc#ERC20-_mint-address-uint256-[ERC20's `_mint`], this one includes some extra parameters, but you can safely ignore those for now. -You'll notice both xref:api:token/ERC777.adoc#IERC777-name--[`name`] and xref:api:token/ERC777.adoc#IERC777-symbol--[`symbol`] are assigned, but not xref:api:token/ERC777.adoc#ERC777-decimals--[`decimals`]. The ERC777 specification makes it mandatory to include support for these functions (unlike ERC20, where it is optional and we had to include xref:api:token/ERC20.adoc#ERC20Detailed[`ERC20Detailed`]), but also mandates that `decimals` always returns a fixed value of `18`, so there's no need to set it ourselves. For a review of `decimals`'s role and importance, refer back to our xref:erc20.adoc#a-note-on-decimals[ERC20 guide]. +You'll notice both xref:api:token/ERC777.adoc#IERC777-name--[`name`] and xref:api:token/ERC777.adoc#IERC777-symbol--[`symbol`] are assigned, but not xref:api:token/ERC777.adoc#ERC777-decimals--[`decimals`]. The ERC777 specification makes it mandatory to include support for these functions (unlike ERC20, where it is optional and we had to include xref:api:token/ERC20.adoc#ERC20Detailed[`ERC20Detailed`]), but also mandates that `decimals` always returns a fixed value of `18`, so there's no need to set it ourselves. For a review of ``decimals``'s role and importance, refer back to our xref:erc20.adoc#a-note-on-decimals[ERC20 guide]. Finally, we'll need to set the xref:api:token/ERC777.adoc#IERC777-defaultOperators--[`defaultOperators`]: special accounts (usually other smart contracts) that will be able to transfer tokens on behalf of their holders. If you're not planning on using operators in your token, you can simply pass an empty array. _Stay tuned for an upcoming in-depth guide on ERC777 operators!_ @@ -49,7 +49,7 @@ That's it for a basic token contract! We can now deploy it, and use the same xre 1000 ---- -To move tokens from one account to another, we can use both xref:api:token/ERC777.adoc#ERC777-transfer-address-uint256-[`ERC20`'s `transfer`] method, or the new xref:api:token/ERC777.adoc#ERC777-send-address-uint256-bytes-[`ERC777`'s `send`], which fulfills a very similar role, but adds an optional `data` field: +To move tokens from one account to another, we can use both xref:api:token/ERC777.adoc#ERC777-transfer-address-uint256-[``ERC20``'s `transfer`] method, or the new xref:api:token/ERC777.adoc#ERC777-send-address-uint256-bytes-[``ERC777``'s `send`], which fulfills a very similar role, but adds an optional `data` field: [source,javascript] ---- From 05d1618d01456eee27e2d2b46cd9f1faa1c4cd48 Mon Sep 17 00:00:00 2001 From: Andrew B Coathup <28278242+abcoathup@users.noreply.github.com> Date: Tue, 7 Apr 2020 21:45:48 +1000 Subject: [PATCH 04/24] Update Contracts docs to make examples compile (#2170) * Update access-control.adoc to make compile Add call to `ERC20("MyToken", "TKN")` in `MyToken` constructor * Update access-control.adoc to make compile Add call to `ERC20("MyToken", "TKN")` in `MyToken` constructor * Update access-control.adoc MyToken formatting * Update erc20-supply.adoc to make compile Add call to `ERC20("MyToken", "TKN")` in `ERC20FixedSupply` constructor * Update erc20-supply.adoc to make compile Add constructor to `ERC20WithMinerReward` * Update erc20-supply.adoc to make compile In `MinerRewardMinter` use `ERC20MinterPauser` * Update erc20-supply.adoc to make compile Add constructor and override to `ERC20WithAutoMinerReward` * Update erc777.adoc to make compile * Update gsn-strategies.adoc to make compile * Update gsn-strategies.adoc to make compile Fix imports, add overrides, and revert reason to `MyContract` --- docs/modules/ROOT/pages/access-control.adoc | 10 +++++----- docs/modules/ROOT/pages/erc20-supply.adoc | 12 ++++++++---- docs/modules/ROOT/pages/erc777.adoc | 4 ++-- docs/modules/ROOT/pages/gsn-strategies.adoc | 16 ++++++++++++---- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/docs/modules/ROOT/pages/access-control.adoc b/docs/modules/ROOT/pages/access-control.adoc index e347de1f5..5fd857c54 100644 --- a/docs/modules/ROOT/pages/access-control.adoc +++ b/docs/modules/ROOT/pages/access-control.adoc @@ -67,7 +67,7 @@ contract MyToken is ERC20, AccessControl { // Create a new role identifier for the minter role bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - constructor(address minter) public { + constructor(address minter) public ERC20("MyToken", "TKN") { // Grant the minter role to a specified account _setupRole(MINTER_ROLE, minter); } @@ -97,7 +97,7 @@ contract MyToken is ERC20, AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); - constructor(address minter, address burner) public { + constructor(address minter, address burner) public ERC20("MyToken", "TKN") { _setupRole(MINTER_ROLE, minter); _setupRole(BURNER_ROLE, burner); } @@ -109,7 +109,7 @@ contract MyToken is ERC20, AccessControl { function burn(address from, uint256 amount) public { require(hasRole(BURNER_ROLE, msg.sender), "Caller is not a burner"); - _burn(from, amount); + _burn(from, amount); } } ---- @@ -140,7 +140,7 @@ contract MyToken is ERC20, AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); - constructor() ERC20("MyToken", "TKN") public { + constructor() public ERC20("MyToken", "TKN") { // Grant the contract deployer the default admin role: it will be able // to grant and revoke any roles _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); @@ -153,7 +153,7 @@ contract MyToken is ERC20, AccessControl { function burn(address from, uint256 amount) public { require(hasRole(BURNER_ROLE, msg.sender), "Caller is not a burner"); - _burn(from, amount); + _burn(from, amount); } } ---- diff --git a/docs/modules/ROOT/pages/erc20-supply.adoc b/docs/modules/ROOT/pages/erc20-supply.adoc index 705935c75..0e5eb5977 100644 --- a/docs/modules/ROOT/pages/erc20-supply.adoc +++ b/docs/modules/ROOT/pages/erc20-supply.adoc @@ -26,7 +26,7 @@ Starting with Contracts v2 this pattern is not only discouraged, but disallowed. [source,solidity] ---- contract ERC20FixedSupply is ERC20 { - constructor() public { + constructor() public ERC20("Fixed", "FIX") { _mint(msg.sender, 1000); } } @@ -44,6 +44,8 @@ The mechanism we will implement is a token reward for the miners that produce Et [source,solidity] ---- contract ERC20WithMinerReward is ERC20 { + constructor() public ERC20("Reward", "RWD") {} + function mintMinerReward() public { _mint(block.coinbase, 1000); } @@ -64,9 +66,9 @@ The accounts with the minter role don't need to be externally owned, though, and [source,solidity] ---- contract MinerRewardMinter { - ERC20DeployReady _token; + ERC20MinterPauser _token; - constructor(ERC20DeployReady token) public { + constructor(ERC20MinterPauser token) public { _token = token; } @@ -90,11 +92,13 @@ Adding to our previous supply mechanism, we can use this to mint a miner reward [source,solidity] ---- contract ERC20WithAutoMinerReward is ERC20 { + constructor() public ERC20("Reward", "RWD") {} + function _mintMinerReward() internal { _mint(block.coinbase, 1000); } - function _transfer(address from, address to, uint256 value) internal { + function _transfer(address from, address to, uint256 value) internal override { _mintMinerReward(); super._transfer(from, to, value); } diff --git a/docs/modules/ROOT/pages/erc777.adoc b/docs/modules/ROOT/pages/erc777.adoc index 242b15f0e..d1d73e90e 100644 --- a/docs/modules/ROOT/pages/erc777.adoc +++ b/docs/modules/ROOT/pages/erc777.adoc @@ -18,7 +18,7 @@ We will replicate the `GLD` example of the xref:erc20.adoc#constructing-an-erc20 [source,solidity] ---- -pragma solidity ^0.5.0; +pragma solidity ^0.6.0; import "@openzeppelin/contracts/token/ERC777/ERC777.sol"; @@ -30,7 +30,7 @@ contract GLDToken is ERC777 { ERC777("Gold", "GLD", defaultOperators) public { - _mint(msg.sender, msg.sender, initialSupply, "", ""); + _mint(msg.sender, initialSupply, "", ""); } } ---- diff --git a/docs/modules/ROOT/pages/gsn-strategies.adoc b/docs/modules/ROOT/pages/gsn-strategies.adoc index c6d34ebe4..13228abe9 100644 --- a/docs/modules/ROOT/pages/gsn-strategies.adoc +++ b/docs/modules/ROOT/pages/gsn-strategies.adoc @@ -59,7 +59,7 @@ Instead of using `GSNRecipient` directly, your GSN recipient contract will inste [source,solidity] ---- -import "@openzeppelin/contracts/GSN/GSNRecipientSignature"; +import "@openzeppelin/contracts/GSN/GSNRecipientSignature.sol"; contract MyContract is GSNRecipientSignature { constructor(address trustedSigner) public GSNRecipientSignature(trustedSigner) { @@ -106,8 +106,8 @@ Your GSN recipient contract needs to inherit from `GSNRecipientERC20Fee` along w [source,solidity] ---- -import "@openzeppelin/contracts/GSN/GSNRecipientERC20Fee"; -import "@openzeppelin/contracts/access/AccessControl"; +import "@openzeppelin/contracts/GSN/GSNRecipientERC20Fee.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; contract MyContract is GSNRecipientERC20Fee, AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); @@ -116,8 +116,16 @@ contract MyContract is GSNRecipientERC20Fee, AccessControl { _setupRole(MINTER_ROLE, _msgSender()); } + function _msgSender() internal view override(Context, GSNRecipient) returns (address payable) { + return GSNRecipient._msgSender(); + } + + function _msgData() internal view override(Context, GSNRecipient) returns (bytes memory) { + return GSNRecipient._msgData(); + } + function mint(address account, uint256 amount) public { - require(hasRole(MINTER_ROLE, _msgSender())); + require(hasRole(MINTER_ROLE, _msgSender()), "Caller is not a minter"); _mint(account, amount); } } From e03c05774b3443ad13b2f646341ed3dd7c1538f1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2020 13:21:09 -0300 Subject: [PATCH 05/24] Bump solhint from 3.0.0-rc.6 to 3.0.0-rc.7 (#2183) Bumps [solhint](https://github.com/protofire/solhint) from 3.0.0-rc.6 to 3.0.0-rc.7. - [Release notes](https://github.com/protofire/solhint/releases) - [Changelog](https://github.com/protofire/solhint/blob/master/CHANGELOG.md) - [Commits](https://github.com/protofire/solhint/compare/v3.0.0-rc.6...v3.0.0-rc.7) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- package-lock.json | 22 +++++++++++----------- package.json | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 584648521..18f7c7db1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2546,6 +2546,12 @@ "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", "dev": true }, + "@solidity-parser/parser": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.5.2.tgz", + "integrity": "sha512-uRyvnvVYmgNmTBpWDbBsH/0kPESQhQpEc4KsvMRLVzFJ1o1s0uIv0Y6Y9IB5vI1Dwz2CbS4X/y4Wyw/75cTFnQ==", + "dev": true + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -33642,11 +33648,12 @@ } }, "solhint": { - "version": "3.0.0-rc.6", - "resolved": "https://registry.npmjs.org/solhint/-/solhint-3.0.0-rc.6.tgz", - "integrity": "sha512-HzNvpzCSePrK+6zS8aFWBJyoc2b0ch6o5CibOZ3hBS7rAE/FgDGtayNgSddDk0v6zfD5xCWfLqp/ZoIyWHHpJg==", + "version": "3.0.0-rc.7", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-3.0.0-rc.7.tgz", + "integrity": "sha512-oXSfE90STaBMlyT0mUl9VdnfKf6wlBeWVBMZRO6oztZGnaapU26CqJZ5ctiNi3pK6/bPnQl3RIXBioKzv+woOQ==", "dev": true, "requires": { + "@solidity-parser/parser": "^0.5.2", "ajv": "^6.6.1", "antlr4": "4.7.1", "ast-parents": "0.0.1", @@ -33660,8 +33667,7 @@ "js-yaml": "^3.12.0", "lodash": "^4.17.11", "prettier": "^1.14.3", - "semver": "^6.3.0", - "solidity-parser-diligence": "^0.4.18" + "semver": "^6.3.0" }, "dependencies": { "acorn": { @@ -33925,12 +33931,6 @@ "integrity": "sha512-4jtxasNGmyC0midtjH/lTFPZYvTTUMy6agYcF+HoMnzW8+cqo3piFrINb4ZCzpPW+7tTVFCGa5ubP34zOzeuMg==", "dev": true }, - "solidity-parser-diligence": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/solidity-parser-diligence/-/solidity-parser-diligence-0.4.18.tgz", - "integrity": "sha512-mauO/qG2v59W9sOn5TYV2dS7+fvFKqIHwiku+TH82e1Yca4H8s6EDG12ZpXO2cmgLlCKX3FOqqC73aYLB8WwNg==", - "dev": true - }, "solidity-parser-sc": { "version": "github:maxsam4/solidity-parser#3f0a30b97b460861654771871bcd970e73d47459", "from": "github:maxsam4/solidity-parser#solidity-0.5", diff --git a/package.json b/package.json index c0584ee4a..5ffe1ee8e 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "lodash.zip": "^4.2.0", "micromatch": "^4.0.2", "mocha": "^7.1.1", - "solhint": "^3.0.0-rc.6", + "solhint": "^3.0.0-rc.7", "solidity-coverage": "github:rotcivegaf/solidity-coverage#5875f5b7bc74d447f3312c9c0e9fc7814b482477", "solidity-docgen": "^0.4.1" }, From 281bcb747ed116e8fefb3ed53bf968acf532198f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2020 13:30:27 -0300 Subject: [PATCH 06/24] Bump @openzeppelin/cli from 2.8.0 to 2.8.1 (#2182) Bumps [@openzeppelin/cli](https://github.com/OpenZeppelin/openzeppelin-sdk) from 2.8.0 to 2.8.1. - [Release notes](https://github.com/OpenZeppelin/openzeppelin-sdk/releases) - [Commits](https://github.com/OpenZeppelin/openzeppelin-sdk/compare/v2.8.0...v2.8.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- package-lock.json | 947 +++++++--------------------------------------- package.json | 2 +- 2 files changed, 148 insertions(+), 801 deletions(-) diff --git a/package-lock.json b/package-lock.json index 18f7c7db1..a6b5ac500 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,16 +62,16 @@ } }, "@firebase/analytics": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.3.0.tgz", - "integrity": "sha512-EEHuK+OcWH6UxufRLVU3lAJ4rmm7aVHmcgkhE9ZQJQy5c+w7QTLvVpGqtrpqD+cYyIBJkFBKJB8NziVyqKwQHw==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.3.2.tgz", + "integrity": "sha512-z4mYytlmnNipXQrGB6bN0tzWa9GzCtK0M2HD86C9OFYpwBeDQGc3UQPAM6kbfkv50Mnl4vlS5Ta2qEw/CvWwug==", "dev": true, "requires": { "@firebase/analytics-types": "0.3.0", - "@firebase/component": "0.1.8", - "@firebase/installations": "0.4.6", - "@firebase/logger": "0.2.0", - "@firebase/util": "0.2.43", + "@firebase/component": "0.1.9", + "@firebase/installations": "0.4.7", + "@firebase/logger": "0.2.1", + "@firebase/util": "0.2.44", "tslib": "1.11.1" }, "dependencies": { @@ -90,15 +90,15 @@ "dev": true }, "@firebase/app": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.0.tgz", - "integrity": "sha512-utFL07aO64ZVs9g79cv1KHomtLdKkkAeKN5e8G9NlXXuO6dZXhcHLbOmKY1AfwrkAvUzPEKkFFY3dytOIt+nlg==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.1.tgz", + "integrity": "sha512-KSzSFQfiJgxi+7Ff/EZQcdvCnqKj2db9xa7I8z1UoRIRez9e0Q6+GpW3mrSVmmSCrBbKYsOO/SJh5NaFot0evg==", "dev": true, "requires": { "@firebase/app-types": "0.6.0", - "@firebase/component": "0.1.8", - "@firebase/logger": "0.2.0", - "@firebase/util": "0.2.43", + "@firebase/component": "0.1.9", + "@firebase/logger": "0.2.1", + "@firebase/util": "0.2.44", "dom-storage": "2.1.0", "tslib": "1.11.1", "xmlhttprequest": "1.8.0" @@ -119,9 +119,9 @@ "dev": true }, "@firebase/auth": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.14.1.tgz", - "integrity": "sha512-LE+QED10cjp28jJ7wwIY58HQBXoJioEWiQy7iQS8Fo2UxHGY5BvGjwnxX4yyszQPbcZZRLDSlBIUaYfog+rdEA==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.14.2.tgz", + "integrity": "sha512-5HaEGne2JbcVvzK9FeOEGi8NNQwq00thmL88uduqI8LTXHSOWaC8Y4El9DesVu6aFEOXELpf7W4I34CG9WwjlA==", "dev": true, "requires": { "@firebase/auth-types": "0.10.0" @@ -140,12 +140,12 @@ "dev": true }, "@firebase/component": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.8.tgz", - "integrity": "sha512-kzuCF+NVympQk3gcsHldOmDRVPVndECi6O9Wvd47HTEQYO9HsZWfOM1fHUvvHAijSzNi16p4NSM7UziuBQBL4w==", + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.9.tgz", + "integrity": "sha512-i58GsVpxBGnKn1rx2RCAH0rk1Ldp6WterfBNDHyxmuyRO6BaZAgvxrZ3Ku1/lqiI7XMbmmRpP3emmwrStbFt9Q==", "dev": true, "requires": { - "@firebase/util": "0.2.43", + "@firebase/util": "0.2.44", "tslib": "1.11.1" }, "dependencies": { @@ -158,16 +158,16 @@ } }, "@firebase/database": { - "version": "0.5.24", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.5.24.tgz", - "integrity": "sha512-9whAQzU8cxDUKGBWCT/aHVmqfyzCP2RkGhbZi2oHpMrmvht7cuBtXtUbDD5R8WomniCOUP8rtQfmCFI7V9ehYw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.0.tgz", + "integrity": "sha512-b1wt4BpzFOXxAaUtkFqfoeZzmZIQ3sLiznqOYaAROnK2JMxpFF41Nh9wZ2tCze6rOkpN+3Kx33hsPCsrQcn0WQ==", "dev": true, "requires": { "@firebase/auth-interop-types": "0.1.4", - "@firebase/component": "0.1.8", - "@firebase/database-types": "0.4.14", - "@firebase/logger": "0.2.0", - "@firebase/util": "0.2.43", + "@firebase/component": "0.1.9", + "@firebase/database-types": "0.5.0", + "@firebase/logger": "0.2.1", + "@firebase/util": "0.2.44", "faye-websocket": "0.11.3", "tslib": "1.11.1" }, @@ -181,27 +181,27 @@ } }, "@firebase/database-types": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.4.14.tgz", - "integrity": "sha512-+D41HWac0HcvwMi+0dezEdSOZHpVjPKPNmpQiW2GDuS5kk27/v1jxc9v7F4ALLtpxbVcn16UZl5PqEkcS9H2Xg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.5.0.tgz", + "integrity": "sha512-6/W3frFznYOALtw2nrWVPK2ytgdl89CzTqVBHCCGf22wT6uKU63iDBo+Nw+7olFGpD15O0zwYalFIcMZ27tkew==", "dev": true, "requires": { "@firebase/app-types": "0.6.0" } }, "@firebase/firestore": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.13.0.tgz", - "integrity": "sha512-GctO+sxLqOnY8SkBN5Z5p1nUYRX+yWSc9Kcx9nIPbUZ0WqBM5BaSlBHZHTFtjmJxS+0j/Y8Mu7c6qm6q5rVnjA==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.14.0.tgz", + "integrity": "sha512-JpwP6LWtNRjCtRbRvzhdtJ1tHL6r0MjCvmMr2Nv7bKmcjqoN8FiP+fZ9KkiZiqsSUhNsFFajyvx9n7R6vC+d2w==", "dev": true, "requires": { - "@firebase/component": "0.1.8", + "@firebase/component": "0.1.9", "@firebase/firestore-types": "1.10.1", - "@firebase/logger": "0.2.0", - "@firebase/util": "0.2.43", + "@firebase/logger": "0.2.1", + "@firebase/util": "0.2.44", "@firebase/webchannel-wrapper": "0.2.38", + "@grpc/grpc-js": "0.7.5", "@grpc/proto-loader": "^0.5.0", - "grpc": "1.24.2", "tslib": "1.11.1" }, "dependencies": { @@ -220,12 +220,12 @@ "dev": true }, "@firebase/functions": { - "version": "0.4.38", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.38.tgz", - "integrity": "sha512-t5QkJg251FmIEEi2mh3Xrf7Q3yonSLRaUW/vhgze7A3Xy3uTIUT3BVNWuKaRmg1n0PgKQaBHCjlDoLJAdSpujg==", + "version": "0.4.40", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.40.tgz", + "integrity": "sha512-Yd0P+/xLt2Lc7AJpi1zff6xjVcJXpT7coTCBjb+58RQhECkoEh1ESx46VzoUGy+4ldoh/ZFFU7p0d/lG/+wDvg==", "dev": true, "requires": { - "@firebase/component": "0.1.8", + "@firebase/component": "0.1.9", "@firebase/functions-types": "0.3.16", "@firebase/messaging-types": "0.4.4", "isomorphic-fetch": "2.2.1", @@ -247,14 +247,14 @@ "dev": true }, "@firebase/installations": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.6.tgz", - "integrity": "sha512-ey8cE2ldRO4pYqg0lCWQ+XFLETHZWha3Hw1CnYJjLivk4FMM8u/es3Oa257wwtYXAUfr0UsPDfHFgYME9E9EhA==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.7.tgz", + "integrity": "sha512-Fz9B/H58xfkAnDGVTW1V/73Jd5LAN9o5dpz1K3+u2W+zp0iU6HoRTwm9Bgk+aV6/0FYjqmtYEDjK8T0OYPoIQA==", "dev": true, "requires": { - "@firebase/component": "0.1.8", + "@firebase/component": "0.1.9", "@firebase/installations-types": "0.3.3", - "@firebase/util": "0.2.43", + "@firebase/util": "0.2.44", "idb": "3.0.2", "tslib": "1.11.1" }, @@ -274,21 +274,21 @@ "dev": true }, "@firebase/logger": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.0.tgz", - "integrity": "sha512-qOMnAh1JY9NkYUEy3iFviiFq0dCvk6qN2DsRy2Y7eAhHR6RqwA47l1kI+0MIXmSzlJ9akXjWAXxV5ijzr68Big==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.1.tgz", + "integrity": "sha512-H4nttTqUzEw3TA/JYl8ma6oMSNKHcdpEWV2L2qA+ZEcpM2OLAzagi//DrYBFR5xpPb17IGagpzSxFgx937Sq/A==", "dev": true }, "@firebase/messaging": { - "version": "0.6.10", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.6.10.tgz", - "integrity": "sha512-WYnKEffG6m0EMHzib8KCWVUGno1cuBC13RrOfGWOCv/whdy9QCIZgMxH/NsY3BrYst8FnjuXEU16fi5AEf4qbg==", + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.6.12.tgz", + "integrity": "sha512-U5piZd/0JFI4/2ZqTiIGYPcQBeTit6fTUbozGn2RSKcQw6WuNb9QJDbTZCzo1BzrHf1zoIqyakggL2AvIq48vA==", "dev": true, "requires": { - "@firebase/component": "0.1.8", - "@firebase/installations": "0.4.6", + "@firebase/component": "0.1.9", + "@firebase/installations": "0.4.7", "@firebase/messaging-types": "0.4.4", - "@firebase/util": "0.2.43", + "@firebase/util": "0.2.44", "idb": "3.0.2", "tslib": "1.11.1" }, @@ -308,16 +308,16 @@ "dev": true }, "@firebase/performance": { - "version": "0.2.36", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.2.36.tgz", - "integrity": "sha512-nMx3gT+ZD86MV5n460XFA1o75YYMGcs2MXrJa462rfUQtqOrtOOvdUvVtmE6cLrHsL4Y83B+VBWKHzACIPghPw==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.3.0.tgz", + "integrity": "sha512-206klc2wzajagbHlR7T2GWvFHsfoRMMWLa2K3GIe6ikDGlPYa/F2byXYzv6e3mSOw6aKLSbTVcIaLBBourpOTA==", "dev": true, "requires": { - "@firebase/component": "0.1.8", - "@firebase/installations": "0.4.6", - "@firebase/logger": "0.2.0", + "@firebase/component": "0.1.9", + "@firebase/installations": "0.4.7", + "@firebase/logger": "0.2.1", "@firebase/performance-types": "0.0.12", - "@firebase/util": "0.2.43", + "@firebase/util": "0.2.44", "tslib": "1.11.1" }, "dependencies": { @@ -361,16 +361,16 @@ } }, "@firebase/remote-config": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.17.tgz", - "integrity": "sha512-jIRHXih0krVTNGYMewFVIaX8WPE1iS06fV4oMMHCCSSforGodv535uVZZ41Il29Q+22zOcyJvahoc990V0cFoA==", + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.18.tgz", + "integrity": "sha512-ufbhnP3O6bRYs74jFIyYZ0dPsv/PsMSmGs669Os5SkEdfjEWX8hnhssfuZCg5VfJQiCrqoSQD/KfPGACmeBcbQ==", "dev": true, "requires": { - "@firebase/component": "0.1.8", - "@firebase/installations": "0.4.6", - "@firebase/logger": "0.2.0", + "@firebase/component": "0.1.9", + "@firebase/installations": "0.4.7", + "@firebase/logger": "0.2.1", "@firebase/remote-config-types": "0.1.8", - "@firebase/util": "0.2.43", + "@firebase/util": "0.2.44", "tslib": "1.11.1" }, "dependencies": { @@ -389,14 +389,14 @@ "dev": true }, "@firebase/storage": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.30.tgz", - "integrity": "sha512-wapt4+NiEqTiLKPpsy+XbdLTN99pkqjf46Z7zqeS+vh+61cJsUT8M7YBfBb0ZN+dY6gnI5QNzviiKpykhJQbVA==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.31.tgz", + "integrity": "sha512-b5rwcMa89mFnKDlhFmGRC0QFpOgqGoNVn4klJDvSnpRGmwOcByQXoos8w1IWP0DW+EWhHcafy7DvUHFlr70onw==", "dev": true, "requires": { - "@firebase/component": "0.1.8", + "@firebase/component": "0.1.9", "@firebase/storage-types": "0.3.11", - "@firebase/util": "0.2.43", + "@firebase/util": "0.2.44", "tslib": "1.11.1" }, "dependencies": { @@ -415,9 +415,9 @@ "dev": true }, "@firebase/util": { - "version": "0.2.43", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.43.tgz", - "integrity": "sha512-4gGlvcoOJ48xO6PH59UOHLjvImdYXANF/1d0ao60fbiJDIKxJqMksXw3UF2zsUrRkyCOqIDLeiVuF18vffXP+g==", + "version": "0.2.44", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.44.tgz", + "integrity": "sha512-yWnFdeuz7P0QC4oC77JyPdAQ/rTGPDfhHcR5WsoMsKBBHTyqEhaKWL9HeRird+p3AL9M4++ep0FYFNd1UKU3Wg==", "dev": true, "requires": { "tslib": "1.11.1" @@ -437,10 +437,27 @@ "integrity": "sha512-mp1XmAJsuqaSWm5WQYo7R0zfZWe9EmwMCxsxkKr+ubLOumyNy4NG5aV45hEpFTosQv4myXpiCiS4GFE9mNqLZQ==", "dev": true }, + "@grpc/grpc-js": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-0.7.5.tgz", + "integrity": "sha512-hhWT+vHPtG4tn0zZJw4ndfv730pBPb+lhJfvQhc7ANBvqixtlNOaXm9VNI98wYF/em0PnrskXnOr8rHh96zjlg==", + "dev": true, + "requires": { + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "@grpc/proto-loader": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.3.tgz", - "integrity": "sha512-8qvUtGg77G2ZT2HqdqYoM/OY97gQd/0crSG34xNmZ4ZOsv3aQT/FQV9QfZPazTGna6MIoyUd+u6AxsoZjJ/VMQ==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.4.tgz", + "integrity": "sha512-HTM4QpI9B2XFkPz7pjwMyMgZchJ93TVkL3kWPW8GDMDKYxsMnmf4w2TNMJK7+KNiYHS5cJrCEAFlF+AwtXWVPA==", "dev": true, "requires": { "lodash.camelcase": "^4.3.0", @@ -714,9 +731,9 @@ } }, "@openzeppelin/cli": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/cli/-/cli-2.8.0.tgz", - "integrity": "sha512-8Jlz9+LGXkI+21fJwFXF8JcFWL0oT4/c9yIMnsT2L4IL78t1jncNIQKC4zG8P8bAjZiDGsuHrelYB3N4xfc0kA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/cli/-/cli-2.8.1.tgz", + "integrity": "sha512-LJa36nowictp01vP60UMcpquq1qTfCnzMVDM++dXRWKEaVuJTepvRDD8qKU7USCIrdHLOEIbwUtZBG1IfiZYnw==", "dev": true, "requires": { "@openzeppelin/fuzzy-solidity-import-parser": "^0.1.2", @@ -829,9 +846,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", - "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==", + "version": "10.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", + "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", "dev": true }, "elliptic": { @@ -978,9 +995,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", - "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==", + "version": "10.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", + "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", "dev": true } } @@ -2059,9 +2076,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", - "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==", + "version": "10.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", + "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", "dev": true } } @@ -2171,9 +2188,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", - "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==", + "version": "10.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", + "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", "dev": true }, "elliptic": { @@ -3822,16 +3839,6 @@ "@types/node": "*" } }, - "@types/bytebuffer": { - "version": "5.0.40", - "resolved": "https://registry.npmjs.org/@types/bytebuffer/-/bytebuffer-5.0.40.tgz", - "integrity": "sha512-h48dyzZrPMz25K6Q4+NCwWaxwXany2FhQg/ErOcdZS1ZpsaDnDMZg8JYLMTGz7uvXKrcKGJUZJlZObyfgdaN9g==", - "dev": true, - "requires": { - "@types/long": "*", - "@types/node": "*" - } - }, "@types/cbor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/cbor/-/cbor-2.0.0.tgz", @@ -4310,16 +4317,6 @@ } } }, - "ascli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", - "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", - "dev": true, - "requires": { - "colour": "~0.7.1", - "optjs": "~3.2.2" - } - }, "asn1": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", @@ -4890,23 +4887,6 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, - "bytebuffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", - "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", - "dev": true, - "requires": { - "long": "~3" - }, - "dependencies": { - "long": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", - "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=", - "dev": true - } - } - }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -4986,12 +4966,6 @@ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", "dev": true }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -5157,39 +5131,6 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -5260,12 +5201,6 @@ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true }, - "colour": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", - "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=", - "dev": true - }, "combined-stream": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", @@ -7481,25 +7416,25 @@ } }, "firebase": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-7.13.1.tgz", - "integrity": "sha512-v4Z7Wioy/7LMC8RJn1jNlOaUqLK7bUEva+Uf+qrbtFd7hM2rWLW+0IqHZBwPrQ5tI604uHj7IlhqAZEjm38AMw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-7.14.0.tgz", + "integrity": "sha512-4QjP8WxVwVh6lvP8I96Wg11coJQ8si093xxUmafdOL7hWzG8u80EdlJOClK9zG8R37OjJRNsmXdslqFiJoGK5g==", "dev": true, "requires": { - "@firebase/analytics": "0.3.0", - "@firebase/app": "0.6.0", + "@firebase/analytics": "0.3.2", + "@firebase/app": "0.6.1", "@firebase/app-types": "0.6.0", - "@firebase/auth": "0.14.1", - "@firebase/database": "0.5.24", - "@firebase/firestore": "1.13.0", - "@firebase/functions": "0.4.38", - "@firebase/installations": "0.4.6", - "@firebase/messaging": "0.6.10", - "@firebase/performance": "0.2.36", + "@firebase/auth": "0.14.2", + "@firebase/database": "0.6.0", + "@firebase/firestore": "1.14.0", + "@firebase/functions": "0.4.40", + "@firebase/installations": "0.4.7", + "@firebase/messaging": "0.6.12", + "@firebase/performance": "0.3.0", "@firebase/polyfill": "0.3.33", - "@firebase/remote-config": "0.1.17", - "@firebase/storage": "0.3.30", - "@firebase/util": "0.2.43" + "@firebase/remote-config": "0.1.18", + "@firebase/storage": "0.3.31", + "@firebase/util": "0.2.44" } }, "flat": { @@ -28692,509 +28627,6 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, - "grpc": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.24.2.tgz", - "integrity": "sha512-EG3WH6AWMVvAiV15d+lr+K77HJ/KV/3FvMpjKjulXHbTwgDZkhkcWbwhxFAoTdxTkQvy0WFcO3Nog50QBbHZWw==", - "dev": true, - "requires": { - "@types/bytebuffer": "^5.0.40", - "lodash.camelcase": "^4.3.0", - "lodash.clone": "^4.5.0", - "nan": "^2.13.2", - "node-pre-gyp": "^0.14.0", - "protobufjs": "^5.0.3" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.3", - "bundled": true, - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "debug": { - "version": "3.2.6", - "bundled": true, - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.4", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - } - } - }, - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true - }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true - }, - "needle": { - "version": "2.4.0", - "bundled": true, - "dev": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, - "dev": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true - }, - "npm-packlist": { - "version": "1.4.6", - "bundled": true, - "dev": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "protobufjs": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", - "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", - "dev": true, - "requires": { - "ascli": "~1", - "bytebuffer": "~5", - "glob": "^7.0.5", - "yargs": "^3.10.0" - } - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true - }, - "semver": { - "version": "5.7.1", - "bundled": true, - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "dev": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.1.1", - "bundled": true, - "dev": true - } - } - }, "handlebars": { "version": "4.7.3", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.3.tgz", @@ -29595,12 +29027,6 @@ "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "dev": true }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, "ipaddr.js": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", @@ -30138,15 +29564,6 @@ "graceful-fs": "^4.1.9" } }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -31050,12 +30467,6 @@ "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", - "dev": true - }, "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", @@ -32117,27 +31528,12 @@ "wordwrap": "~1.0.0" } }, - "optjs": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", - "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=", - "dev": true - }, "original-require": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz", "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -32550,9 +31946,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", - "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==", + "version": "10.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", + "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", "dev": true } } @@ -33925,12 +33321,6 @@ } } }, - "solidity-parser-antlr": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/solidity-parser-antlr/-/solidity-parser-antlr-0.4.11.tgz", - "integrity": "sha512-4jtxasNGmyC0midtjH/lTFPZYvTTUMy6agYcF+HoMnzW8+cqo3piFrINb4ZCzpPW+7tTVFCGa5ubP34zOzeuMg==", - "dev": true - }, "solidity-parser-sc": { "version": "github:maxsam4/solidity-parser#3f0a30b97b460861654771871bcd970e73d47459", "from": "github:maxsam4/solidity-parser#solidity-0.5", @@ -34929,15 +34319,15 @@ "dev": true }, "truffle-flattener": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/truffle-flattener/-/truffle-flattener-1.4.2.tgz", - "integrity": "sha512-7qUIzaW8a4vI4nui14wsytht2oaqvqnZ1Iet2wRq2T0bCJ0wb6HByMKQhZKpU46R+n5BMTY4K5n+0ITyeNlmuQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/truffle-flattener/-/truffle-flattener-1.4.3.tgz", + "integrity": "sha512-r29fkSkV8i9oMW35KbpKR0bP4iPnzIJqlW2S+CL3BjLsxq6YnlMn9+e0BpiJIJPmeXJgeYHQvCGceucpM0Dovg==", "dev": true, "requires": { "@resolver-engine/imports-fs": "^0.2.2", + "@solidity-parser/parser": "^0.5.2", "find-up": "^2.1.0", - "mkdirp": "^0.5.1", - "solidity-parser-antlr": "^0.4.11", + "mkdirp": "^1.0.4", "tsort": "0.0.1" }, "dependencies": { @@ -34960,6 +34350,12 @@ "path-exists": "^3.0.0" } }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -35266,9 +34662,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", - "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==", + "version": "10.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", + "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", "dev": true }, "elliptic": { @@ -35338,9 +34734,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", - "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==", + "version": "10.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", + "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", "dev": true } } @@ -36791,61 +36187,12 @@ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, "yaeti": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", "dev": true }, - "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "dev": true, - "requires": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", - "dev": true - } - } - }, "yargs-parser": { "version": "13.1.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", diff --git a/package.json b/package.json index 5ffe1ee8e..4f4183e7a 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ }, "homepage": "https://openzeppelin.com/contracts/", "devDependencies": { - "@openzeppelin/cli": "^2.8.0", + "@openzeppelin/cli": "^2.8.1", "@openzeppelin/docs-utils": "^0.1.0", "@openzeppelin/gsn-helpers": "^0.2.3", "@openzeppelin/gsn-provider": "^0.1.10", From d2ab599bd3374ad377fb66dd3bf34110e90f6dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 14 Apr 2020 14:41:33 -0300 Subject: [PATCH 07/24] Update IERC777.sol (#2184) --- contracts/token/ERC777/IERC777.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/token/ERC777/IERC777.sol b/contracts/token/ERC777/IERC777.sol index a93b3a92f..8a46cb707 100644 --- a/contracts/token/ERC777/IERC777.sol +++ b/contracts/token/ERC777/IERC777.sol @@ -96,7 +96,7 @@ interface IERC777 { function authorizeOperator(address operator) external; /** - * @dev Make an account an operator of the caller. + * @dev Revoke an account's operator status for the caller. * * See {isOperatorFor} and {defaultOperators}. * From 3b10205c8eb98a87798141b14f8ffdeafd9e55b6 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Tue, 14 Apr 2020 19:06:51 -0300 Subject: [PATCH 08/24] Improve ERC20Snapshot documentation (#2186) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolás Venturo --- contracts/token/ERC20/ERC20Snapshot.sol | 59 ++++++++++++++++++++----- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/contracts/token/ERC20/ERC20Snapshot.sol b/contracts/token/ERC20/ERC20Snapshot.sol index fef67dded..cd256002a 100644 --- a/contracts/token/ERC20/ERC20Snapshot.sol +++ b/contracts/token/ERC20/ERC20Snapshot.sol @@ -6,16 +6,28 @@ import "../../utils/Counters.sol"; import "./ERC20.sol"; /** - * @dev ERC20 token with snapshots. + * @dev This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and + * total supply at the time are recorded for later access. * - * When a snapshot is made, the balances and total supply at the time of the snapshot are recorded for later - * access. + * This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting. + * In naive implementations it's possible to perform a "double spend" attack by reusing the same balance from different + * accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be + * used to create an efficient ERC20 forking mechanism. * - * To make a snapshot, call the {snapshot} function, which will emit the {Snapshot} event and return a snapshot id. - * To get the total supply from a snapshot, call the function {totalSupplyAt} with the snapshot id. - * To get the balance of an account from a snapshot, call the {balanceOfAt} function with the snapshot id and the - * account address. - * @author Validity Labs AG + * Snapshots are created by the internal {_snapshot} function, which will emit the {Snapshot} event and return a + * snapshot id. To get the total supply at the time of a snapshot, call the function {totalSupplyAt} with the snapshot + * id. To get the balance of an account at the time of a snapshot, call the {balanceOfAt} function with the snapshot id + * and the account address. + * + * ==== Gas Costs + * + * Snapshots are efficient. Snapshot creation is _O(1)_. Retrieval of balances or total supply from a snapshot is _O(log + * n)_ in the number of snapshots that have been created, although _n_ for a specific account will generally be much + * smaller since identical balances in subsequent snapshots are stored as a single entry. + * + * There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is + * only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent + * transfers will have normal cost until the next snapshot, and so on. */ abstract contract ERC20Snapshot is ERC20 { // Inspired by Jordi Baylina's MiniMeToken to record historical balances: @@ -38,12 +50,31 @@ abstract contract ERC20Snapshot is ERC20 { // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid. Counters.Counter private _currentSnapshotId; + /** + * @dev Emitted by {_snapshot} when a snapshot identified by `id` is created. + */ event Snapshot(uint256 id); /** - * @dev Creates a new snapshot id. Balances are only stored in snapshots on demand: unless a snapshot was taken, a - * balance change will not be recorded. This means the extra added cost of storing snapshotted balances is only paid - * when required, but is also flexible enough that it allows for e.g. daily snapshots. + * @dev Creates a new snapshot and returns its snapshot id. + * + * Emits a {Snapshot} event that contains the same id. + * + * {_snapshot} is `internal`: you must decide how to expose it externally. This can be done both by + * guarding it with a system such as {AccessControl}, or by leaving it open to the public. + * + * [WARNING] + * ==== + * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking, + * you must consider that it can potentially be used by attackers in two ways. + * + * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow + * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target + * specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs + * section above. + * + * We haven't measured the actual numbers; if this is something you're interested in please reach out to us. + * ==== */ function _snapshot() internal virtual returns (uint256) { _currentSnapshotId.increment(); @@ -53,12 +84,18 @@ abstract contract ERC20Snapshot is ERC20 { return currentId; } + /** + * @dev Retrieves the balance of `account` at the time `snapshotId` was created. + */ function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) { (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]); return snapshotted ? value : balanceOf(account); } + /** + * @dev Retrieves the total supply at the time `snapshotId` was created. + */ function totalSupplyAt(uint256 snapshotId) public view returns(uint256) { (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots); From b734bf3fa558b5afaa443c56c4deddcd857f5aef Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 15 Apr 2020 13:33:24 -0300 Subject: [PATCH 09/24] Tweak wording in ERC20Snapshot docs --- contracts/token/ERC20/ERC20Snapshot.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/token/ERC20/ERC20Snapshot.sol b/contracts/token/ERC20/ERC20Snapshot.sol index cd256002a..55d12b2a4 100644 --- a/contracts/token/ERC20/ERC20Snapshot.sol +++ b/contracts/token/ERC20/ERC20Snapshot.sol @@ -60,13 +60,13 @@ abstract contract ERC20Snapshot is ERC20 { * * Emits a {Snapshot} event that contains the same id. * - * {_snapshot} is `internal`: you must decide how to expose it externally. This can be done both by - * guarding it with a system such as {AccessControl}, or by leaving it open to the public. + * {_snapshot} is `internal` and you have to decide how to expose it externally. It's usage may be restricted to a + * set of accounts, for example using {AccessControl}, or it may be open to the public. * * [WARNING] * ==== * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking, - * you must consider that it can potentially be used by attackers in two ways. + * you must consider that it can potentially be used by attackers in two ways. * * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target From 3216fd9729216fda61266a37637f392f09c9dc87 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 15 Apr 2020 13:33:39 -0300 Subject: [PATCH 10/24] Configure line length in .editorconfig --- .editorconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/.editorconfig b/.editorconfig index e885a65c4..4a1b689c3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,6 +9,7 @@ end_of_line = lf indent_style = space insert_final_newline = true trim_trailing_whitespace = true +max_line_length = 120 [*.sol] indent_size = 4 From 4ca719bf8bdbaafeeb96c5a0d26f4e2572cda0bc Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 15 Apr 2020 14:35:27 -0300 Subject: [PATCH 11/24] Fix typo --- contracts/token/ERC20/ERC20Snapshot.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/token/ERC20/ERC20Snapshot.sol b/contracts/token/ERC20/ERC20Snapshot.sol index 55d12b2a4..d35bae541 100644 --- a/contracts/token/ERC20/ERC20Snapshot.sol +++ b/contracts/token/ERC20/ERC20Snapshot.sol @@ -60,7 +60,7 @@ abstract contract ERC20Snapshot is ERC20 { * * Emits a {Snapshot} event that contains the same id. * - * {_snapshot} is `internal` and you have to decide how to expose it externally. It's usage may be restricted to a + * {_snapshot} is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a * set of accounts, for example using {AccessControl}, or it may be open to the public. * * [WARNING] From b6513f6ad7f8a31c2bbfd9a8e0a85e78ea5b0df5 Mon Sep 17 00:00:00 2001 From: Robert Kaiser Date: Wed, 15 Apr 2020 20:39:33 +0200 Subject: [PATCH 12/24] provide 'automatic' token URI by appending the token ID to the base URI (#2174) * provide 'automatic' token URI by appending the token ID to the base URI, if a base is set but no token-specific URI is available * make the three cases more explicit, avoid else after return * adjust comments to reflect reality --- contracts/token/ERC721/ERC721.sol | 26 ++++++++++++++++---------- test/token/ERC721/ERC721.test.js | 4 ++-- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 9aba35129..3bc6bc039 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -10,6 +10,7 @@ import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; import "../../utils/EnumerableSet.sol"; import "../../utils/EnumerableMap.sol"; +import "../../utils/Strings.sol"; /** * @title ERC721 Non-Fungible Token Standard basic implementation @@ -132,8 +133,9 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable /** * @dev Returns the URI for a given token ID. May return an empty string. * - * If the token's URI is non-empty and a base URI was set (via - * {_setBaseURI}), it will be added to the token ID's URI as a prefix. + * If no base URI was set (via {_setBaseURI}), return the token ID's URI. + * If a base URI was set, it will be added as a prefix to the token ID's URI, + * or to the token ID itself, if no URI is set for that token ID. * * Reverts if the token ID does not exist. */ @@ -142,19 +144,22 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable string memory _tokenURI = _tokenURIs[tokenId]; - // Even if there is a base URI, it is only appended to non-empty token-specific URIs - if (bytes(_tokenURI).length == 0) { - return ""; - } else { - // abi.encodePacked is being used to concatenate strings + // If there is no base URI, return the token URI. + if (bytes(_baseURI).length == 0) { + return _tokenURI; + } + // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked). + if (bytes(_tokenURI).length > 0) { return string(abi.encodePacked(_baseURI, _tokenURI)); } + // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI. + return string(abi.encodePacked(_baseURI, Strings.fromUint256(tokenId))); } /** * @dev Returns the base URI set via {_setBaseURI}. This will be - * automatically added as a preffix in {tokenURI} to each token's URI, when - * they are non-empty. + * automatically added as a prefix in {tokenURI} to each token's URI, or + * to the token ID if no specific URI is set for that token ID. */ function baseURI() public view returns (string memory) { return _baseURI; @@ -444,7 +449,8 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable /** * @dev Internal function to set the base URI for all token IDs. It is - * automatically added as a prefix to the value returned in {tokenURI}. + * automatically added as a prefix to the value returned in {tokenURI}, + * or to the token ID if {tokenURI} is empty. */ function _setBaseURI(string memory baseURI_) internal virtual { _baseURI = baseURI_; diff --git a/test/token/ERC721/ERC721.test.js b/test/token/ERC721/ERC721.test.js index 2b850a0dc..102853226 100644 --- a/test/token/ERC721/ERC721.test.js +++ b/test/token/ERC721/ERC721.test.js @@ -92,10 +92,10 @@ describe('ERC721', function () { expect(await this.token.tokenURI(firstTokenId)).to.be.equal(newBaseURI + sampleUri); }); - it('token URI is empty for tokens with no URI but with base URI', async function () { + it('tokenId is appended to base URI for tokens with no URI', async function () { await this.token.setBaseURI(baseURI); - expect(await this.token.tokenURI(firstTokenId)).to.be.equal(''); + expect(await this.token.tokenURI(firstTokenId)).to.be.equal(baseURI + firstTokenId); }); it('tokens with URI can be burnt ', async function () { From 3e139baa501a3a1bfefb1eeeb62996dbefad6c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 15 Apr 2020 17:58:24 -0300 Subject: [PATCH 13/24] Add missing hook to ERC777, fix relevant documentation (#2191) * Improve ERC20/721 Pausable docs * Add ERC20Pausable mint and burn tests * Add ERC721Pausable mint and burn tests * Add _beforeTransfer hook in ERC777 to mint and burn --- contracts/mocks/ERC20PausableMock.sol | 8 ++++ contracts/token/ERC20/ERC20Pausable.sol | 3 +- contracts/token/ERC721/ERC721Pausable.sol | 14 +++++- contracts/token/ERC777/ERC777.sol | 4 ++ test/token/ERC20/ERC20Pausable.test.js | 54 +++++++++++++++++++++++ test/token/ERC721/ERC721Pausable.test.js | 19 +++++++- 6 files changed, 96 insertions(+), 6 deletions(-) diff --git a/contracts/mocks/ERC20PausableMock.sol b/contracts/mocks/ERC20PausableMock.sol index 639941c7f..fcf27b6cd 100644 --- a/contracts/mocks/ERC20PausableMock.sol +++ b/contracts/mocks/ERC20PausableMock.sol @@ -20,4 +20,12 @@ contract ERC20PausableMock is ERC20Pausable { function unpause() external { _unpause(); } + + function mint(address to, uint256 amount) public { + _mint(to, amount); + } + + function burn(address from, uint256 amount) public { + _burn(from, amount); + } } diff --git a/contracts/token/ERC20/ERC20Pausable.sol b/contracts/token/ERC20/ERC20Pausable.sol index 5aa21a603..8860c9ebf 100644 --- a/contracts/token/ERC20/ERC20Pausable.sol +++ b/contracts/token/ERC20/ERC20Pausable.sol @@ -4,8 +4,7 @@ import "./ERC20.sol"; import "../../utils/Pausable.sol"; /** - * @title Pausable token - * @dev ERC20 with pausable transfers and allowances. + * @dev ERC20 token with pausable token transfers, minting and burning. * * Useful for scenarios such as preventing trades until the end of an evaluation * period, or having an emergency switch for freezing all token transfers in the diff --git a/contracts/token/ERC721/ERC721Pausable.sol b/contracts/token/ERC721/ERC721Pausable.sol index 50da11c37..ff77a2402 100644 --- a/contracts/token/ERC721/ERC721Pausable.sol +++ b/contracts/token/ERC721/ERC721Pausable.sol @@ -4,10 +4,20 @@ import "./ERC721.sol"; import "../../utils/Pausable.sol"; /** - * @title ERC721 Non-Fungible Pausable token - * @dev ERC721 modified with pausable transfers. + * @dev ERC721 token with pausable token transfers, minting and burning. + * + * Useful for scenarios such as preventing trades until the end of an evaluation + * period, or having an emergency switch for freezing all token transfers in the + * event of a large bug. */ abstract contract ERC721Pausable is ERC721, Pausable { + /** + * @dev See {ERC721-_beforeTokenTransfer}. + * + * Requirements: + * + * - the contract must not be paused. + */ function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); diff --git a/contracts/token/ERC777/ERC777.sol b/contracts/token/ERC777/ERC777.sol index 7f130ee59..bd7880b65 100644 --- a/contracts/token/ERC777/ERC777.sol +++ b/contracts/token/ERC777/ERC777.sol @@ -322,6 +322,8 @@ contract ERC777 is Context, IERC777, IERC20 { address operator = _msgSender(); + _beforeTokenTransfer(operator, address(0), account, amount); + // Update state variables _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); @@ -382,6 +384,8 @@ contract ERC777 is Context, IERC777, IERC20 { address operator = _msgSender(); + _beforeTokenTransfer(operator, from, address(0), amount); + _callTokensToSend(operator, from, address(0), amount, data, operatorData); // Update state variables diff --git a/test/token/ERC20/ERC20Pausable.test.js b/test/token/ERC20/ERC20Pausable.test.js index b43e82062..dd175269e 100644 --- a/test/token/ERC20/ERC20Pausable.test.js +++ b/test/token/ERC20/ERC20Pausable.test.js @@ -78,5 +78,59 @@ describe('ERC20Pausable', function () { ); }); }); + + describe('mint', function () { + const amount = new BN('42'); + + it('allows to mint when unpaused', async function () { + await this.token.mint(recipient, amount); + + expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(amount); + }); + + it('allows to mint when paused and then unpaused', async function () { + await this.token.pause(); + await this.token.unpause(); + + await this.token.mint(recipient, amount); + + expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(amount); + }); + + it('reverts when trying to mint when paused', async function () { + await this.token.pause(); + + await expectRevert(this.token.mint(recipient, amount), + 'ERC20Pausable: token transfer while paused' + ); + }); + }); + + describe('burn', function () { + const amount = new BN('42'); + + it('allows to burn when unpaused', async function () { + await this.token.burn(holder, amount); + + expect(await this.token.balanceOf(holder)).to.be.bignumber.equal(initialSupply.sub(amount)); + }); + + it('allows to burn when paused and then unpaused', async function () { + await this.token.pause(); + await this.token.unpause(); + + await this.token.burn(holder, amount); + + expect(await this.token.balanceOf(holder)).to.be.bignumber.equal(initialSupply.sub(amount)); + }); + + it('reverts when trying to burn when paused', async function () { + await this.token.pause(); + + await expectRevert(this.token.burn(holder, amount), + 'ERC20Pausable: token transfer while paused' + ); + }); + }); }); }); diff --git a/test/token/ERC721/ERC721Pausable.test.js b/test/token/ERC721/ERC721Pausable.test.js index a15862847..659757ee7 100644 --- a/test/token/ERC721/ERC721Pausable.test.js +++ b/test/token/ERC721/ERC721Pausable.test.js @@ -19,7 +19,8 @@ describe('ERC721Pausable', function () { context('when token is paused', function () { const firstTokenId = new BN(1); - const mintedTokens = new BN(1); + const secondTokenId = new BN(1337); + const mockData = '0x42'; beforeEach(async function () { @@ -49,6 +50,20 @@ describe('ERC721Pausable', function () { ); }); + it('reverts when trying to mint', async function () { + await expectRevert( + this.token.mint(receiver, secondTokenId), + 'ERC721Pausable: token transfer while paused' + ); + }); + + it('reverts when trying to burn', async function () { + await expectRevert( + this.token.burn(firstTokenId), + 'ERC721Pausable: token transfer while paused' + ); + }); + describe('getApproved', function () { it('returns approved address', async function () { const approvedAccount = await this.token.getApproved(firstTokenId); @@ -59,7 +74,7 @@ describe('ERC721Pausable', function () { describe('balanceOf', function () { it('returns the amount of tokens owned by the given address', async function () { const balance = await this.token.balanceOf(owner); - expect(balance).to.be.bignumber.equal(mintedTokens); + expect(balance).to.be.bignumber.equal('1'); }); }); From 8b10cb38d8fedf34f2d89b0ed604f2dceb76d6a9 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 15 Apr 2020 18:04:00 -0300 Subject: [PATCH 14/24] Rename Strings.fromUint256 to Strings.toString (#2188) * rename Strings.fromUint256 to Strings.toString * add changelog entry * fix conflict with js toString method --- CHANGELOG.md | 1 + contracts/mocks/StringsMock.sol | 2 +- contracts/token/ERC721/ERC721.sol | 2 +- contracts/utils/Strings.sol | 3 +-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce48a7730..0859f5153 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ * `ERC721`: added a constructor for `name` and `symbol`. ([#2160](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2160)) * `ERC20Detailed`: this contract was removed and its functionality merged into `ERC20`. ([#2161](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2161)) * `ERC20`: added a constructor for `name` and `symbol`. `decimals` now defaults to 18. ([#2161](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2161)) + * `Strings`: renamed `fromUint256` to `toString` ([#2188](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2188)) ## 2.5.0 (2020-02-04) diff --git a/contracts/mocks/StringsMock.sol b/contracts/mocks/StringsMock.sol index 383278070..a7a50eb3c 100644 --- a/contracts/mocks/StringsMock.sol +++ b/contracts/mocks/StringsMock.sol @@ -4,6 +4,6 @@ import "../utils/Strings.sol"; contract StringsMock { function fromUint256(uint256 value) public pure returns (string memory) { - return Strings.fromUint256(value); + return Strings.toString(value); } } diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 3bc6bc039..ad72d2606 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -153,7 +153,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable return string(abi.encodePacked(_baseURI, _tokenURI)); } // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI. - return string(abi.encodePacked(_baseURI, Strings.fromUint256(tokenId))); + return string(abi.encodePacked(_baseURI, Strings.toString(tokenId))); } /** diff --git a/contracts/utils/Strings.sol b/contracts/utils/Strings.sol index 6977c809f..1ed3c5197 100644 --- a/contracts/utils/Strings.sol +++ b/contracts/utils/Strings.sol @@ -1,14 +1,13 @@ pragma solidity ^0.6.0; /** - * @title Strings * @dev String operations. */ library Strings { /** * @dev Converts a `uint256` to its ASCII `string` representation. */ - function fromUint256(uint256 value) internal pure returns (string memory) { + function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol From cca71ab7095d66598758933505960b05d2a914ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 16 Apr 2020 12:13:49 -0300 Subject: [PATCH 15/24] Fix deprecation warnings (#2115) * Fix deprecation warnings * Workaround linter bug --- contracts/introspection/ERC165Checker.sol | 4 ++-- contracts/payment/PullPayment.sol | 8 ++++++-- contracts/utils/Address.sol | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/contracts/introspection/ERC165Checker.sol b/contracts/introspection/ERC165Checker.sol index b7db18850..dbf9085e6 100644 --- a/contracts/introspection/ERC165Checker.sol +++ b/contracts/introspection/ERC165Checker.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.6.2; /** * @dev Library used to query support of an interface declared via {IERC165}. @@ -97,7 +97,7 @@ library ERC165Checker { returns (bool, bool) { bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId); - (bool success, bytes memory result) = account.staticcall.gas(30000)(encodedParams); + (bool success, bytes memory result) = account.staticcall{ gas: 30000 }(encodedParams); if (result.length < 32) return (false, false); return (success, abi.decode(result, (bool))); } diff --git a/contracts/payment/PullPayment.sol b/contracts/payment/PullPayment.sol index 3cd486fb0..9b4fcb405 100644 --- a/contracts/payment/PullPayment.sol +++ b/contracts/payment/PullPayment.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.6.2; import "./escrow/Escrow.sol"; @@ -62,6 +62,10 @@ contract PullPayment { * @param amount The amount to transfer. */ function _asyncTransfer(address dest, uint256 amount) internal virtual { - _escrow.deposit.value(amount)(dest); + // solhint-disable-previous-line no-unused-vars + + // TODO: remove the previous linter directive once + // https://github.com/protofire/solhint/issues/170 is fixed + _escrow.deposit{ value: amount }(dest); } } diff --git a/contracts/utils/Address.sol b/contracts/utils/Address.sol index 736fa0758..4ae5d8bfc 100644 --- a/contracts/utils/Address.sol +++ b/contracts/utils/Address.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity ^0.6.2; /** * @dev Collection of functions related to the address type @@ -52,7 +52,7 @@ library Address { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value - (bool success, ) = recipient.call.value(amount)(""); + (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } } From 13e113df8163209eaf852c76a3c7689b3ee836b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 17 Apr 2020 11:37:58 -0300 Subject: [PATCH 16/24] Improve usage of toString --- contracts/token/ERC721/ERC721.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index ad72d2606..0552ce7f3 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -21,6 +21,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable using Address for address; using EnumerableSet for EnumerableSet.UintSet; using EnumerableMap for EnumerableMap.UintToAddressMap; + using Strings for uint256; // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` @@ -153,7 +154,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable return string(abi.encodePacked(_baseURI, _tokenURI)); } // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI. - return string(abi.encodePacked(_baseURI, Strings.toString(tokenId))); + return string(abi.encodePacked(_baseURI, tokenId.toString())); } /** From c7705712ba441c8f0a01ace8d947e51d069a02c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 17 Apr 2020 17:00:30 -0300 Subject: [PATCH 17/24] Remove in-constructor requirements (#2195) * Remove isConstructor requirement from _setupRole * Remove isConstructor requirement from _setupDecimals * Update contracts/access/AccessControl.sol Co-Authored-By: Francisco Giordano Co-authored-by: Francisco Giordano --- contracts/access/AccessControl.sol | 10 +++++++--- contracts/mocks/AccessControlMock.sol | 4 ---- contracts/mocks/ERC20DecimalsMock.sol | 4 ---- contracts/token/ERC20/ERC20.sol | 7 +++---- test/access/AccessControl.test.js | 9 --------- test/token/ERC20/ERC20.test.js | 6 ------ 6 files changed, 10 insertions(+), 30 deletions(-) diff --git a/contracts/access/AccessControl.sol b/contracts/access/AccessControl.sol index 00f2efc98..cd7ebd9ca 100644 --- a/contracts/access/AccessControl.sol +++ b/contracts/access/AccessControl.sol @@ -164,12 +164,16 @@ abstract contract AccessControl is Context { * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * - * Requirements: + * [WARNING] + * ==== + * This function should only be called from the constructor when setting + * up the initial roles for the system. * - * - this function can only be called from a constructor. + * Using this function in any other way is effectively circumventing the admin + * system imposed by {AccessControl}. + * ==== */ function _setupRole(bytes32 role, address account) internal virtual { - require(!address(this).isContract(), "AccessControl: roles cannot be setup after construction"); _grantRole(role, account); } diff --git a/contracts/mocks/AccessControlMock.sol b/contracts/mocks/AccessControlMock.sol index 876e78a2a..4f96be5d5 100644 --- a/contracts/mocks/AccessControlMock.sol +++ b/contracts/mocks/AccessControlMock.sol @@ -10,8 +10,4 @@ contract AccessControlMock is AccessControl { function setRoleAdmin(bytes32 roleId, bytes32 adminRoleId) public { _setRoleAdmin(roleId, adminRoleId); } - - function setupRole(bytes32 roleId, address account) public { - _setupRole(roleId, account); - } } diff --git a/contracts/mocks/ERC20DecimalsMock.sol b/contracts/mocks/ERC20DecimalsMock.sol index d4d25c52f..afb941305 100644 --- a/contracts/mocks/ERC20DecimalsMock.sol +++ b/contracts/mocks/ERC20DecimalsMock.sol @@ -6,8 +6,4 @@ contract ERC20DecimalsMock is ERC20 { constructor (string memory name, string memory symbol, uint8 decimals) public ERC20(name, symbol) { _setupDecimals(decimals); } - - function setupDecimals(uint8 decimals) public { - _setupDecimals(decimals); - } } diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index ac514c483..9503a0a80 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -279,12 +279,11 @@ contract ERC20 is Context, IERC20 { /** * @dev Sets {decimals} to a value other than the default one of 18. * - * Requirements: - * - * - this function can only be called from a constructor. + * WARNING: This function should only be called from the constructor. Most + * applications that interact with token contracts will not expect + * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal { - require(!address(this).isContract(), "ERC20: decimals cannot be changed after construction"); _decimals = decimals_; } diff --git a/test/access/AccessControl.test.js b/test/access/AccessControl.test.js index db4cf47c0..c49276f92 100644 --- a/test/access/AccessControl.test.js +++ b/test/access/AccessControl.test.js @@ -17,15 +17,6 @@ describe('AccessControl', function () { this.accessControl = await AccessControlMock.new({ from: admin }); }); - describe('_setupRole', function () { - it('cannot be called outside the constructor', async function () { - await expectRevert( - this.accessControl.setupRole(OTHER_ROLE, other), - 'AccessControl: roles cannot be setup after construction' - ); - }); - }); - describe('default admin', function () { it('deployer has default admin role', async function () { expect(await this.accessControl.hasRole(DEFAULT_ADMIN_ROLE, admin)).to.equal(true); diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index 7996fa39e..ba1701074 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -44,12 +44,6 @@ describe('ERC20', function () { const token = await ERC20DecimalsMock.new(name, symbol, decimals); expect(await token.decimals()).to.be.bignumber.equal(decimals); }); - - it('reverts if setting decimals after construction', async function () { - const token = await ERC20DecimalsMock.new(name, symbol, decimals); - - await expectRevert(token.setupDecimals(decimals.addn(1)), 'ERC20: decimals cannot be changed after construction'); - }); }); shouldBehaveLikeERC20('ERC20', initialSupply, initialHolder, recipient, anotherAccount); From 1075898b0690d043064c3873e7a5887152b8259f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2020 12:33:00 -0300 Subject: [PATCH 18/24] Bump @openzeppelin/cli from 2.8.1 to 2.8.2 (#2200) Bumps [@openzeppelin/cli](https://github.com/OpenZeppelin/openzeppelin-sdk) from 2.8.1 to 2.8.2. - [Release notes](https://github.com/OpenZeppelin/openzeppelin-sdk/releases) - [Commits](https://github.com/OpenZeppelin/openzeppelin-sdk/compare/v2.8.1...v2.8.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- package-lock.json | 266 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 134 insertions(+), 134 deletions(-) diff --git a/package-lock.json b/package-lock.json index a6b5ac500..757cc0efb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,16 +62,16 @@ } }, "@firebase/analytics": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.3.2.tgz", - "integrity": "sha512-z4mYytlmnNipXQrGB6bN0tzWa9GzCtK0M2HD86C9OFYpwBeDQGc3UQPAM6kbfkv50Mnl4vlS5Ta2qEw/CvWwug==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.3.3.tgz", + "integrity": "sha512-Mj4lufHCnDqI2e8jAFqWmo9r2ejBJiGbI0MUvoiKVMxQm0kddQxUwmxfE6ozOAZ2HjB6OZ0iiAO+XU+0w/BnlA==", "dev": true, "requires": { "@firebase/analytics-types": "0.3.0", - "@firebase/component": "0.1.9", - "@firebase/installations": "0.4.7", - "@firebase/logger": "0.2.1", - "@firebase/util": "0.2.44", + "@firebase/component": "0.1.10", + "@firebase/installations": "0.4.8", + "@firebase/logger": "0.2.2", + "@firebase/util": "0.2.45", "tslib": "1.11.1" }, "dependencies": { @@ -90,15 +90,15 @@ "dev": true }, "@firebase/app": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.1.tgz", - "integrity": "sha512-KSzSFQfiJgxi+7Ff/EZQcdvCnqKj2db9xa7I8z1UoRIRez9e0Q6+GpW3mrSVmmSCrBbKYsOO/SJh5NaFot0evg==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.2.tgz", + "integrity": "sha512-rAxc90+82GAPpUxS02EO0dys4+TeQ6XjFjCwQz/OVptGeLgxN9ZoXYAf/bxyeYOdLxJW0kbEKE/0xXaJDt5gsg==", "dev": true, "requires": { "@firebase/app-types": "0.6.0", - "@firebase/component": "0.1.9", - "@firebase/logger": "0.2.1", - "@firebase/util": "0.2.44", + "@firebase/component": "0.1.10", + "@firebase/logger": "0.2.2", + "@firebase/util": "0.2.45", "dom-storage": "2.1.0", "tslib": "1.11.1", "xmlhttprequest": "1.8.0" @@ -119,9 +119,9 @@ "dev": true }, "@firebase/auth": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.14.2.tgz", - "integrity": "sha512-5HaEGne2JbcVvzK9FeOEGi8NNQwq00thmL88uduqI8LTXHSOWaC8Y4El9DesVu6aFEOXELpf7W4I34CG9WwjlA==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.14.3.tgz", + "integrity": "sha512-XPB3Mf3PwHibv2HbvqOol02ACCuwAKSY9HAtq70w3K3OwSDX4opDdrNOhoer7Nrq3xvX58b+c+oVGxD9mbo/qQ==", "dev": true, "requires": { "@firebase/auth-types": "0.10.0" @@ -140,12 +140,12 @@ "dev": true }, "@firebase/component": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.9.tgz", - "integrity": "sha512-i58GsVpxBGnKn1rx2RCAH0rk1Ldp6WterfBNDHyxmuyRO6BaZAgvxrZ3Ku1/lqiI7XMbmmRpP3emmwrStbFt9Q==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.10.tgz", + "integrity": "sha512-Iy1+f8wp6mROz19oxWUd31NxMlGxtW1IInGHITnVa6eZtXOg0lxcbgYeLp9W3PKzvvNfshHU0obDkcMY97zRAw==", "dev": true, "requires": { - "@firebase/util": "0.2.44", + "@firebase/util": "0.2.45", "tslib": "1.11.1" }, "dependencies": { @@ -158,16 +158,16 @@ } }, "@firebase/database": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.0.tgz", - "integrity": "sha512-b1wt4BpzFOXxAaUtkFqfoeZzmZIQ3sLiznqOYaAROnK2JMxpFF41Nh9wZ2tCze6rOkpN+3Kx33hsPCsrQcn0WQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.1.tgz", + "integrity": "sha512-7XqUbj3nK2vEdFjGOXBfKISmpLrM0caIwwfDPxhn6i7X/g6AIH+D1limH+Jit4QeKMh/IJZDNqO7P+Fz+e8q1Q==", "dev": true, "requires": { "@firebase/auth-interop-types": "0.1.4", - "@firebase/component": "0.1.9", + "@firebase/component": "0.1.10", "@firebase/database-types": "0.5.0", - "@firebase/logger": "0.2.1", - "@firebase/util": "0.2.44", + "@firebase/logger": "0.2.2", + "@firebase/util": "0.2.45", "faye-websocket": "0.11.3", "tslib": "1.11.1" }, @@ -190,17 +190,17 @@ } }, "@firebase/firestore": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.14.0.tgz", - "integrity": "sha512-JpwP6LWtNRjCtRbRvzhdtJ1tHL6r0MjCvmMr2Nv7bKmcjqoN8FiP+fZ9KkiZiqsSUhNsFFajyvx9n7R6vC+d2w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.14.1.tgz", + "integrity": "sha512-6wu+Oh00O8NPWyetr8BVZ9Y3Z7PrBZpoJjam2jjB0RVOaksvC1VTmjIOK6cLczt9hD0JRtb5wy+ME7E70N0ruA==", "dev": true, "requires": { - "@firebase/component": "0.1.9", + "@firebase/component": "0.1.10", "@firebase/firestore-types": "1.10.1", - "@firebase/logger": "0.2.1", - "@firebase/util": "0.2.44", - "@firebase/webchannel-wrapper": "0.2.38", - "@grpc/grpc-js": "0.7.5", + "@firebase/logger": "0.2.2", + "@firebase/util": "0.2.45", + "@firebase/webchannel-wrapper": "0.2.39", + "@grpc/grpc-js": "0.8.1", "@grpc/proto-loader": "^0.5.0", "tslib": "1.11.1" }, @@ -220,12 +220,12 @@ "dev": true }, "@firebase/functions": { - "version": "0.4.40", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.40.tgz", - "integrity": "sha512-Yd0P+/xLt2Lc7AJpi1zff6xjVcJXpT7coTCBjb+58RQhECkoEh1ESx46VzoUGy+4ldoh/ZFFU7p0d/lG/+wDvg==", + "version": "0.4.41", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.41.tgz", + "integrity": "sha512-S7fYjzoCSWoTUpTvYRXHYByXdNIP7TYFkfBGvy/ca1WT/6AnBOkdFuxPLilEaKWKlERMbYUQgxyNq52nUPRhCw==", "dev": true, "requires": { - "@firebase/component": "0.1.9", + "@firebase/component": "0.1.10", "@firebase/functions-types": "0.3.16", "@firebase/messaging-types": "0.4.4", "isomorphic-fetch": "2.2.1", @@ -247,14 +247,14 @@ "dev": true }, "@firebase/installations": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.7.tgz", - "integrity": "sha512-Fz9B/H58xfkAnDGVTW1V/73Jd5LAN9o5dpz1K3+u2W+zp0iU6HoRTwm9Bgk+aV6/0FYjqmtYEDjK8T0OYPoIQA==", + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.8.tgz", + "integrity": "sha512-J3tyKCdZ07LR0Bw3rs4CIsWia5exGt77fdbvqnhYa6K8YfIUPFLzsGRvlFJkoIhOMXfujfnC3O/DakROOgOltg==", "dev": true, "requires": { - "@firebase/component": "0.1.9", + "@firebase/component": "0.1.10", "@firebase/installations-types": "0.3.3", - "@firebase/util": "0.2.44", + "@firebase/util": "0.2.45", "idb": "3.0.2", "tslib": "1.11.1" }, @@ -274,21 +274,21 @@ "dev": true }, "@firebase/logger": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.1.tgz", - "integrity": "sha512-H4nttTqUzEw3TA/JYl8ma6oMSNKHcdpEWV2L2qA+ZEcpM2OLAzagi//DrYBFR5xpPb17IGagpzSxFgx937Sq/A==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.2.tgz", + "integrity": "sha512-MbEy17Ha1w/DlLtvxG89ScQ+0+yoElGKJ1nUCQHHLjeMNsRwd2wnUPOVCsZvtBzQp8Z0GaFmD4a2iG2v91lEbA==", "dev": true }, "@firebase/messaging": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.6.12.tgz", - "integrity": "sha512-U5piZd/0JFI4/2ZqTiIGYPcQBeTit6fTUbozGn2RSKcQw6WuNb9QJDbTZCzo1BzrHf1zoIqyakggL2AvIq48vA==", + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.6.13.tgz", + "integrity": "sha512-QfC1H88q+YYjqzrmplzRwUsVfDJpVB+AaUnv6SPBoh12Eh/Wutu+ot8h6rpEc1b0B69EGYD/Pu2+bnixYVhlUA==", "dev": true, "requires": { - "@firebase/component": "0.1.9", - "@firebase/installations": "0.4.7", + "@firebase/component": "0.1.10", + "@firebase/installations": "0.4.8", "@firebase/messaging-types": "0.4.4", - "@firebase/util": "0.2.44", + "@firebase/util": "0.2.45", "idb": "3.0.2", "tslib": "1.11.1" }, @@ -308,16 +308,16 @@ "dev": true }, "@firebase/performance": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.3.0.tgz", - "integrity": "sha512-206klc2wzajagbHlR7T2GWvFHsfoRMMWLa2K3GIe6ikDGlPYa/F2byXYzv6e3mSOw6aKLSbTVcIaLBBourpOTA==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.3.1.tgz", + "integrity": "sha512-YBs3iIGNZM39Yas4AU9BFZS4na1J/yoARVUGsL0Vcvw6TaPN57KiqKdfbjxz84WSuC3xrDa6Hirxh9S1sS0zbQ==", "dev": true, "requires": { - "@firebase/component": "0.1.9", - "@firebase/installations": "0.4.7", - "@firebase/logger": "0.2.1", + "@firebase/component": "0.1.10", + "@firebase/installations": "0.4.8", + "@firebase/logger": "0.2.2", "@firebase/performance-types": "0.0.12", - "@firebase/util": "0.2.44", + "@firebase/util": "0.2.45", "tslib": "1.11.1" }, "dependencies": { @@ -336,20 +336,20 @@ "dev": true }, "@firebase/polyfill": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.33.tgz", - "integrity": "sha512-Arp9JViyD2i0K01NCCY0WZK5p16kQB/wddf44+Qboh+u3eIrFbVk0OO2IknjrkzIW392u73Ts7TkVxLPGPJF9g==", + "version": "0.3.34", + "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.34.tgz", + "integrity": "sha512-6EN02vwhX6cmyB4YswKhHkS3kMeNDxjCgf4vR3L9wYv+A5QVgAM85ifzf3mZT0tq3f2LfIsTsCIr/mlz2Swl1A==", "dev": true, "requires": { - "core-js": "3.6.4", + "core-js": "3.6.5", "promise-polyfill": "8.1.3", "whatwg-fetch": "2.0.4" }, "dependencies": { "core-js": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", - "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", "dev": true }, "whatwg-fetch": { @@ -361,16 +361,16 @@ } }, "@firebase/remote-config": { - "version": "0.1.18", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.18.tgz", - "integrity": "sha512-ufbhnP3O6bRYs74jFIyYZ0dPsv/PsMSmGs669Os5SkEdfjEWX8hnhssfuZCg5VfJQiCrqoSQD/KfPGACmeBcbQ==", + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.19.tgz", + "integrity": "sha512-2n6bavDGO+cQsS3fs+yHthnkp5TKh8sqSD89dztt/b3/KKRb4C89r3apb6QIcQw/AlyToM+NyU6WIZyXfVAhqQ==", "dev": true, "requires": { - "@firebase/component": "0.1.9", - "@firebase/installations": "0.4.7", - "@firebase/logger": "0.2.1", + "@firebase/component": "0.1.10", + "@firebase/installations": "0.4.8", + "@firebase/logger": "0.2.2", "@firebase/remote-config-types": "0.1.8", - "@firebase/util": "0.2.44", + "@firebase/util": "0.2.45", "tslib": "1.11.1" }, "dependencies": { @@ -389,14 +389,14 @@ "dev": true }, "@firebase/storage": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.31.tgz", - "integrity": "sha512-b5rwcMa89mFnKDlhFmGRC0QFpOgqGoNVn4klJDvSnpRGmwOcByQXoos8w1IWP0DW+EWhHcafy7DvUHFlr70onw==", + "version": "0.3.32", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.32.tgz", + "integrity": "sha512-mwWI03VbTd1jP7mmeNBv7mJ96i8GUX1fSxVept5aV2FQb2pAWTKXr7Gmxg06w642I0T1+qZTRVXs8G5m8vuTjg==", "dev": true, "requires": { - "@firebase/component": "0.1.9", + "@firebase/component": "0.1.10", "@firebase/storage-types": "0.3.11", - "@firebase/util": "0.2.44", + "@firebase/util": "0.2.45", "tslib": "1.11.1" }, "dependencies": { @@ -415,9 +415,9 @@ "dev": true }, "@firebase/util": { - "version": "0.2.44", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.44.tgz", - "integrity": "sha512-yWnFdeuz7P0QC4oC77JyPdAQ/rTGPDfhHcR5WsoMsKBBHTyqEhaKWL9HeRird+p3AL9M4++ep0FYFNd1UKU3Wg==", + "version": "0.2.45", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.45.tgz", + "integrity": "sha512-k3IqXaIgwlPg7m5lXmMUtkqA/p+LMFkFQIqBuDtdT0iyWB6kQDokyjw2Sgd3GoTybs6tWqUKFZupZpV6r73UHw==", "dev": true, "requires": { "tslib": "1.11.1" @@ -432,15 +432,15 @@ } }, "@firebase/webchannel-wrapper": { - "version": "0.2.38", - "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.2.38.tgz", - "integrity": "sha512-mp1XmAJsuqaSWm5WQYo7R0zfZWe9EmwMCxsxkKr+ubLOumyNy4NG5aV45hEpFTosQv4myXpiCiS4GFE9mNqLZQ==", + "version": "0.2.39", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.2.39.tgz", + "integrity": "sha512-V5oQjtYxHlEpWdQr68ZFo8T+3NVccrTieRy8RnzYIasCeptxOxwYUG0cAAKmalgrrrfRJdXup8h5ybi3XSW9Hw==", "dev": true }, "@grpc/grpc-js": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-0.7.5.tgz", - "integrity": "sha512-hhWT+vHPtG4tn0zZJw4ndfv730pBPb+lhJfvQhc7ANBvqixtlNOaXm9VNI98wYF/em0PnrskXnOr8rHh96zjlg==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-0.8.1.tgz", + "integrity": "sha512-e8gSjRZnOUefsR3obOgxG9RtYW2Mw83hh7ogE2ByCdgRhoX0mdnJwBcZOami3E0l643KCTZvORFwfSEi48KFIQ==", "dev": true, "requires": { "semver": "^6.2.0" @@ -731,9 +731,9 @@ } }, "@openzeppelin/cli": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@openzeppelin/cli/-/cli-2.8.1.tgz", - "integrity": "sha512-LJa36nowictp01vP60UMcpquq1qTfCnzMVDM++dXRWKEaVuJTepvRDD8qKU7USCIrdHLOEIbwUtZBG1IfiZYnw==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/@openzeppelin/cli/-/cli-2.8.2.tgz", + "integrity": "sha512-K0m1UAywnweAwzbwwmqI+JSezDRnqDRWkKQMI2VV6T03LOXcG/L9oqO9KRORI8md+KbxBW9v5rmNV63wGQIRlA==", "dev": true, "requires": { "@openzeppelin/fuzzy-solidity-import-parser": "^0.1.2", @@ -777,9 +777,9 @@ }, "dependencies": { "ajv": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", - "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", + "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -846,9 +846,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", - "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", + "version": "10.17.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.20.tgz", + "integrity": "sha512-XgDgo6W10SeGEAM0k7FosJpvLCynOTYns4Xk3J5HGrA+UI/bKZ30PGMzOP5Lh2zs4259I71FSYLAtjnx3qhObw==", "dev": true }, "elliptic": { @@ -995,9 +995,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", - "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", + "version": "10.17.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.20.tgz", + "integrity": "sha512-XgDgo6W10SeGEAM0k7FosJpvLCynOTYns4Xk3J5HGrA+UI/bKZ30PGMzOP5Lh2zs4259I71FSYLAtjnx3qhObw==", "dev": true } } @@ -2076,9 +2076,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", - "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", + "version": "10.17.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.20.tgz", + "integrity": "sha512-XgDgo6W10SeGEAM0k7FosJpvLCynOTYns4Xk3J5HGrA+UI/bKZ30PGMzOP5Lh2zs4259I71FSYLAtjnx3qhObw==", "dev": true } } @@ -2188,9 +2188,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", - "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", + "version": "10.17.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.20.tgz", + "integrity": "sha512-XgDgo6W10SeGEAM0k7FosJpvLCynOTYns4Xk3J5HGrA+UI/bKZ30PGMzOP5Lh2zs4259I71FSYLAtjnx3qhObw==", "dev": true }, "elliptic": { @@ -7416,25 +7416,25 @@ } }, "firebase": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-7.14.0.tgz", - "integrity": "sha512-4QjP8WxVwVh6lvP8I96Wg11coJQ8si093xxUmafdOL7hWzG8u80EdlJOClK9zG8R37OjJRNsmXdslqFiJoGK5g==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-7.14.1.tgz", + "integrity": "sha512-2lgBgWuFOd9wnwgOQEKmqqxuWf2Cp2xw08Nwar8/fD5gtoMngn7JY2PE86VUSu7XVTyhVFLfAIAMyZLDaRRTOg==", "dev": true, "requires": { - "@firebase/analytics": "0.3.2", - "@firebase/app": "0.6.1", + "@firebase/analytics": "0.3.3", + "@firebase/app": "0.6.2", "@firebase/app-types": "0.6.0", - "@firebase/auth": "0.14.2", - "@firebase/database": "0.6.0", - "@firebase/firestore": "1.14.0", - "@firebase/functions": "0.4.40", - "@firebase/installations": "0.4.7", - "@firebase/messaging": "0.6.12", - "@firebase/performance": "0.3.0", - "@firebase/polyfill": "0.3.33", - "@firebase/remote-config": "0.1.18", - "@firebase/storage": "0.3.31", - "@firebase/util": "0.2.44" + "@firebase/auth": "0.14.3", + "@firebase/database": "0.6.1", + "@firebase/firestore": "1.14.1", + "@firebase/functions": "0.4.41", + "@firebase/installations": "0.4.8", + "@firebase/messaging": "0.6.13", + "@firebase/performance": "0.3.1", + "@firebase/polyfill": "0.3.34", + "@firebase/remote-config": "0.1.19", + "@firebase/storage": "0.3.32", + "@firebase/util": "0.2.45" } }, "flat": { @@ -31946,9 +31946,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", - "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", + "version": "10.17.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.20.tgz", + "integrity": "sha512-XgDgo6W10SeGEAM0k7FosJpvLCynOTYns4Xk3J5HGrA+UI/bKZ30PGMzOP5Lh2zs4259I71FSYLAtjnx3qhObw==", "dev": true } } @@ -34441,9 +34441,9 @@ "dev": true }, "resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz", + "integrity": "sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -34662,9 +34662,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", - "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", + "version": "10.17.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.20.tgz", + "integrity": "sha512-XgDgo6W10SeGEAM0k7FosJpvLCynOTYns4Xk3J5HGrA+UI/bKZ30PGMzOP5Lh2zs4259I71FSYLAtjnx3qhObw==", "dev": true }, "elliptic": { @@ -34734,9 +34734,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", - "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", + "version": "10.17.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.20.tgz", + "integrity": "sha512-XgDgo6W10SeGEAM0k7FosJpvLCynOTYns4Xk3J5HGrA+UI/bKZ30PGMzOP5Lh2zs4259I71FSYLAtjnx3qhObw==", "dev": true } } diff --git a/package.json b/package.json index 4f4183e7a..5263b7e89 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ }, "homepage": "https://openzeppelin.com/contracts/", "devDependencies": { - "@openzeppelin/cli": "^2.8.1", + "@openzeppelin/cli": "^2.8.2", "@openzeppelin/docs-utils": "^0.1.0", "@openzeppelin/gsn-helpers": "^0.2.3", "@openzeppelin/gsn-provider": "^0.1.10", From 2663c5ee0f710661a0372065f4b2e0cc7b56eec9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2020 13:43:00 -0300 Subject: [PATCH 19/24] Bump @openzeppelin/test-environment from 0.1.3 to 0.1.4 (#2201) Bumps [@openzeppelin/test-environment](https://github.com/OpenZeppelin/openzeppelin-test-environment) from 0.1.3 to 0.1.4. - [Release notes](https://github.com/OpenZeppelin/openzeppelin-test-environment/releases) - [Changelog](https://github.com/OpenZeppelin/openzeppelin-test-environment/blob/master/CHANGELOG.md) - [Commits](https://github.com/OpenZeppelin/openzeppelin-test-environment/compare/v0.1.3...v0.1.4) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- package-lock.json | 52 +++++++++++++++++++++++++++++------------------ package.json | 2 +- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index 757cc0efb..744250a1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1418,9 +1418,9 @@ } }, "@openzeppelin/test-environment": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/test-environment/-/test-environment-0.1.3.tgz", - "integrity": "sha512-joYTi4hFbXjKEWvgtitQm43q5HtnQvPnz8eBoqHg+fijNi2v8HqC76Id+m2yOtXtDwG0XSvNzbiJaT1lxNBc1w==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@openzeppelin/test-environment/-/test-environment-0.1.4.tgz", + "integrity": "sha512-RzzfiJI6079CRT6D6n8S9wXBIkrvW54CP/deTTRrGbNDV0MNcQE0U0DwRaQAtyztXQM+2RISy7B66JZUpGSUzQ==", "dev": true, "requires": { "@openzeppelin/contract-loader": "^0.6.1", @@ -1432,7 +1432,7 @@ "ganache-core": "^2.8.0", "lodash.merge": "^4.6.2", "p-queue": "^6.2.0", - "semver": "^6.3.0", + "semver": "^7.1.3", "try-require": "^1.2.1", "web3": "1.2.2" }, @@ -1485,9 +1485,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.16.tgz", - "integrity": "sha512-A4283YSA1OmnIivcpy/4nN86YlnKRiQp8PYwI2KdPCONEBN093QTb0gCtERtkLyVNGKKIGazTZ2nAmVzQU51zA==", + "version": "10.17.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.20.tgz", + "integrity": "sha512-XgDgo6W10SeGEAM0k7FosJpvLCynOTYns4Xk3J5HGrA+UI/bKZ30PGMzOP5Lh2zs4259I71FSYLAtjnx3qhObw==", "dev": true }, "elliptic": { @@ -1517,9 +1517,9 @@ "dev": true }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true }, "uuid": { @@ -1557,9 +1557,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.16.tgz", - "integrity": "sha512-A4283YSA1OmnIivcpy/4nN86YlnKRiQp8PYwI2KdPCONEBN093QTb0gCtERtkLyVNGKKIGazTZ2nAmVzQU51zA==", + "version": "10.17.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.20.tgz", + "integrity": "sha512-XgDgo6W10SeGEAM0k7FosJpvLCynOTYns4Xk3J5HGrA+UI/bKZ30PGMzOP5Lh2zs4259I71FSYLAtjnx3qhObw==", "dev": true } } @@ -4009,7 +4009,8 @@ "acorn": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true }, "acorn-jsx": { "version": "5.1.0", @@ -8282,6 +8283,11 @@ "negotiator": "0.6.2" } }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + }, "acorn-jsx": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", @@ -20482,9 +20488,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", - "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==" + "version": "10.17.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.14.tgz", + "integrity": "sha512-G0UmX5uKEmW+ZAhmZ6PLTQ5eu/VPaT+d/tdLd5IFsKRPcbe6lPxocBtcYBFSaLaCW8O60AX90e91Nsp8lVHCNw==" } } }, @@ -20593,9 +20599,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", - "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==" + "version": "10.17.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.14.tgz", + "integrity": "sha512-G0UmX5uKEmW+ZAhmZ6PLTQ5eu/VPaT+d/tdLd5IFsKRPcbe6lPxocBtcYBFSaLaCW8O60AX90e91Nsp8lVHCNw==" }, "aes-js": { "version": "3.0.0", @@ -21096,6 +21102,7 @@ "@webassemblyjs/helper-module-context": "1.8.5", "@webassemblyjs/wasm-edit": "1.8.5", "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.2.1", "ajv": "^6.10.2", "ajv-keywords": "^3.4.1", "chrome-trace-event": "^1.0.2", @@ -21116,6 +21123,11 @@ "webpack-sources": "^1.4.1" }, "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" + }, "cacache": { "version": "12.0.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", diff --git a/package.json b/package.json index 5263b7e89..09170be4c 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@openzeppelin/docs-utils": "^0.1.0", "@openzeppelin/gsn-helpers": "^0.2.3", "@openzeppelin/gsn-provider": "^0.1.10", - "@openzeppelin/test-environment": "^0.1.3", + "@openzeppelin/test-environment": "^0.1.4", "@openzeppelin/test-helpers": "^0.5.5", "chai": "^4.2.0", "eslint": "^6.5.1", From 6d5ef3ef5f06a1daa6b89a0e6ee56a4727140098 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2020 14:02:33 -0300 Subject: [PATCH 20/24] Bump solhint from 3.0.0-rc.7 to 3.0.0-rc.8 (#2202) Bumps [solhint](https://github.com/protofire/solhint) from 3.0.0-rc.7 to 3.0.0-rc.8. - [Release notes](https://github.com/protofire/solhint/releases) - [Changelog](https://github.com/protofire/solhint/blob/master/CHANGELOG.md) - [Commits](https://github.com/protofire/solhint/compare/v3.0.0-rc.7...v3.0.0-rc.8) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- package-lock.json | 20 +++++++++++++------- package.json | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 744250a1b..6e296c3ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33056,12 +33056,12 @@ } }, "solhint": { - "version": "3.0.0-rc.7", - "resolved": "https://registry.npmjs.org/solhint/-/solhint-3.0.0-rc.7.tgz", - "integrity": "sha512-oXSfE90STaBMlyT0mUl9VdnfKf6wlBeWVBMZRO6oztZGnaapU26CqJZ5ctiNi3pK6/bPnQl3RIXBioKzv+woOQ==", + "version": "3.0.0-rc.8", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-3.0.0-rc.8.tgz", + "integrity": "sha512-FTS8Trg/C48ke+zIxAzbaFfCDzkVcwXHBNzCEKpe0S6GcCIfJs3p31tedcdRgkEWXRWs25pd1cFzBn6PNuUrZA==", "dev": true, "requires": { - "@solidity-parser/parser": "^0.5.2", + "@solidity-parser/parser": "^0.6.0", "ajv": "^6.6.1", "antlr4": "4.7.1", "ast-parents": "0.0.1", @@ -33078,6 +33078,12 @@ "semver": "^6.3.0" }, "dependencies": { + "@solidity-parser/parser": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.6.0.tgz", + "integrity": "sha512-RiJXfS22frulogcfQCFhbKrd5ATu6P4tYUv/daChiIh6VHyKQ1kkVZVfX6aP7c2YGU/Bf9RwGNKdwLjfpaoqYQ==", + "dev": true + }, "acorn": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", @@ -33085,9 +33091,9 @@ "dev": true }, "ajv": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", - "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", + "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", diff --git a/package.json b/package.json index 09170be4c..856c82b59 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "lodash.zip": "^4.2.0", "micromatch": "^4.0.2", "mocha": "^7.1.1", - "solhint": "^3.0.0-rc.7", + "solhint": "^3.0.0-rc.8", "solidity-coverage": "github:rotcivegaf/solidity-coverage#5875f5b7bc74d447f3312c9c0e9fc7814b482477", "solidity-docgen": "^0.4.1" }, From c986dfb256c570a7aeb3bf0e035ee73c7c595b76 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2020 14:17:12 -0300 Subject: [PATCH 21/24] [Security] Bump acorn from 6.4.0 to 6.4.1 (#2204) Bumps [acorn](https://github.com/acornjs/acorn) from 6.4.0 to 6.4.1. **This update includes security fixes.** - [Release notes](https://github.com/acornjs/acorn/releases) - [Commits](https://github.com/acornjs/acorn/compare/6.4.0...6.4.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- package-lock.json | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6e296c3ab..4227435a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4009,8 +4009,7 @@ "acorn": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", - "dev": true + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" }, "acorn-jsx": { "version": "5.1.0", @@ -8283,11 +8282,6 @@ "negotiator": "0.6.2" } }, - "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" - }, "acorn-jsx": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", @@ -21102,7 +21096,6 @@ "@webassemblyjs/helper-module-context": "1.8.5", "@webassemblyjs/wasm-edit": "1.8.5", "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.2.1", "ajv": "^6.10.2", "ajv-keywords": "^3.4.1", "chrome-trace-event": "^1.0.2", @@ -21123,11 +21116,6 @@ "webpack-sources": "^1.4.1" }, "dependencies": { - "acorn": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", - "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" - }, "cacache": { "version": "12.0.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", From 5bb8d0245bab09a863bbd4865327164645fdbf66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Mon, 20 Apr 2020 16:43:05 -0300 Subject: [PATCH 22/24] Improve Hooks documentation (#2199) * Improve Hooks docs * Improve Utils docs * Apply suggestions from code review Co-Authored-By: Francisco Giordano * Add enumerable code samples * Remove import statement from example Co-authored-by: Francisco Giordano --- contracts/token/ERC20/ERC20.sol | 2 +- contracts/token/ERC721/ERC721.sol | 2 +- contracts/token/ERC777/ERC777.sol | 2 +- contracts/utils/EnumerableMap.sol | 24 ++++ contracts/utils/EnumerableSet.sol | 13 +- contracts/utils/README.adoc | 42 ++++-- docs/modules/ROOT/nav.adoc | 5 +- .../ROOT/pages/extending-contracts.adoc | 123 ++++++++++++++++++ docs/modules/ROOT/pages/using-hooks.adoc | 7 - 9 files changed, 195 insertions(+), 25 deletions(-) create mode 100644 docs/modules/ROOT/pages/extending-contracts.adoc delete mode 100644 docs/modules/ROOT/pages/using-hooks.adoc diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 9503a0a80..2ee0f2ef5 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -299,7 +299,7 @@ contract ERC20 is Context, IERC20 { * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks]. + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 0552ce7f3..de67e48fd 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -514,7 +514,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable * - when `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * - * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks]. + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { } } diff --git a/contracts/token/ERC777/ERC777.sol b/contracts/token/ERC777/ERC777.sol index bd7880b65..c09518cdc 100644 --- a/contracts/token/ERC777/ERC777.sol +++ b/contracts/token/ERC777/ERC777.sol @@ -492,7 +492,7 @@ contract ERC777 is Context, IERC777, IERC20 { * - when `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * - * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks]. + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address operator, address from, address to, uint256 tokenId) internal virtual { } } diff --git a/contracts/utils/EnumerableMap.sol b/contracts/utils/EnumerableMap.sol index 9ba74de56..109af5908 100644 --- a/contracts/utils/EnumerableMap.sol +++ b/contracts/utils/EnumerableMap.sol @@ -1,5 +1,29 @@ pragma solidity ^0.6.0; +/** + * @dev Library for managing an enumerable variant of Solidity's + * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] + * type. + * + * Maps have the following properties: + * + * - Entries are added, removed, and checked for existence in constant time + * (O(1)). + * - Entries are enumerated in O(n). No guarantees are made on the ordering. + * + * ``` + * contract Example { + * // Add the library methods + * using EnumerableMap for EnumerableMap.UintToAddressMap; + * + * // Declare a set state variable + * EnumerableMap.UintToAddressMap private myMap; + * } + * ``` + * + * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are + * supported. + */ library EnumerableMap { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Map type with diff --git a/contracts/utils/EnumerableSet.sol b/contracts/utils/EnumerableSet.sol index 4c040e9fa..e855700cc 100644 --- a/contracts/utils/EnumerableSet.sol +++ b/contracts/utils/EnumerableSet.sol @@ -11,11 +11,18 @@ pragma solidity ^0.6.0; * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * - * As of v2.5.0, only `address` sets are supported. + * ``` + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; * - * Include with `using EnumerableSet for EnumerableSet.AddressSet;`. + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` * - * @author Alberto Cuesta Cañada + * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` + * (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code diff --git a/contracts/utils/README.adoc b/contracts/utils/README.adoc index 5f8249389..1f0dcf0b1 100644 --- a/contracts/utils/README.adoc +++ b/contracts/utils/README.adoc @@ -1,25 +1,49 @@ = Utilities -Miscellaneous contracts containing utility functions, often related to working with different data types. +Miscellaneous contracts and libraries containing utility functions you can use to improve security, work with new data types, or safely use low-level primitives. + +Security tools include: + + * {Pausable}: provides a simple way to halt activity in your contracts (often in reponse to an external threat). + * {ReentrancyGuard}: protects you from https://blog.openzeppelin.com/reentrancy-after-istanbul/[reentrant calls]. + +The {Address}, {Arrays} and {Strings} libraries provide more operations related to these native data types, while {SafeCast} adds ways to safely convert between the different signed and unsigned numeric types. + +For new data types: + + * {Counters}: a simple way to get a counter that can only be incremented or decremented. Very useful for ID generation, counting contract activity, among others. + * {EnumerableMap}: like Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] type, but with key-value _enumeration_: this will let you know how many entries a mapping has, and iterate over them (which is not possible with `mapping`). + * {EnumerableSet}: like {EnumerableMap}, but for https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets]. Can be used to store privileged accounts, issued IDs, etc. + +[NOTE] +==== +Because Solidity does not support generic types, {EnumerableMap} and {EnumerableSet} are specialized to a limited number of key-value types. + +As of v3.0, {EnumerableMap} supports `uint256 -> address` (`UintToAddressMap`), and {EnumerableSet} supports `address` and `uint256` (`AddressSet` and `UintSet`). +==== + +Finally, {Create2} contains all necessary utilities to safely use the https://blog.openzeppelin.com/getting-the-most-out-of-create2/[`CREATE2` EVM opcode], without having to deal with low-level assembly. == Contracts -{{Address}} +{{Pausable}} -{{SafeCast}} +{{ReentrancyGuard}} + +== Libraries + +{{Address}} {{Arrays}} {{Counters}} -{{Strings}} - -{{EnumerableSet}} +{{Create2}} {{EnumerableMap}} -{{Create2}} +{{EnumerableSet}} -{{ReentrancyGuard}} +{{SafeCast}} -{{Pausable}} +{{Strings}} diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 857d116b5..d155159eb 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -8,12 +8,11 @@ ** xref:erc721.adoc[ERC721] ** xref:erc777.adoc[ERC777] -* xref:using-hooks.adoc[Using Hooks] - * xref:gsn.adoc[Gas Station Network] ** xref:gsn-strategies.adoc[Strategies] +* xref:extending-contracts.adoc[Extending Contracts] + * xref:utilities.adoc[Utilities] - * xref:releases-stability.adoc[Releases & Stability] diff --git a/docs/modules/ROOT/pages/extending-contracts.adoc b/docs/modules/ROOT/pages/extending-contracts.adoc new file mode 100644 index 000000000..5d210b237 --- /dev/null +++ b/docs/modules/ROOT/pages/extending-contracts.adoc @@ -0,0 +1,123 @@ += Extending Contracts + +Most of the OpenZeppelin Contracts are expected to be used via https://solidity.readthedocs.io/en/latest/contracts.html#inheritance[inheritance]: you will _inherit_ from them when writing your own contracts. + +This is the commonly found `is` syntax, like in `contract MyToken is ERC20`. + +[NOTE] +==== +Unlike ``contract``s, Solidity ``library``s are not inherited from and instead rely on the https://solidity.readthedocs.io/en/latest/contracts.html#using-for[`using for`] syntax. + +OpenZeppelin Contracts has some ``library``s: most are in the xref:api:utils.adoc[Utils] directory. +==== + +== Overriding + +Inheritance is often used to add the parent contract's functionality to your own contract, but that's not all it can do. You can also _change_ how some parts of the parent behave using _overrides_. + +For example, imagine you want to change xref:api:access.adoc#AccessControl[`AccessControl`] so that xref:api:access.adoc#AccessControl-revokeRole-bytes32-address-[`revokeRole`] can no longer be called. This can be achieved using overrides: + +```solidity +pragma solidity ^0.6.0; + +import "@openzeppelin/contracts/access/AccessControl.sol"; + +contract ModifiedAccessControl is AccessControl { + // Override the revokeRole function + function revokeRole(bytes32, address) public override { + revert("ModifiedAccessControl: cannot revoke roles"); + } +} +``` + +The old `revokeRole` is then replaced by our override, and any calls to it will immediately revert. We cannot _remove_ the function from the contract, but reverting on all calls is good enough. + +=== Calling `super` + +Sometimes you want to _extend_ a parent's behavior, instead of outright changing it to something else. This is where `super` comes in. + +The `super` keyword will let you call functions defined in a parent contract, even if they are overridden. This mechanism can be used to add additional checks to a function, emit events, or otherwise add functionality as you see fit. + +TIP: For more information on how overrides work, head over to the https://solidity.readthedocs.io/en/latest/contracts.html#index-17[official Solidity documentation]. + +Here is a modified version of xref:api:access.adoc#AccessControl[`AccessControl`] where xref:api:access.adoc#AccessControl-revokeRole-bytes32-address-[`revokeRole`] cannot be used to revoke the `DEFAULT_ADMIN_ROLE`: + + +```solidity +pragma solidity ^0.6.0; + +import "@openzeppelin/contracts/access/AccessControl.sol"; + +contract ModifiedAccessControl is AccessControl { + function revokeRole(bytes32 role, address account) public override { + require( + role != DEFAULT_ADMIN_ROLE, + "ModifiedAccessControl: cannot revoke default admin role" + ); + + super.revokeRole(role, account); + } +} +``` + +The `super.revokeRole` statement at the end will invoke ``AccessControl``'s original version of `revokeRole`, the same code that would've run if there were no overrides in place. + +NOTE: As of v3.0.0, `view` functions are not `virtual` in OpenZeppelin, and therefore cannot be overriden. We're considering https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2154[lifting this restriction] in an upcoming release. Let us know if this is something you care about! + +[[using-hooks]] +== Using Hooks + +Sometimes, in order to extend a parent contract you will need to override multiple related functions, which leads to code duplication and increased likelihood of bugs. + +For example, consider implementing safe xref:api:token/ERC20.adoc#ERC20[`ERC20`] transfers in the style of xref:api:token/ERC721.adoc#IERC721Receiver[`IERC721Receiver`]. You may think overriding xref:api:token/ERC20.adoc#ERC20-transfer-address-uint256-[`transfer`] and xref:api:token/ERC20.adoc#ERC20-transferFrom-address-address-uint256-[`transferFrom`] would be enough, but what about xref:api:token/ERC20.adoc#ERC20-_transfer-address-address-uint256-[`_transfer`] and xref:api:token/ERC20.adoc#ERC20-_mint-address-uint256-[`_mint`]? To prevent you from having to deal with these details, we introduced **hooks**. + +Hooks are simply functions that are called before or after some action takes place. They provide a centralized point to _hook into_ and extend the original behavior. + +Here's how you would implement the `IERC721Receiver` pattern in `ERC20`, using the xref:api:token/ERC20.adoc#ERC20-_beforeTokenTransfer-address-address-uint256-[`_beforeTokenTransfer`] hook: + +```solidity +pragma solidity ^0.6.0; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract ERC20WithSafeTransfer is ERC20 { + function _beforeTokenTransfer(address from, address to, uint256 amount) + internal virtual override + { + super._beforeTokenTransfer(from, to, amount); + + require(_validRecipient(to), "ERC20WithSafeTransfer: invalid recipient"); + } + + function _validRecipient(address to) private view returns (bool) { + ... + } +``` + +Using hooks this way leads to cleaner and safer code, without having to rely on a deep understanding of the parent's internals. + +[NOTE] +==== +Hooks are a new feature of OpenZeppelin Contracts v3.0.0, and we're eager to learn how you plan to use them! + +So far, the only available hook is `_beforeTransferHook`, in all of xref:api:token/ERC20.adoc#ERC20-_beforeTokenTransfer-address-address-uint256-[`ERC20`], xref:api:token/ERC721.adoc#ERC721-_beforeTokenTransfer-address-address-uint256-[ERC721] and xref:api:token/ERC777.adoc#ERC777-_beforeTokenTransfer-address-address-address-uint256-[ERC777]. If you have ideas for new hooks, let us know! +==== + +=== Rules of Hooks + +There's a few guidelines you should follow when writing code that uses hooks in order to prevent issues. They are very simple, but do make sure you follow them: + +1. Whenever you override a parent's hook, re-apply the `virtual` attribute to the hook. That will allow child contracts to add more functionality to the hook. +2. **Always** call the parent's hook in your override using `super`. This will make sure all hooks in the inheritance tree are called: contracts like xref:api:token/ERC20.adoc#ERC20Pausable[`ERC20Pausable`] rely on this behavior. + +```solidity +contract MyToken is ERC20 { + function _beforeTokenTransfer(address from, address to, uint256 amount) + internal virtual override // Add virtual here! + { + super._beforeTokenTransfer(from, to, amount); // Call parent hook + ... + } +} +``` +That's it! Enjoy simpler code using hooks! diff --git a/docs/modules/ROOT/pages/using-hooks.adoc b/docs/modules/ROOT/pages/using-hooks.adoc deleted file mode 100644 index dcb8413ac..000000000 --- a/docs/modules/ROOT/pages/using-hooks.adoc +++ /dev/null @@ -1,7 +0,0 @@ -# Using Hooks - -is a good idea. - -using hooks: - super.hook() must _always_ be called - if you want to cancel the process, revert. works both in before and after From 715ec806f033176fd9f5084a6232486e597c488f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Mon, 20 Apr 2020 20:05:48 -0300 Subject: [PATCH 23/24] ERC721 deploy ready fixes (#2192) * Add baseURI to ERC721MinterPauser constructor * Add tokenURI to mint * Remove tokenId and tokenURI from ERC721 deploy ready * Rename ERC721MinterPauser to ERC721MinterAutoID, remove Pausable mechanisms * Restore pausing to ERC721 * Rename deploy ready to presets * Rename ERC721 preset --- .../ERC20PresetMinterPauser.sol} | 14 ++--- .../ERC721PresetMinterPauserAutoId.sol} | 45 ++++++++++----- .../{deploy-ready => presets}/README.adoc | 6 +- contracts/token/ERC721/ERC721.sol | 30 ++++++++-- .../ERC20PresetMinterPauser.test.js} | 10 ++-- .../ERC721PresetMinterPauserAutoId.js} | 55 ++++++++++++------- 6 files changed, 105 insertions(+), 55 deletions(-) rename contracts/{deploy-ready/ERC20MinterPauser.sol => presets/ERC20PresetMinterPauser.sol} (79%) rename contracts/{deploy-ready/ERC721MinterPauser.sol => presets/ERC721PresetMinterPauserAutoId.sol} (51%) rename contracts/{deploy-ready => presets}/README.adoc (87%) rename test/{deploy-ready/ERC20MinterPauser.test.js => presets/ERC20PresetMinterPauser.test.js} (91%) rename test/{deploy-ready/ERC721MinterPauser.test.js => presets/ERC721PresetMinterPauserAutoId.js} (67%) diff --git a/contracts/deploy-ready/ERC20MinterPauser.sol b/contracts/presets/ERC20PresetMinterPauser.sol similarity index 79% rename from contracts/deploy-ready/ERC20MinterPauser.sol rename to contracts/presets/ERC20PresetMinterPauser.sol index 2e50997cb..96cf1e7b2 100644 --- a/contracts/deploy-ready/ERC20MinterPauser.sol +++ b/contracts/presets/ERC20PresetMinterPauser.sol @@ -16,11 +16,11 @@ import "../token/ERC20/ERC20Pausable.sol"; * This contract uses {AccessControl} to lock permissioned functions using the * different roles - head to its documentation for details. * - * The account that deploys the contract will be granted the minter role, the - * pauser role, and the default admin role, meaning it will be able to grant - * both the minter and pauser roles. + * The account that deploys the contract will be granted the minter and pauser + * roles, as well as the default admin role, which will let it grant both minter + * and pauser roles to aother accounts */ -contract ERC20MinterPauser is Context, AccessControl, ERC20Burnable, ERC20Pausable { +contract ERC20PresetMinterPauser is Context, AccessControl, ERC20Burnable, ERC20Pausable { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); @@ -47,7 +47,7 @@ contract ERC20MinterPauser is Context, AccessControl, ERC20Burnable, ERC20Pausab * - the caller must have the `MINTER_ROLE`. */ function mint(address to, uint256 amount) public { - require(hasRole(MINTER_ROLE, _msgSender()), "ERC20MinterPauser: must have minter role to mint"); + require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint"); _mint(to, amount); } @@ -61,7 +61,7 @@ contract ERC20MinterPauser is Context, AccessControl, ERC20Burnable, ERC20Pausab * - the caller must have the `PAUSER_ROLE`. */ function pause() public { - require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20MinterPauser: must have pauser role to pause"); + require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause"); _pause(); } @@ -75,7 +75,7 @@ contract ERC20MinterPauser is Context, AccessControl, ERC20Burnable, ERC20Pausab * - the caller must have the `PAUSER_ROLE`. */ function unpause() public { - require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20MinterPauser: must have pauser role to unpause"); + require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to unpause"); _unpause(); } diff --git a/contracts/deploy-ready/ERC721MinterPauser.sol b/contracts/presets/ERC721PresetMinterPauserAutoId.sol similarity index 51% rename from contracts/deploy-ready/ERC721MinterPauser.sol rename to contracts/presets/ERC721PresetMinterPauserAutoId.sol index 68f46ed1c..128a0b464 100644 --- a/contracts/deploy-ready/ERC721MinterPauser.sol +++ b/contracts/presets/ERC721PresetMinterPauserAutoId.sol @@ -2,6 +2,7 @@ pragma solidity ^0.6.0; import "../access/AccessControl.sol"; import "../GSN/Context.sol"; +import "../utils/Counters.sol"; import "../token/ERC721/ERC721.sol"; import "../token/ERC721/ERC721Burnable.sol"; import "../token/ERC721/ERC721Pausable.sol"; @@ -12,33 +13,43 @@ import "../token/ERC721/ERC721Pausable.sol"; * - ability for holders to burn (destroy) their tokens * - a minter role that allows for token minting (creation) * - a pauser role that allows to stop all token transfers + * - token ID and URI autogeneration * * This contract uses {AccessControl} to lock permissioned functions using the * different roles - head to its documentation for details. * - * The account that deploys the contract will be granted the minter role, the - * pauser role, and the default admin role, meaning it will be able to grant - * both the minter and pauser roles. + * The account that deploys the contract will be granted the minter and pauser + * roles, as well as the default admin role, which will let it grant both minter + * and pauser roles to aother accounts */ -contract ERC721MinterPauser is Context, AccessControl, ERC721Burnable, ERC721Pausable { +contract ERC721PresetMinterPauserAutoId is Context, AccessControl, ERC721Burnable, ERC721Pausable { + using Counters for Counters.Counter; + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); + Counters.Counter private _tokenIdTracker; + /** - * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the - * account that deploys the contract. + * @dev Grants `DEFAULT_ADMIN_ROLE` and `MINTER_ROLE`to the account that + * deploys the contract. * - * See {ERC721-constructor}. + * Token URIs will be autogenerated based on `baseURI` and their token IDs. + * See {ERC721-tokenURI}. */ - constructor(string memory name, string memory symbol) public ERC721(name, symbol) { + constructor(string memory name, string memory symbol, string memory baseURI) public ERC721(name, symbol) { _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(MINTER_ROLE, _msgSender()); _setupRole(PAUSER_ROLE, _msgSender()); + + _setBaseURI(baseURI); } /** - * @dev Creates the `tokenId` tokens for `to`. + * @dev Creates a new token for `to`. Its token ID will be automatically + * assigned (and available on the emitted {Transfer} event), and the token + * URI autogenerated based on the base URI passed at construction. * * See {ERC721-_mint}. * @@ -46,9 +57,13 @@ contract ERC721MinterPauser is Context, AccessControl, ERC721Burnable, ERC721Pau * * - the caller must have the `MINTER_ROLE`. */ - function mint(address to, uint256 tokenId) public { - require(hasRole(MINTER_ROLE, _msgSender()), "ERC721MinterPauser: must have minter role to mint"); - _mint(to, tokenId); + function mint(address to) public { + require(hasRole(MINTER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have minter role to mint"); + + // We can just use balanceOf to create the new tokenId because tokens + // can be burned (destroyed), so we need a separate counter. + _mint(to, _tokenIdTracker.current()); + _tokenIdTracker.increment(); } /** @@ -61,21 +76,21 @@ contract ERC721MinterPauser is Context, AccessControl, ERC721Burnable, ERC721Pau * - the caller must have the `PAUSER_ROLE`. */ function pause() public { - require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721MinterPauser: must have pauser role to pause"); + require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to pause"); _pause(); } /** * @dev Unpauses all token transfers. * - * See {ERC20Pausable} and {Pausable-_unpause}. + * See {ERC721Pausable} and {Pausable-_unpause}. * * Requirements: * * - the caller must have the `PAUSER_ROLE`. */ function unpause() public { - require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721MinterPauser: must have pauser role to unpause"); + require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to unpause"); _unpause(); } diff --git a/contracts/deploy-ready/README.adoc b/contracts/presets/README.adoc similarity index 87% rename from contracts/deploy-ready/README.adoc rename to contracts/presets/README.adoc index 6ae8e63ab..e649928e4 100644 --- a/contracts/deploy-ready/README.adoc +++ b/contracts/presets/README.adoc @@ -1,4 +1,4 @@ -= Deploy Ready += Presets These contracts integrate different Ethereum standards (ERCs) with custom extensions and modules, showcasing common configurations that are ready to deploy **without having to write any Solidity code**. @@ -8,6 +8,6 @@ TIP: Intermediate and advanced users can use these as starting points when writi == Tokens -{{ERC20MinterPauser}} +{{ERC20PresetMinterPauser}} -{{ERC721MinterPauser}} +{{ERC721PresetMinterPauserAutoId}} diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index de67e48fd..60125a083 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -134,11 +134,33 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable /** * @dev Returns the URI for a given token ID. May return an empty string. * - * If no base URI was set (via {_setBaseURI}), return the token ID's URI. - * If a base URI was set, it will be added as a prefix to the token ID's URI, - * or to the token ID itself, if no URI is set for that token ID. + * If a base URI is set (via {_setBaseURI}), it is added as a prefix to the + * token's own URI (via {_setTokenURI}). * - * Reverts if the token ID does not exist. + * If there is a base URI but no token URI, the token's ID will be used as + * its URI when appending it to the base URI. This pattern for autogenerated + * token URIs can lead to large gas savings. + * + * .Examples + * |=== + * |`_setBaseURI()` |`_setTokenURI()` |`tokenURI()` + * | "" + * | "" + * | "" + * | "" + * | "token.uri/123" + * | "token.uri/123" + * | "token.uri/" + * | "123" + * | "token.uri/123" + * | "token.uri/" + * | "" + * | "token.uri/" + * |=== + * + * Requirements: + * + * - `tokenId` must exist. */ function tokenURI(uint256 tokenId) public view override returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); diff --git a/test/deploy-ready/ERC20MinterPauser.test.js b/test/presets/ERC20PresetMinterPauser.test.js similarity index 91% rename from test/deploy-ready/ERC20MinterPauser.test.js rename to test/presets/ERC20PresetMinterPauser.test.js index ae1aa13c5..179a475a5 100644 --- a/test/deploy-ready/ERC20MinterPauser.test.js +++ b/test/presets/ERC20PresetMinterPauser.test.js @@ -5,9 +5,9 @@ const { ZERO_ADDRESS } = constants; const { expect } = require('chai'); -const ERC20MinterPauser = contract.fromArtifact('ERC20MinterPauser'); +const ERC20PresetMinterPauser = contract.fromArtifact('ERC20PresetMinterPauser'); -describe('ERC20MinterPauser', function () { +describe('ERC20PresetMinterPauser', function () { const [ deployer, other ] = accounts; const name = 'MinterPauserToken'; @@ -20,7 +20,7 @@ describe('ERC20MinterPauser', function () { const PAUSER_ROLE = web3.utils.soliditySha3('PAUSER_ROLE'); beforeEach(async function () { - this.token = await ERC20MinterPauser.new(name, symbol, { from: deployer }); + this.token = await ERC20PresetMinterPauser.new(name, symbol, { from: deployer }); }); it('deployer has the default admin role', async function () { @@ -54,7 +54,7 @@ describe('ERC20MinterPauser', function () { it('other accounts cannot mint tokens', async function () { await expectRevert( this.token.mint(other, amount, { from: other }), - 'ERC20MinterPauser: must have minter role to mint' + 'ERC20PresetMinterPauser: must have minter role to mint' ); }); }); @@ -86,7 +86,7 @@ describe('ERC20MinterPauser', function () { }); it('other accounts cannot pause', async function () { - await expectRevert(this.token.pause({ from: other }), 'ERC20MinterPauser: must have pauser role to pause'); + await expectRevert(this.token.pause({ from: other }), 'ERC20PresetMinterPauser: must have pauser role to pause'); }); }); diff --git a/test/deploy-ready/ERC721MinterPauser.test.js b/test/presets/ERC721PresetMinterPauserAutoId.js similarity index 67% rename from test/deploy-ready/ERC721MinterPauser.test.js rename to test/presets/ERC721PresetMinterPauserAutoId.js index fff63928a..1dc4c1cbb 100644 --- a/test/deploy-ready/ERC721MinterPauser.test.js +++ b/test/presets/ERC721PresetMinterPauserAutoId.js @@ -5,22 +5,32 @@ const { ZERO_ADDRESS } = constants; const { expect } = require('chai'); -const ERC721MinterPauser = contract.fromArtifact('ERC721MinterPauser'); +const ERC721PresetMinterPauserAutoId = contract.fromArtifact('ERC721PresetMinterPauserAutoId'); -describe('ERC721MinterPauser', function () { +describe('ERC721PresetMinterPauserAutoId', function () { const [ deployer, other ] = accounts; - const name = 'MinterPauserToken'; - const symbol = 'DRT'; - - const tokenId = new BN('1337'); + const name = 'MinterAutoIDToken'; + const symbol = 'MAIT'; + const baseURI = 'my.app/'; const DEFAULT_ADMIN_ROLE = '0x0000000000000000000000000000000000000000000000000000000000000000'; const MINTER_ROLE = web3.utils.soliditySha3('MINTER_ROLE'); - const PAUSER_ROLE = web3.utils.soliditySha3('PAUSER_ROLE'); beforeEach(async function () { - this.token = await ERC721MinterPauser.new(name, symbol, { from: deployer }); + this.token = await ERC721PresetMinterPauserAutoId.new(name, symbol, baseURI, { from: deployer }); + }); + + it('token has correct name', async function () { + expect(await this.token.name()).to.equal(name); + }); + + it('token has correct symbol', async function () { + expect(await this.token.symbol()).to.equal(symbol); + }); + + it('token has correct base URI', async function () { + expect(await this.token.baseURI()).to.equal(baseURI); }); it('deployer has the default admin role', async function () { @@ -33,29 +43,27 @@ describe('ERC721MinterPauser', function () { expect(await this.token.getRoleMember(MINTER_ROLE, 0)).to.equal(deployer); }); - it('deployer has the pauser role', async function () { - expect(await this.token.getRoleMemberCount(PAUSER_ROLE)).to.be.bignumber.equal('1'); - expect(await this.token.getRoleMember(PAUSER_ROLE, 0)).to.equal(deployer); - }); - - it('minter and pauser role admin is the default admin', async function () { + it('minter role admin is the default admin', async function () { expect(await this.token.getRoleAdmin(MINTER_ROLE)).to.equal(DEFAULT_ADMIN_ROLE); - expect(await this.token.getRoleAdmin(PAUSER_ROLE)).to.equal(DEFAULT_ADMIN_ROLE); }); describe('minting', function () { it('deployer can mint tokens', async function () { - const receipt = await this.token.mint(other, tokenId, { from: deployer }); + const tokenId = new BN('0'); + + const receipt = await this.token.mint(other, { from: deployer }); expectEvent(receipt, 'Transfer', { from: ZERO_ADDRESS, to: other, tokenId }); expect(await this.token.balanceOf(other)).to.be.bignumber.equal('1'); expect(await this.token.ownerOf(tokenId)).to.equal(other); + + expect(await this.token.tokenURI(tokenId)).to.equal(baseURI + tokenId); }); it('other accounts cannot mint tokens', async function () { await expectRevert( - this.token.mint(other, tokenId, { from: other }), - 'ERC721MinterPauser: must have minter role to mint' + this.token.mint(other, { from: other }), + 'ERC721PresetMinterPauserAutoId: must have minter role to mint' ); }); }); @@ -81,19 +89,24 @@ describe('ERC721MinterPauser', function () { await this.token.pause({ from: deployer }); await expectRevert( - this.token.mint(other, tokenId, { from: deployer }), + this.token.mint(other, { from: deployer }), 'ERC721Pausable: token transfer while paused' ); }); it('other accounts cannot pause', async function () { - await expectRevert(this.token.pause({ from: other }), 'ERC721MinterPauser: must have pauser role to pause'); + await expectRevert( + this.token.pause({ from: other }), + 'ERC721PresetMinterPauserAutoId: must have pauser role to pause' + ); }); }); describe('burning', function () { it('holders can burn their tokens', async function () { - await this.token.mint(other, tokenId, { from: deployer }); + const tokenId = new BN('0'); + + await this.token.mint(other, { from: deployer }); const receipt = await this.token.burn(tokenId, { from: other }); From 528c23d6799e51b02f1b58514fde93a6de128f7a Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Mon, 20 Apr 2020 20:10:30 -0300 Subject: [PATCH 24/24] Remove ethpm.json and update releasing docs (#2205) * remove ethpm.json * update releasing document * fix release documentation to be more realistic --- RELEASING.md | 79 ++----------------- .../ROOT/pages/releases-stability.adoc | 4 +- ethpm.json | 17 ---- scripts/release/synchronize-versions.js | 4 +- 4 files changed, 11 insertions(+), 93 deletions(-) delete mode 100644 ethpm.json diff --git a/RELEASING.md b/RELEASING.md index 8934ff70c..5840c9c9f 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,83 +1,20 @@ # Releasing -This document describes our release process, and contains the steps to be followed by an OpenZeppelin maintainer at the several stages of a release. +> Visit the documentation for [details about release schedule]. -We release a new version of OpenZeppelin monthly. Release cycles are tracked in the [issue milestones](https://github.com/OpenZeppelin/openzeppelin-contracts/milestones). +Start on an up-to-date `master` branch. -Each release has at least one release candidate published first, intended for community review and any critical fixes that may come out of it. At the moment we leave 1 week between the first release candidate and the final release. +Create the release branch with `npm run release start minor`. -Before starting make sure to verify the following items. -* Your local `master` branch is in sync with your `upstream` remote (it may have another name depending on your setup). -* Your repo is clean, particularly with no untracked files in the contracts and tests directories. Verify with `git clean -n`. +Publish a release candidate with `npm run release rc`. +Publish the final release with `npm run release final`. -## Creating the release branch +Follow the general [OpenZeppelin release checklist]. -We'll refer to a release `vX.Y.Z`. +[details about release schedule]: https://docs.openzeppelin.com/contracts/releases-stability +[OpenZeppelin release checklist]: https://github.com/OpenZeppelin/code-style/blob/master/RELEASE_CHECKLIST.md -``` -git checkout master -git checkout -b release-vX.Y.Z -``` - -## Creating a release candidate - -Once in the release branch, change the version string in `package.json`, `package-lock.json` and `ethpm.json` to `X.Y.Z-rc.R`. (This will be `X.Y.Z-rc.1` for the first release candidate.) Commit these changes and tag the commit as `vX.Y.Z-rc.R`. - -``` -git add package.json package-lock.json ethpm.json -git commit -m "Release candidate vX.Y.Z-rc.R" -git tag -a vX.Y.Z-rc.R -git push upstream release-vX.Y.Z -git push upstream vX.Y.Z-rc.R -``` - -Draft the release notes in our [GitHub releases](https://github.com/OpenZeppelin/openzeppelin-contracts/releases). Make sure to mark it as a pre-release! Try to be consistent with our previous release notes in the title and format of the text. Release candidates don't need a detailed changelog, but make sure to include a link to GitHub's compare page. - -Once the CI run for the new tag is green, publish on npm under the `next` tag. You should see the contracts compile automatically. - -``` -npm publish --tag next -``` - -Publish the release notes on GitHub and the forum, and ask our community manager to announce the release candidate on at least Twitter. - -## Creating the final release - -Make sure to have the latest changes from `upstream` in your local release branch. - -``` -git checkout release-vX.Y.Z -git pull upstream -``` - -Before starting the release process, make one final commit to CHANGELOG.md, including the date of the release. - -Change the version string in `package.json`, `package-lock.json` and `ethpm.json` removing the "-rc.R" suffix. Commit these changes and tag the commit as `vX.Y.Z`. - -``` -git add package.json package-lock.json ethpm.json -git commit -m "Release vX.Y.Z" -git tag -a vX.Y.Z -git push upstream release-vX.Y.Z -git push upstream vX.Y.Z -``` - -Draft the release notes in GitHub releases. Try to be consistent with our previous release notes in the title and format of the text. Make sure to include a detailed changelog. - -Once the CI run for the new tag is green, publish on npm. You should see the contracts compile automatically. - -``` -npm publish -``` - -Publish the release notes on GitHub and ask our community manager to announce the release! - -Delete the `next` tag in the npm package as there is no longer a release candidate. - -``` -npm dist-tag rm --otp $2FA_CODE @openzeppelin/contracts next -``` ## Merging the release branch diff --git a/docs/modules/ROOT/pages/releases-stability.adoc b/docs/modules/ROOT/pages/releases-stability.adoc index 2efee0306..94dbb3972 100644 --- a/docs/modules/ROOT/pages/releases-stability.adoc +++ b/docs/modules/ROOT/pages/releases-stability.adoc @@ -12,7 +12,7 @@ OpenZeppelin Contracts follows a <" - ], - "keywords": [ - "solidity", - "ethereum", - "smart", - "contracts", - "security", - "zeppelin" - ], - "license": "MIT" -} diff --git a/scripts/release/synchronize-versions.js b/scripts/release/synchronize-versions.js index cadb6be43..15915a1c8 100755 --- a/scripts/release/synchronize-versions.js +++ b/scripts/release/synchronize-versions.js @@ -1,14 +1,12 @@ #!/usr/bin/env node -// Synchronizes the versions in ethpm.json and contracts/package.json with the -// one in package.json. +// Synchronizes the version in contracts/package.json with the one in package.json. // This is run automatically when npm version is run. const fs = require('fs'); const cp = require('child_process'); setVersion('contracts/package.json'); -setVersion('ethpm.json'); function setVersion (file) { const json = JSON.parse(fs.readFileSync(file));