Browse Source

Add to ERC1155 doc and minor fixes (#2282)

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
Andrew B Coathup 5 years ago
parent
commit
32f0fe5d08

+ 11 - 3
docs/modules/ROOT/pages/access-control.adoc

@@ -11,6 +11,8 @@ OpenZeppelin provides xref:api:access.adoc#Ownable[`Ownable`] for implementing o
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
+// contracts/MyContract.sol
+// SPDX-License-Identifier: MIT
 pragma solidity ^0.6.0;
 pragma solidity ^0.6.0;
 
 
 import "@openzeppelin/contracts/access/Ownable.sol";
 import "@openzeppelin/contracts/access/Ownable.sol";
@@ -46,7 +48,7 @@ While the simplicity of _ownership_ can be useful for simple systems or quick pr
 
 
 In essence, we will be defining multiple _roles_, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using `onlyOwner`. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.
 In essence, we will be defining multiple _roles_, each allowed to perform different sets of actions. An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for instead of simply using `onlyOwner`. Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.
 
 
-Most of software development uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.
+Most software uses access control systems that are role-based: some users are regular users, some may be supervisors or managers, and a few will often have administrative privileges.
 
 
 [[using-access-control]]
 [[using-access-control]]
 === Using `AccessControl`
 === Using `AccessControl`
@@ -58,6 +60,8 @@ Here's a simple example of using `AccessControl` in an xref:tokens.adoc#ERC20[`E
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
+// contracts/MyToken.sol
+// SPDX-License-Identifier: MIT
 pragma solidity ^0.6.0;
 pragma solidity ^0.6.0;
 
 
 import "@openzeppelin/contracts/access/AccessControl.sol";
 import "@openzeppelin/contracts/access/AccessControl.sol";
@@ -88,6 +92,8 @@ Let's augment our ERC20 token example by also defining a 'burner' role, which le
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
+// contracts/MyToken.sol
+// SPDX-License-Identifier: MIT
 pragma solidity ^0.6.0;
 pragma solidity ^0.6.0;
 
 
 import "@openzeppelin/contracts/access/AccessControl.sol";
 import "@openzeppelin/contracts/access/AccessControl.sol";
@@ -119,7 +125,7 @@ So clean! By splitting concerns this way, more granular levels of permission may
 [[granting-and-revoking]]
 [[granting-and-revoking]]
 === Granting and Revoking Roles
 === Granting and Revoking Roles
 
 
-The ERC20 token example above uses `\_setupRole`, an `internal` function that is useful when programmatically asigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?
+The ERC20 token example above uses `_setupRole`, an `internal` function that is useful when programmatically assigning roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?
 
 
 By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the `hasRole` check pass. To grant and revoke roles dynamically, you will need help from the _role's admin_.
 By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making the `hasRole` check pass. To grant and revoke roles dynamically, you will need help from the _role's admin_.
 
 
@@ -131,6 +137,8 @@ Let's take a look at the ERC20 token example, this time taking advantage of the
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
+// contracts/MyToken.sol
+// SPDX-License-Identifier: MIT
 pragma solidity ^0.6.0;
 pragma solidity ^0.6.0;
 
 
 import "@openzeppelin/contracts/access/AccessControl.sol";
 import "@openzeppelin/contracts/access/AccessControl.sol";
@@ -160,7 +168,7 @@ contract MyToken is ERC20, AccessControl {
 
 
 Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and _that_ role was granted to `msg.sender`, that same account can call `grantRole` to give minting or burning permission, and `revokeRole` to remove it.
 Note that, unlike the previous examples, no accounts are granted the 'minter' or 'burner' roles. However, because those roles' admin role is the default admin role, and _that_ role was granted to `msg.sender`, that same account can call `grantRole` to give minting or burning permission, and `revokeRole` to remove it.
 
 
-Dynamic role allocation is a often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as https://en.wikipedia.org/wiki/Know_your_customer[KYC], where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.
+Dynamic role allocation is often a desirable property, for example in systems where trust in a participant may vary over time. It can also be used to support use cases such as https://en.wikipedia.org/wiki/Know_your_customer[KYC], where the list of role-bearers may not be known up-front, or may be prohibitively expensive to include in a single transaction.
 
 
 [[querying-privileged-accounts]]
 [[querying-privileged-accounts]]
 === Querying Privileged Accounts
 === Querying Privileged Accounts

+ 1 - 1
docs/modules/ROOT/pages/drafts.adoc

@@ -16,4 +16,4 @@ Removed contracts are still available on the v2.5 release of OpenZeppelin Contra
 $ npm install @openzeppelin/contracts@v2.5
 $ npm install @openzeppelin/contracts@v2.5
 ```
 ```
 
 
-Refer to the xref:2.x@contracts:api:utils.adoc[v2.x documentation] when working with them.
+Refer to the xref:2.x@contracts:api:drafts.adoc[v2.x documentation] when working with them.

+ 129 - 1
docs/modules/ROOT/pages/erc1155.adoc

@@ -9,7 +9,7 @@ TIP: ERC1155 draws ideas from all of xref:erc20.adoc[ERC20], xref:721.adoc[ERC72
 
 
 The distinctive feature of ERC1155 is that it uses a single smart contract to represent multiple tokens at once. This is why its xref:api:token/ERC1155.adoc#IERC1155-balanceOf-address-uint256-[`balanceOf`] function differs from ERC20's and ERC777's: it has an additional `id` argument for the identifier of the token that you want to query the balance of.
 The distinctive feature of ERC1155 is that it uses a single smart contract to represent multiple tokens at once. This is why its xref:api:token/ERC1155.adoc#IERC1155-balanceOf-address-uint256-[`balanceOf`] function differs from ERC20's and ERC777's: it has an additional `id` argument for the identifier of the token that you want to query the balance of.
 
 
-This is similar to how ERC721 does things, but in that standard a token `id` has no concept of balance: each token is non-fungible and exists or doesn't. The xref:api:token/ERC721.adoc#IERC721-balanceOf-address-[`balanceOf`] function refers to _how many different tokens_ an account has, not how many of each. On the other hand, in ERC1155 accounts have a distinct balance for each token `id`, and non-fungible tokens are implemented by simply minting a single one of them.
+This is similar to how ERC721 does things, but in that standard a token `id` has no concept of balance: each token is non-fungible and exists or doesn't. The ERC721 xref:api:token/ERC721.adoc#IERC721-balanceOf-address-[`balanceOf`] function refers to _how many different tokens_ an account has, not how many of each. On the other hand, in ERC1155 accounts have a distinct balance for each token `id`, and non-fungible tokens are implemented by simply minting a single one of them.
 
 
 This approach leads to massive gas savings for projects that require multiple tokens. Instead of deploying a new contract for each token type, a single ERC1155 token contract can hold the entire system state, reducing deployment costs and complexity.
 This approach leads to massive gas savings for projects that require multiple tokens. Instead of deploying a new contract for each token type, a single ERC1155 token contract can hold the entire system state, reducing deployment costs and complexity.
 
 
@@ -19,3 +19,131 @@ This approach leads to massive gas savings for projects that require multiple to
 Because all state is held in a single contract, it is possible to operate over multiple tokens in a single transaction very efficiently. The standard provides two functions, xref:api:token/ERC1155.adoc#IERC1155-balanceOfBatch-address---uint256---[`balanceOfBatch`] and xref:api:token/ERC1155.adoc#IERC1155-safeBatchTransferFrom-address-address-uint256---uint256---bytes-[`safeBatchTransferFrom`], that make querying multiple balances and transferring multiple tokens simpler and less gas-intensive.
 Because all state is held in a single contract, it is possible to operate over multiple tokens in a single transaction very efficiently. The standard provides two functions, xref:api:token/ERC1155.adoc#IERC1155-balanceOfBatch-address---uint256---[`balanceOfBatch`] and xref:api:token/ERC1155.adoc#IERC1155-safeBatchTransferFrom-address-address-uint256---uint256---bytes-[`safeBatchTransferFrom`], that make querying multiple balances and transferring multiple tokens simpler and less gas-intensive.
 
 
 In the spirit of the standard, we've also included batch operations in the non-standard functions, such as xref:api:token/ERC1155.adoc#ERC1155-_mintBatch-address-uint256---uint256---bytes-[`_mintBatch`].
 In the spirit of the standard, we've also included batch operations in the non-standard functions, such as xref:api:token/ERC1155.adoc#ERC1155-_mintBatch-address-uint256---uint256---bytes-[`_mintBatch`].
+
+== Constructing an ERC1155 Token Contract
+
+We'll use ERC1155 to track multiple items in our game, which will each have their own unique attributes. We mint all items to the deployer of the contract, which we can later transfer to players. Players are free to keep their tokens or trade them with other people as they see fit, as they would any other asset on the blockchain!  
+
+For simplicity we will mint all items in the constructor but you could add minting functionality to the contract to mint on demand to players. 
+
+TIP: For an overview of minting mechanisms check out xref:erc20-supply.adoc[Creating ERC20 Supply].
+
+Here's what a contract for tokenized items might look like:
+
+[source,solidity]
+----
+// contracts/GameItems.sol
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.6.0;
+
+import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
+
+contract GameItems is ERC1155 {
+    uint256 public constant GOLD = 0;
+    uint256 public constant SILVER = 1;
+    uint256 public constant THORS_HAMMER = 2;
+    uint256 public constant SWORD = 3;
+    uint256 public constant SHIELD = 4;
+
+    constructor() public ERC1155("https://game.example/api/item/{1}.json") {
+        _mint(msg.sender, GOLD, 10**18, "");
+        _mint(msg.sender, SILVER, 10**27, "");
+        _mint(msg.sender, THORS_HAMMER, 1, "");
+        _mint(msg.sender, SWORD, 10**9, "");
+        _mint(msg.sender, SHIELD, 10**9, "");
+    }
+}
+----
+
+Note that for our Game Items, Gold is a fungible token whilst Thor's Hammer is a non-fungible token as we minted only one.
+
+The xref:api:token/ERC1155.adoc#ERC1155[`ERC1155`] contract includes the optional extension xref:api:token/ERC1155.adoc#IERC1155MetadataURI[`IERC1155MetadataURI`]. That's where the xref:api:token/ERC1155.adoc#IERC1155MetadataURI-uri-uint256-[`uri`] function comes from: we use it to retrieve the metadata uri.
+
+Also note that, unlike ERC20, ERC1155 lacks a `decimals` field, since each token is distinct and cannot be partitioned.
+
+Once deployed, we will be able to query the deployer’s balance:
+[source,javascript]
+----
+> gameItems.balanceOf(deployerAddress,3)
+1000000000
+----
+
+We can transfer items to player accounts:
+[source,javascript]
+----
+> gameItems.safeTransferFrom(deployerAddress, playerAddress, 2, 1, "0x0")
+> gameItems.balanceOf(playerAddress, 2)
+1
+> gameItems.balanceOf(deployerAddress, 2)
+0
+----
+
+We can also batch transfer items to player accounts and get the balance of batches:
+[source,javascript]
+----
+> gameItems.safeBatchTransferFrom(deployerAddress, playerAddress, [0,1,3,4], [50,100,1,1], "0x0")
+> gameItems.balanceOfBatch([playerAddress,playerAddress,playerAddress,playerAddress,playerAddress], [0,1,2,3,4])
+[50,100,1,1,1]
+----
+
+The metadata uri can be obtained:
+
+[source,javascript]
+----
+> gameItems.uri(2)
+"https://game.example/api/item/{id}.json"
+----
+
+The `uri` can include the string `{id}` which clients must replace with the actual token ID, in lowercase hexadecimal (with no 0x prefix) and leading zero padded to 64 hex characters.
+
+For token ID `2` and uri `https://game.example/api/item/{id}.json` clients would replace `{id}` with `0000000000000000000000000000000000000000000000000000000000000002` to retrieve JSON at `https://game.example/api/item/0000000000000000000000000000000000000000000000000000000000000002.json`.
+
+The JSON document for token ID 2 might look something like:
+
+[source,json]
+----
+{
+    "name": "Thor's hammer",
+    "description": "Mjölnir, the legendary hammer of the Norse god of thunder.",
+    "image": "https://game.example/item-id-8u5h2m.png",
+    "strength": 20
+}
+----
+
+For more information about the metadata JSON Schema, check out the https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md#erc-1155-metadata-uri-json-schema[ERC-1155 Metadata URI JSON Schema].
+
+NOTE: you'll notice that the item's information is included in the metadata, but that information isn't on-chain! So a game developer could change the underlying metadata, changing the rules of the game!
+
+[[sending-to-contracts]]
+== Sending Tokens to Contracts
+
+A key difference when using xref:api:token/ERC1155.adoc#IERC1155-safeTransferFrom-address-address-uint256-uint256-bytes-[`safeTransferFrom`] is that token transfers to other contracts may revert with the following message:
+
+[source,text]
+----
+ERC1155: transfer to non ERC1155Receiver implementer
+----
+
+This is a good thing! It means that the recipient contract has not registered itself as aware of the ERC1155 protocol, so transfers to it are disabled to *prevent tokens from being locked forever*. As an example, https://etherscan.io/token/0xa74476443119A942dE498590Fe1f2454d7D4aC0d?a=0xa74476443119A942dE498590Fe1f2454d7D4aC0d[the Golem contract currently holds over 350k `GNT` tokens], worth multiple tens of thousands of dollars, and lacks methods to get them out of there. This has happened to virtually every ERC20-backed project, usually due to user error.
+
+In order for our contract to receive ERC1155 tokens we can inherit from the convenience contract xref:api:token/ERC1155.adoc#ERC1155Holder[`ERC1155Holder`] which handles the registering for us.  Though we need to remember to implement functionality to allow tokens to be transferred out of our contract:
+
+[source,solidity]
+----
+// contracts/MyContract.sol
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.6.0;
+
+import "@openzeppelin/contracts/token/ERC1155/ERC1155Holder.sol";
+
+contract MyContract is ERC1155Holder {
+}
+----
+
+We can also implement more complex scenarios using the xref:api:token/ERC1155.adoc#IERC1155Receiver-onERC1155Received-address-address-uint256-uint256-bytes-[`onERC1155Received`] and xref:api:token/ERC1155.adoc#IERC1155Receiver-onERC1155BatchReceived-address-address-uint256---uint256---bytes-[`onERC1155BatchReceived`] functions.
+
+[[Presets]]
+== Preset ERC1155 contract
+A preset ERC1155 is available, xref:api:presets/ERC1155PresetMinterPauser[ERC1155PresetMinterPauser]. It is preset to allow for token minting (create) - including batch minting, stop all token transfers (pause) and allow holders to burn (destroy) their tokens. The contract uses xref:access-control.adoc[Access Control] to control access to the minting and pausing functionality.  The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role.
+
+This contract is ready to deploy without having to write any Solidity code.  It can be used as-is for quick prototyping and testing, but is also suitable for production environments.

+ 1 - 1
docs/modules/ROOT/pages/erc20-supply.adoc

@@ -2,7 +2,7 @@
 
 
 In this guide you will learn how to create an ERC20 token with a custom supply mechanism. We will showcase two idiomatic ways to use OpenZeppelin Contracts for this purpose that you will be able to apply to your smart contract development practice.
 In this guide you will learn how to create an ERC20 token with a custom supply mechanism. We will showcase two idiomatic ways to use OpenZeppelin Contracts for this purpose that you will be able to apply to your smart contract development practice.
 
 
-The standard interface implemented by tokens built on Ethereum is called ERC20, and Contracts includes a widely used implementation of it: the aptly named xref:api:token/ERC20.adoc[`ERC20`] contract. This contract, like the standard itself, is quite simple and bare-bones. In fact, if you try deploy an instance of `ERC20` as-is it will be quite literally useless... it will have no supply! What use is a token with no supply?
+The standard interface implemented by tokens built on Ethereum is called ERC20, and Contracts includes a widely used implementation of it: the aptly named xref:api:token/ERC20.adoc[`ERC20`] contract. This contract, like the standard itself, is quite simple and bare-bones. In fact, if you try to deploy an instance of `ERC20` as-is it will be quite literally useless... it will have no supply! What use is a token with no supply?
 
 
 The way that supply is created is not defined in the ERC20 document. Every token is free to experiment with their own mechanisms, ranging from the most decentralized to the most centralized, from the most naive to the most researched, and more.
 The way that supply is created is not defined in the ERC20 document. Every token is free to experiment with their own mechanisms, ranging from the most decentralized to the most centralized, from the most naive to the most researched, and more.
 
 

+ 13 - 5
docs/modules/ROOT/pages/erc20.adoc

@@ -13,12 +13,14 @@ Here's what our GLD token might look like.
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
+// contracts/GLDToken.sol
+// SPDX-License-Identifier: MIT
 pragma solidity ^0.6.0;
 pragma solidity ^0.6.0;
 
 
 import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
 import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
 
 
 contract GLDToken is ERC20 {
 contract GLDToken is ERC20 {
-    constructor(uint256 initialSupply) ERC20("Gold", "GLD") public {
+    constructor(uint256 initialSupply) public ERC20("Gold", "GLD") {
         _mint(msg.sender, initialSupply);
         _mint(msg.sender, initialSupply);
     }
     }
 }
 }
@@ -33,18 +35,18 @@ That's it! Once deployed, we will be able to query the deployer's balance:
 [source,javascript]
 [source,javascript]
 ----
 ----
 > GLDToken.balanceOf(deployerAddress)
 > GLDToken.balanceOf(deployerAddress)
-1000
+1000000000000000000000
 ----
 ----
 
 
 We can also xref:api:token/ERC20.adoc#IERC20-transfer-address-uint256-[transfer] these tokens to other accounts:
 We can also xref:api:token/ERC20.adoc#IERC20-transfer-address-uint256-[transfer] these tokens to other accounts:
 
 
 [source,javascript]
 [source,javascript]
 ----
 ----
-> GLDToken.transfer(otherAddress, 300)
+> GLDToken.transfer(otherAddress, 300000000000000000000)
 > GLDToken.balanceOf(otherAddress)
 > GLDToken.balanceOf(otherAddress)
-300
+300000000000000000000
 > GLDToken.balanceOf(deployerAddress)
 > GLDToken.balanceOf(deployerAddress)
-700
+700000000000000000000
 ----
 ----
 
 
 [[a-note-on-decimals]]
 [[a-note-on-decimals]]
@@ -67,3 +69,9 @@ So if you want to send `5` tokens using a token contract with 18 decimals, the t
 ```solidity
 ```solidity
 transfer(recipient, 5 * 10^18);
 transfer(recipient, 5 * 10^18);
 ```
 ```
+
+[[Presets]]
+== Preset ERC20 contract
+A preset ERC20 is available, xref:api:presets/ERC20PresetMinterPauser[ERC20PresetMinterPauser]. It is preset to allow for token minting (create), stop all token transfers (pause) and allow holders to burn (destroy) their tokens. The contract uses xref:access-control.adoc[Access Control] to control access to the minting and pausing functionality.  The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role.
+
+This contract is ready to deploy without having to write any Solidity code.  It can be used as-is for quick prototyping and testing, but is also suitable for production environments.

+ 18 - 6
docs/modules/ROOT/pages/erc721.adoc

@@ -2,16 +2,18 @@
 
 
 We've discussed how you can make a _fungible_ token using xref:erc20.adoc[ERC20], but what if not all tokens are alike? This comes up in situations like *real estate* or *collectibles*, where some items are valued more than others, due to their usefulness, rarity, etc. ERC721 is a standard for representing ownership of xref:tokens.adoc#different-kinds-of-tokens[_non-fungible_ tokens], that is, where each token is unique.
 We've discussed how you can make a _fungible_ token using xref:erc20.adoc[ERC20], but what if not all tokens are alike? This comes up in situations like *real estate* or *collectibles*, where some items are valued more than others, due to their usefulness, rarity, etc. ERC721 is a standard for representing ownership of xref:tokens.adoc#different-kinds-of-tokens[_non-fungible_ tokens], that is, where each token is unique.
 
 
-ERC721 is a more complex standard than ERC20, with multiple optional extensions, and is split accross a number of contracts. The OpenZeppelin Contracts provide flexibility regarding how these are combined, along with custom useful extensions. Check out the xref:api:token/ERC721.adoc[API Reference] to learn more about these.
+ERC721 is a more complex standard than ERC20, with multiple optional extensions, and is split across a number of contracts. The OpenZeppelin Contracts provide flexibility regarding how these are combined, along with custom useful extensions. Check out the xref:api:token/ERC721.adoc[API Reference] to learn more about these.
 
 
 == Constructing an ERC721 Token Contract
 == Constructing an ERC721 Token Contract
 
 
-We'll use ERC721 to track items in our game, which will each have their own unique attributes. Whenever one is to be awarded to a player, it will be minted and sent to them. Players are free to keep their token or trade it with other people as they see fit, as they would any other asset on the blockchain!
+We'll use ERC721 to track items in our game, which will each have their own unique attributes. Whenever one is to be awarded to a player, it will be minted and sent to them. Players are free to keep their token or trade it with other people as they see fit, as they would any other asset on the blockchain!  Please note any account can call `awardItem` to mint items.  To restrict what accounts can mint items we can add xref:access-control.adoc[Access Control].
 
 
 Here's what a contract for tokenized items might look like:
 Here's what a contract for tokenized items might look like:
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
+// contracts/GameItem.sol
+// SPDX-License-Identifier: MIT
 pragma solidity ^0.6.0;
 pragma solidity ^0.6.0;
 
 
 import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
 import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
@@ -21,10 +23,12 @@ contract GameItem is ERC721 {
     using Counters for Counters.Counter;
     using Counters for Counters.Counter;
     Counters.Counter private _tokenIds;
     Counters.Counter private _tokenIds;
 
 
-    constructor() ERC721("GameItem", "ITM") public {
-    }
+    constructor() public ERC721("GameItem", "ITM") {}
 
 
-    function awardItem(address player, string memory tokenURI) public returns (uint256) {
+    function awardItem(address player, string memory tokenURI)
+        public
+        returns (uint256)
+    {
         _tokenIds.increment();
         _tokenIds.increment();
 
 
         uint256 newItemId = _tokenIds.current();
         uint256 newItemId = _tokenIds.current();
@@ -45,7 +49,9 @@ New items can be created:
 [source,javascript]
 [source,javascript]
 ----
 ----
 > gameItem.awardItem(playerAddress, "https://game.example/item-id-8u5h2m.json")
 > gameItem.awardItem(playerAddress, "https://game.example/item-id-8u5h2m.json")
-7
+Transaction successful. Transaction hash: 0x...
+Events emitted:
+ - Transfer(0x0000000000000000000000000000000000000000, playerAddress, 7)
 ----
 ----
 
 
 And the owner and metadata of each item queried:
 And the owner and metadata of each item queried:
@@ -73,3 +79,9 @@ This `tokenURI` should resolve to a JSON document that might look something like
 For more information about the `tokenURI` metadata JSON Schema, check out the https://eips.ethereum.org/EIPS/eip-721[ERC721 specification].
 For more information about the `tokenURI` metadata JSON Schema, check out the https://eips.ethereum.org/EIPS/eip-721[ERC721 specification].
 
 
 NOTE: you'll notice that the item's information is included in the metadata, but that information isn't on-chain! So a game developer could change the underlying metadata, changing the rules of the game! If you'd like to put all item information on-chain, you can extend ERC721 to do so (though it will be rather costly). You could also leverage IPFS to store the tokenURI information, but these techniques are out of the scope of this overview guide.
 NOTE: you'll notice that the item's information is included in the metadata, but that information isn't on-chain! So a game developer could change the underlying metadata, changing the rules of the game! If you'd like to put all item information on-chain, you can extend ERC721 to do so (though it will be rather costly). You could also leverage IPFS to store the tokenURI information, but these techniques are out of the scope of this overview guide.
+
+[[Presets]]
+== Preset ERC721 contract
+A preset ERC721 is available, xref:api:presets/ERC721PresetMinterPauserAutoId[ERC721PresetMinterPauserAutoId]. It is preset to allow for token minting (create) with token ID and URI auto generation, stop all token transfers (pause) and allow holders to burn (destroy) their tokens. The contract uses xref:access-control.adoc[Access Control] to control access to the minting and pausing functionality.  The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role.
+
+This contract is ready to deploy without having to write any Solidity code.  It can be used as-is for quick prototyping and testing, but is also suitable for production environments.

+ 4 - 5
docs/modules/ROOT/pages/erc777.adoc

@@ -18,17 +18,16 @@ We will replicate the `GLD` example of the xref:erc20.adoc#constructing-an-erc20
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
+// contracts/GLDToken.sol
+// SPDX-License-Identifier: MIT
 pragma solidity ^0.6.0;
 pragma solidity ^0.6.0;
 
 
 import "@openzeppelin/contracts/token/ERC777/ERC777.sol";
 import "@openzeppelin/contracts/token/ERC777/ERC777.sol";
 
 
 contract GLDToken is ERC777 {
 contract GLDToken is ERC777 {
-    constructor(
-        uint256 initialSupply,
-        address[] memory defaultOperators
-    )
-        ERC777("Gold", "GLD", defaultOperators)
+    constructor(uint256 initialSupply, address[] memory defaultOperators)
         public
         public
+        ERC777("Gold", "GLD", defaultOperators)
     {
     {
         _mint(msg.sender, initialSupply, "", "");
         _mint(msg.sender, initialSupply, "", "");
     }
     }

+ 10 - 2
docs/modules/ROOT/pages/extending-contracts.adoc

@@ -18,6 +18,8 @@ Inheritance is often used to add the parent contract's functionality to your own
 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:
 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
 ```solidity
+// contracts/ModifiedAccessControl.sol
+// SPDX-License-Identifier: MIT
 pragma solidity ^0.6.0;
 pragma solidity ^0.6.0;
 
 
 import "@openzeppelin/contracts/access/AccessControl.sol";
 import "@openzeppelin/contracts/access/AccessControl.sol";
@@ -44,6 +46,8 @@ Here is a modified version of xref:api:access.adoc#AccessControl[`AccessControl`
 
 
 
 
 ```solidity
 ```solidity
+// contracts/ModifiedAccessControl.sol
+// SPDX-License-Identifier: MIT
 pragma solidity ^0.6.0;
 pragma solidity ^0.6.0;
 
 
 import "@openzeppelin/contracts/access/AccessControl.sol";
 import "@openzeppelin/contracts/access/AccessControl.sol";
@@ -62,7 +66,7 @@ contract ModifiedAccessControl is AccessControl {
 
 
 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.
 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!
+NOTE: As of v3.0.0, `view` functions are not `virtual` in OpenZeppelin, and therefore cannot be overridden. 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]]
 == Using Hooks
 == Using Hooks
@@ -92,6 +96,9 @@ contract ERC20WithSafeTransfer is ERC20 {
     function _validRecipient(address to) private view returns (bool) {
     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.
 Using hooks this way leads to cleaner and safer code, without having to rely on a deep understanding of the parent's internals.
@@ -100,7 +107,7 @@ Using hooks this way leads to cleaner and safer code, without having to rely on
 ====
 ====
 Hooks are a new feature of OpenZeppelin Contracts v3.0.0, and we're eager to learn how you plan to use them!
 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!
+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`], xref:api:token/ERC777.adoc#ERC777-_beforeTokenTransfer-address-address-address-uint256-[`ERC777`] and xref:api:token/ERC1155.adoc#ERC1155-_beforeTokenTransfer-address-address-address-uint256---uint256---bytes-[`ERC1155`]. If you have ideas for new hooks, let us know!
 ====
 ====
 
 
 === Rules of Hooks
 === Rules of Hooks
@@ -121,3 +128,4 @@ contract MyToken is ERC20 {
 }
 }
 ```
 ```
 That's it! Enjoy simpler code using hooks!
 That's it! Enjoy simpler code using hooks!
+

+ 5 - 1
docs/modules/ROOT/pages/gsn-strategies.adoc

@@ -47,7 +47,7 @@ On the other hand, you need to have a backend server, microservice, or lambda fu
 
 
 `GSNRecipientSignature` decides whether or not to accept the relayed call based on the included signature.
 `GSNRecipientSignature` decides whether or not to accept the relayed call based on the included signature.
 
 
-The `acceptRelayedCall` implementation recovers the address from the signature of the relayed call parameters in `approvalData` and compares to the trusted signer.
+The `acceptRelayedCall` implementation recovers the address from the signature of the relayed call parameters in `approvalData` and compares it to the trusted signer.
 If the included signature matches the trusted signer, the relayed call is approved.
 If the included signature matches the trusted signer, the relayed call is approved.
 On the other hand, when the included signature doesn't match the trusted signer, the relayed call gets rejected with an error code of `INVALID_SIGNER`.
 On the other hand, when the included signature doesn't match the trusted signer, the relayed call gets rejected with an error code of `INVALID_SIGNER`.
 
 
@@ -106,6 +106,10 @@ Your GSN recipient contract needs to inherit from `GSNRecipientERC20Fee` along w
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
+// contracts/MyContract.sol
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.6.0;
+
 import "@openzeppelin/contracts/GSN/GSNRecipientERC20Fee.sol";
 import "@openzeppelin/contracts/GSN/GSNRecipientERC20Fee.sol";
 import "@openzeppelin/contracts/access/AccessControl.sol";
 import "@openzeppelin/contracts/access/AccessControl.sol";
 
 

+ 19 - 19
docs/modules/ROOT/pages/gsn.adoc

@@ -34,17 +34,17 @@ First, RelayHub will ask your recipient contract if it wants to receive a relaye
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
-function acceptRelayedCall(
-  address relay,
-  address from,
-  bytes calldata encodedFunction,
-  uint256 transactionFee,
-  uint256 gasPrice,
-  uint256 gasLimit,
-  uint256 nonce,
-  bytes calldata approvalData,
-  uint256 maxPossibleCharge
-) external view returns (uint256, bytes memory);
+    function acceptRelayedCall(
+        address relay,
+        address from,
+        bytes calldata encodedFunction,
+        uint256 transactionFee,
+        uint256 gasPrice,
+        uint256 gasLimit,
+        uint256 nonce,
+        bytes calldata approvalData,
+        uint256 maxPossibleCharge
+    ) external view returns (uint256, bytes memory);
 ----
 ----
 
 
 There are multiple ways to make this work, including:
 There are multiple ways to make this work, including:
@@ -60,7 +60,7 @@ In this function, you return a number indicating whether you accept the call (0)
 
 
 === pre and postRelayedCall
 === pre and postRelayedCall
 
 
-After a relayed call is accepted, RelayHub will give your contract two opportunities to charge your user for their call, perform some bookeeping, etc.: _before_ and _after_ the actual relayed call is made. These functions are aptly named `preRelayedCall` and `postRelayedCall`.
+After a relayed call is accepted, RelayHub will give your contract two opportunities to charge your user for their call, perform some bookkeeping, etc.: _before_ and _after_ the actual relayed call is made. These functions are aptly named `preRelayedCall` and `postRelayedCall`.
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
@@ -72,13 +72,12 @@ function preRelayedCall(bytes calldata context) external returns (bytes32);
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
-
-function postRelayedCall(
-  bytes calldata context,
-  bool success,
-  uint actualCharge,
-  bytes32 preRetVal
-) external;
+    function postRelayedCall(
+        bytes calldata context,
+        bool success,
+        uint256 actualCharge,
+        bytes32 preRetVal
+    ) external;
 ----
 ----
 
 
 `postRelayedCall` will give you an accurate estimate of the transaction cost, making it a natural place to charge users. It will also let you know if the relayed call reverted or not. This allows you, for instance, to not charge users for reverted calls - but remember that you will be charged by the relayer nonetheless.
 `postRelayedCall` will give you an accurate estimate of the transaction cost, making it a natural place to charge users. It will also let you know if the relayed call reverted or not. This allows you, for instance, to not charge users for reverted calls - but remember that you will be charged by the relayer nonetheless.
@@ -88,3 +87,4 @@ These functions allow you to implement, for instance, a flow where you charge yo
 == Further reading
 == Further reading
 
 
 Read our xref:gsn-strategies.adoc[guide on the payment strategies] pre-built and shipped in OpenZeppelin Contracts, or check out xref:api:GSN.adoc[the API reference of the GSN base contracts].
 Read our xref:gsn-strategies.adoc[guide on the payment strategies] pre-built and shipped in OpenZeppelin Contracts, or check out xref:api:GSN.adoc[the API reference of the GSN base contracts].
+

+ 4 - 1
docs/modules/ROOT/pages/index.adoc

@@ -26,6 +26,8 @@ Once installed, you can use the contracts in the library by importing them:
 
 
 [source,solidity]
 [source,solidity]
 ----
 ----
+// contracts/MyNFT.sol
+// SPDX-License-Identifier: MIT
 pragma solidity ^0.6.0;
 pragma solidity ^0.6.0;
 
 
 import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
 import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
@@ -46,7 +48,7 @@ To keep your system secure, you should **always** use the installed code as-is,
 The guides in the sidebar will teach about different concepts, and how to use the related contracts that OpenZeppelin Contracts provides:
 The guides in the sidebar will teach about different concepts, and how to use the related contracts that OpenZeppelin Contracts provides:
 
 
 * xref:access-control.adoc[Access Control]: decide who can perform each of the actions on your system.
 * xref:access-control.adoc[Access Control]: decide who can perform each of the actions on your system.
-* xref:tokens.adoc[Tokens]: create tradeable assets or collectibles, like the well known xref:erc20.adoc[ERC20] and xref:erc721.adoc[ERC721] standards.
+* xref:tokens.adoc[Tokens]: create tradable assets or collectibles, like the well known xref:erc20.adoc[ERC20] and xref:erc721.adoc[ERC721] standards.
 * xref:gsn.adoc[Gas Station Network]: let your users interact with your contracts without having to pay for gas themselves.
 * xref:gsn.adoc[Gas Station Network]: let your users interact with your contracts without having to pay for gas themselves.
 * xref:utilities.adoc[Utilities]: generic useful tools, including non-overflowing math, signature verification, and trustless paying systems.
 * xref:utilities.adoc[Utilities]: generic useful tools, including non-overflowing math, signature verification, and trustless paying systems.
 
 
@@ -57,3 +59,4 @@ Finally, you may want to take a look at the https://blog.openzeppelin.com/guides
 * https://blog.openzeppelin.com/the-hitchhikers-guide-to-smart-contracts-in-ethereum-848f08001f05[The Hitchhiker’s Guide to Smart Contracts in Ethereum] will help you get an overview of the various tools available for smart contract development, and help you set up your environment.
 * https://blog.openzeppelin.com/the-hitchhikers-guide-to-smart-contracts-in-ethereum-848f08001f05[The Hitchhiker’s Guide to Smart Contracts in Ethereum] will help you get an overview of the various tools available for smart contract development, and help you set up your environment.
 * https://blog.openzeppelin.com/a-gentle-introduction-to-ethereum-programming-part-1-783cc7796094[A Gentle Introduction to Ethereum Programming, Part 1] provides very useful information on an introductory level, including many basic concepts from the Ethereum platform.
 * https://blog.openzeppelin.com/a-gentle-introduction-to-ethereum-programming-part-1-783cc7796094[A Gentle Introduction to Ethereum Programming, Part 1] provides very useful information on an introductory level, including many basic concepts from the Ethereum platform.
 * For a more in-depth dive, you may read the guide https://blog.openzeppelin.com/designing-the-architecture-for-your-ethereum-application-9cec086f8317[Designing the architecture for your Ethereum application], which discusses how to better structure your application and its relationship to the real world.
 * For a more in-depth dive, you may read the guide https://blog.openzeppelin.com/designing-the-architecture-for-your-ethereum-application-9cec086f8317[Designing the architecture for your Ethereum application], which discusses how to better structure your application and its relationship to the real world.
+

+ 4 - 3
docs/modules/ROOT/pages/releases-stability.adoc

@@ -1,6 +1,6 @@
 = New Releases and API Stability
 = New Releases and API Stability
 
 
-Developing smart contracts is hard, and a conservative approach towards dependencies is sometimes favored. However, it is also very important to stay on top of new releases: these may include bugfixes, or deprecate old patterns in favor of newer and better practices.
+Developing smart contracts is hard, and a conservative approach towards dependencies is sometimes favored. However, it is also very important to stay on top of new releases: these may include bug fixes, or deprecate old patterns in favor of newer and better practices.
 
 
 Here we describe when you should expect new releases to come out, and how this affects you as a user of OpenZeppelin Contracts.
 Here we describe when you should expect new releases to come out, and how this affects you as a user of OpenZeppelin Contracts.
 
 
@@ -67,7 +67,7 @@ No events will be removed, and their arguments won't be changed in any way. New
 While attempts will generally be made to lower the gas costs of working with OpenZeppelin Contracts, there are no guarantees regarding this. In particular, users should not assume gas costs will not increase when upgrading library versions.
 While attempts will generally be made to lower the gas costs of working with OpenZeppelin Contracts, there are no guarantees regarding this. In particular, users should not assume gas costs will not increase when upgrading library versions.
 
 
 [[bugfixes]]
 [[bugfixes]]
-=== Bugfixes
+=== Bug Fixes
 
 
 The API stability guarantees may need to be broken in order to fix a bug, and we will do so. This decision won't be made lightly however, and all options will be explored to make the change as non-disruptive as possible. When sufficient, contracts or functions which may result in unsafe behaviour will be deprecated instead of removed (e.g. https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1543[#1543] and https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1550[#1550]).
 The API stability guarantees may need to be broken in order to fix a bug, and we will do so. This decision won't be made lightly however, and all options will be explored to make the change as non-disruptive as possible. When sufficient, contracts or functions which may result in unsafe behaviour will be deprecated instead of removed (e.g. https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1543[#1543] and https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1550[#1550]).
 
 
@@ -76,6 +76,7 @@ The API stability guarantees may need to be broken in order to fix a bug, and we
 
 
 Starting on version 0.5.0, the Solidity team switched to a faster release cycle, with minor releases every few weeks (v0.5.0 was released on November 2018, and v0.5.5 on March 2019), and major, breaking-change releases every couple months (with v0.6.0 scheduled for late March 2019). Including the compiler version in OpenZeppelin Contract's stability guarantees would therefore force the library to either stick to old compilers, or release frequent major updates simply to keep up with newer Solidity releases.
 Starting on version 0.5.0, the Solidity team switched to a faster release cycle, with minor releases every few weeks (v0.5.0 was released on November 2018, and v0.5.5 on March 2019), and major, breaking-change releases every couple months (with v0.6.0 scheduled for late March 2019). Including the compiler version in OpenZeppelin Contract's stability guarantees would therefore force the library to either stick to old compilers, or release frequent major updates simply to keep up with newer Solidity releases.
 
 
-Because of this, *the minimum required Solidity compiler version is not part of the stability guarantees*, and users may be required to upgrade their compiler when using newer versions of Contracts. Bugfixes will still be backported to older library releases so that all versions currently in use receive these updates.
+Because of this, *the minimum required Solidity compiler version is not part of the stability guarantees*, and users may be required to upgrade their compiler when using newer versions of Contracts. Bug fixes will still be backported to older library releases so that all versions currently in use receive these updates.
 
 
 You can read more about the rationale behind this, the other options we considered and why we went down this path https://github.com/OpenZeppelin/openzeppelin-contracts/issues/1498#issuecomment-449191611[here].
 You can read more about the rationale behind this, the other options we considered and why we went down this path https://github.com/OpenZeppelin/openzeppelin-contracts/issues/1498#issuecomment-449191611[here].
+

+ 4 - 3
docs/modules/ROOT/pages/utilities.adoc

@@ -1,13 +1,13 @@
 = Utilities
 = Utilities
 
 
-The OpenZeppelin Contracs provide a ton of useful utilities that you can use in your project. Here are some of the more popular ones.
+The OpenZeppelin Contracts provide a ton of useful utilities that you can use in your project. Here are some of the more popular ones.
 
 
 [[cryptography]]
 [[cryptography]]
 == Cryptography
 == Cryptography
 
 
 === Checking Signatures On-Chain
 === Checking Signatures On-Chain
 
 
-xref:api:cryptography.adoc#ECDSA[`ECDSA`] provides functions for recovering and managing Ethereum account ECDSA signatures. These are often generated via https://web3js.readthedocs.io/en/v1.2.4/web3-eth.html#sign[`web3.eth.sign`], and are a 65 byte array (of type `bytes` in Solidity) arranged the follwing way: `[[v (1)], [r (32)], [s (32)]]`.
+xref:api:cryptography.adoc#ECDSA[`ECDSA`] provides functions for recovering and managing Ethereum account ECDSA signatures. These are often generated via https://web3js.readthedocs.io/en/v1.2.4/web3-eth.html#sign[`web3.eth.sign`], and are a 65 byte array (of type `bytes` in Solidity) arranged the following way: `[[v (1)], [r (32)], [s (32)]]`.
 
 
 The data signer can be recovered with xref:api:cryptography.adoc#ECDSA-recover-bytes32-bytes-[`ECDSA.recover`], and its address compared to verify the signature. Most wallets will hash the data to sign and add the prefix '\x19Ethereum Signed Message:\n', so when attempting to recover the signer of an Ethereum signed message hash, you'll want to use xref:api:cryptography.adoc#ECDSA-toEthSignedMessageHash-bytes32-[`toEthSignedMessageHash`].
 The data signer can be recovered with xref:api:cryptography.adoc#ECDSA-recover-bytes32-bytes-[`ECDSA.recover`], and its address compared to verify the signature. Most wallets will hash the data to sign and add the prefix '\x19Ethereum Signed Message:\n', so when attempting to recover the signer of an Ethereum signed message hash, you'll want to use xref:api:cryptography.adoc#ECDSA-toEthSignedMessageHash-bytes32-[`toEthSignedMessageHash`].
 
 
@@ -90,7 +90,7 @@ If you want to Escrow some funds, check out xref:api:payment.adoc#Escrow[`Escrow
 [[collections]]
 [[collections]]
 == Collections
 == Collections
 
 
-If you need support for more powerful collections than Solidity's native arrays and mappings, take a look at xref:api:utils.adoc#EnumerableSet[`EnumerableSet`] and xref:api:utils.adoc#EnumerableMap[`EnumerableMap`]. They are similar to mappings in that they store and remove elements in constant time and don't allow for repeated entries, but they also supports _enumeration_, which means you can easily query all stored entries both on and off-chain.
+If you need support for more powerful collections than Solidity's native arrays and mappings, take a look at xref:api:utils.adoc#EnumerableSet[`EnumerableSet`] and xref:api:utils.adoc#EnumerableMap[`EnumerableMap`]. They are similar to mappings in that they store and remove elements in constant time and don't allow for repeated entries, but they also support _enumeration_, which means you can easily query all stored entries both on and off-chain.
 
 
 [[misc]]
 [[misc]]
 == Misc
 == Misc
@@ -98,3 +98,4 @@ If you need support for more powerful collections than Solidity's native arrays
 Want to check if an address is a contract? Use xref:api:utils.adoc#Address[`Address`] and xref:api:utils.adoc#Address-isContract-address-[`Address.isContract()`].
 Want to check if an address is a contract? Use xref:api:utils.adoc#Address[`Address`] and xref:api:utils.adoc#Address-isContract-address-[`Address.isContract()`].
 
 
 Want to keep track of some numbers that increment by 1 every time you want another one? Check out xref:api:utils.adoc#Counters[`Counters`]. This is useful for lots of things, like creating incremental identifiers, as shown on the xref:erc721.adoc[ERC721 guide].
 Want to keep track of some numbers that increment by 1 every time you want another one? Check out xref:api:utils.adoc#Counters[`Counters`]. This is useful for lots of things, like creating incremental identifiers, as shown on the xref:erc721.adoc[ERC721 guide].
+