0
# Token Standards
1
2
OpenZeppelin provides comprehensive implementations of Ethereum token standards including ERC20 (fungible tokens), ERC721 (non-fungible tokens), ERC777 (advanced fungible tokens), and ERC1155 (multi-token standard). Each implementation includes core functionality and optional extensions.
3
4
## Capabilities
5
6
### ERC20 - Fungible Token Standard
7
8
Standard fungible token implementation with optional extensions for burning, capping, pausing, and snapshots.
9
10
```solidity { .api }
11
/**
12
* Interface of the ERC20 standard as defined in the EIP
13
*/
14
interface IERC20 {
15
/**
16
* Returns the amount of tokens in existence
17
*/
18
function totalSupply() external view returns (uint256);
19
20
/**
21
* Returns the amount of tokens owned by account
22
*/
23
function balanceOf(address account) external view returns (uint256);
24
25
/**
26
* Moves amount tokens from the caller's account to recipient
27
* Returns a boolean value indicating whether the operation succeeded
28
* Emits a Transfer event
29
*/
30
function transfer(address recipient, uint256 amount) external returns (bool);
31
32
/**
33
* Returns the remaining number of tokens that spender will be allowed to spend on behalf of owner
34
*/
35
function allowance(address owner, address spender) external view returns (uint256);
36
37
/**
38
* Sets amount as the allowance of spender over the caller's tokens
39
* Returns a boolean value indicating whether the operation succeeded
40
* Emits an Approval event
41
*/
42
function approve(address spender, uint256 amount) external returns (bool);
43
44
/**
45
* Moves amount tokens from sender to recipient using the allowance mechanism
46
* amount is then deducted from the caller's allowance
47
* Returns a boolean value indicating whether the operation succeeded
48
* Emits a Transfer event
49
*/
50
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
51
52
/**
53
* Emitted when value tokens are moved from one account (from) to another (to)
54
* Note that value may be zero
55
*/
56
event Transfer(address indexed from, address indexed to, uint256 value);
57
58
/**
59
* Emitted when the allowance of a spender for an owner is set by a call to approve
60
* value is the new allowance
61
*/
62
event Approval(address indexed owner, address indexed spender, uint256 value);
63
}
64
65
/**
66
* Implementation of the IERC20 interface with additional metadata extension
67
*/
68
contract ERC20 is Context, IERC20, IERC20Metadata {
69
/**
70
* Returns the name of the token
71
*/
72
function name() public view virtual override returns (string memory);
73
74
/**
75
* Returns the symbol of the token
76
*/
77
function symbol() public view virtual override returns (string memory);
78
79
/**
80
* Returns the number of decimals used to get its user representation
81
* For example, if decimals equals 2, a balance of 505 tokens should be displayed as 5.05
82
*/
83
function decimals() public view virtual override returns (uint8);
84
}
85
```
86
87
**Usage Example:**
88
89
```solidity
90
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
91
92
contract MyToken is ERC20 {
93
constructor() ERC20("MyToken", "MTK") {
94
_mint(msg.sender, 1000000 * 10**decimals());
95
}
96
}
97
```
98
99
### ERC20 Extensions
100
101
Extensions that add functionality to the base ERC20 implementation.
102
103
```solidity { .api }
104
/**
105
* Extension of ERC20 that allows token holders to destroy both their own tokens and those that they have been approved to use
106
*/
107
abstract contract ERC20Burnable is Context, ERC20 {
108
/**
109
* Destroys amount tokens from the caller
110
*/
111
function burn(uint256 amount) public virtual;
112
113
/**
114
* Destroys amount tokens from account, deducting from the caller's allowance
115
*/
116
function burnFrom(address account, uint256 amount) public virtual;
117
}
118
119
/**
120
* Extension of ERC20 that adds a cap to the supply of tokens
121
*/
122
abstract contract ERC20Capped is ERC20 {
123
/**
124
* Returns the cap on the token's total supply
125
*/
126
function cap() public view virtual returns (uint256);
127
}
128
129
/**
130
* ERC20 token with pausable token transfers, minting and burning
131
*/
132
abstract contract ERC20Pausable is ERC20, Pausable {
133
// All transfers, mints, and burns are paused when contract is paused
134
}
135
136
/**
137
* ERC20 token with snapshots
138
*/
139
abstract contract ERC20Snapshot is ERC20 {
140
/**
141
* Retrieves the balance of account at the time snapshotId was created
142
*/
143
function balanceOfAt(address account, uint256 snapshotId) public view virtual returns (uint256);
144
145
/**
146
* Retrieves the total supply at the time snapshotId was created
147
*/
148
function totalSupplyAt(uint256 snapshotId) public view virtual returns (uint256);
149
}
150
```
151
152
### SafeERC20
153
154
Wrapper around ERC20 operations that throw on failure for tokens that return false on failure.
155
156
```solidity { .api }
157
/**
158
* Wrappers around ERC20 operations that throw on failure
159
*/
160
library SafeERC20 {
161
using Address for address;
162
163
function safeTransfer(IERC20 token, address to, uint256 value) internal;
164
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal;
165
function safeApprove(IERC20 token, address spender, uint256 value) internal;
166
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal;
167
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal;
168
}
169
```
170
171
### ERC721 - Non-Fungible Token Standard
172
173
Standard non-fungible token implementation with metadata and enumerable extensions.
174
175
```solidity { .api }
176
/**
177
* Required interface of an ERC721 compliant contract
178
*/
179
interface IERC721 {
180
/**
181
* Returns the number of tokens in owner's account
182
*/
183
function balanceOf(address owner) external view returns (uint256 balance);
184
185
/**
186
* Returns the owner of the tokenId token
187
*/
188
function ownerOf(uint256 tokenId) external view returns (address owner);
189
190
/**
191
* Safely transfers tokenId token from from to to
192
*/
193
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
194
function safeTransferFrom(address from, address to, uint256 tokenId) external;
195
196
/**
197
* Transfers tokenId token from from to to
198
*/
199
function transferFrom(address from, address to, uint256 tokenId) external;
200
201
/**
202
* Gives permission to to to transfer tokenId token to another account
203
*/
204
function approve(address to, uint256 tokenId) external;
205
206
/**
207
* Returns the account approved for tokenId token
208
*/
209
function getApproved(uint256 tokenId) external view returns (address operator);
210
211
/**
212
* Approve or remove operator as an operator for the caller
213
*/
214
function setApprovalForAll(address operator, bool _approved) external;
215
216
/**
217
* Returns if the operator is allowed to manage all of the assets of owner
218
*/
219
function isApprovedForAll(address owner, address operator) external view returns (bool);
220
221
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
222
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
223
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
224
}
225
226
/**
227
* Implementation of ERC721 Non-Fungible Token Standard, including the Metadata extension
228
*/
229
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
230
/**
231
* Returns the token collection name
232
*/
233
function name() public view virtual override returns (string memory);
234
235
/**
236
* Returns the token collection symbol
237
*/
238
function symbol() public view virtual override returns (string memory);
239
240
/**
241
* Returns the Uniform Resource Identifier (URI) for tokenId token
242
*/
243
function tokenURI(uint256 tokenId) public view virtual override returns (string memory);
244
}
245
```
246
247
### ERC777 - Advanced Token Standard
248
249
Advanced fungible token standard with operator permissions and hooks.
250
251
```solidity { .api }
252
/**
253
* Interface of the ERC777Token standard as defined in the EIP
254
*/
255
interface IERC777 {
256
/**
257
* Returns the name of the token
258
*/
259
function name() external view returns (string memory);
260
261
/**
262
* Returns the symbol of the token
263
*/
264
function symbol() external view returns (string memory);
265
266
/**
267
* Returns the smallest part of the token that is not divisible
268
*/
269
function granularity() external view returns (uint256);
270
271
/**
272
* Returns the amount of tokens in existence
273
*/
274
function totalSupply() external view returns (uint256);
275
276
/**
277
* Returns the amount of tokens owned by an account
278
*/
279
function balanceOf(address owner) external view returns (uint256);
280
281
/**
282
* Moves amount of tokens from the caller's account to recipient
283
*/
284
function send(address recipient, uint256 amount, bytes calldata data) external;
285
286
/**
287
* Destroys amount tokens from the caller's account
288
*/
289
function burn(uint256 amount, bytes calldata data) external;
290
291
/**
292
* Returns true if an account is an operator of tokenHolder
293
*/
294
function isOperatorFor(address operator, address tokenHolder) external view returns (bool);
295
296
/**
297
* Make an account an operator of the caller
298
*/
299
function authorizeOperator(address operator) external;
300
301
/**
302
* Revoke an account's operator status for the caller
303
*/
304
function revokeOperator(address operator) external;
305
306
/**
307
* Returns the list of default operators
308
*/
309
function defaultOperators() external view returns (address[] memory);
310
311
/**
312
* Moves amount tokens from holder to recipient
313
*/
314
function operatorSend(address sender, address recipient, uint256 amount, bytes calldata data, bytes calldata operatorData) external;
315
316
/**
317
* Destroys amount tokens from account
318
*/
319
function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData) external;
320
321
event Sent(address indexed operator, address indexed from, address indexed to, uint256 amount, bytes data, bytes operatorData);
322
event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
323
event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
324
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
325
event RevokedOperator(address indexed operator, address indexed tokenHolder);
326
}
327
```
328
329
### ERC1155 - Multi Token Standard
330
331
Standard for contracts that manage multiple token types including both fungible and non-fungible tokens.
332
333
```solidity { .api }
334
/**
335
* Required interface of an ERC1155 compliant contract
336
*/
337
interface IERC1155 {
338
/**
339
* Transfers amount tokens of token type id from from to to
340
*/
341
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
342
343
/**
344
* Batched version of safeTransferFrom
345
*/
346
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
347
348
/**
349
* Returns the amount of tokens of token type id owned by account
350
*/
351
function balanceOf(address account, uint256 id) external view returns (uint256);
352
353
/**
354
* Batched version of balanceOf
355
*/
356
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
357
358
/**
359
* Grants or revokes permission to operator to transfer the caller's tokens
360
*/
361
function setApprovalForAll(address operator, bool approved) external;
362
363
/**
364
* Returns true if operator is approved to transfer account's tokens
365
*/
366
function isApprovedForAll(address account, address operator) external view returns (bool);
367
368
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
369
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
370
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
371
event URI(string value, uint256 indexed id);
372
}
373
```
374
375
## Usage Patterns
376
377
### Creating a Basic ERC20 Token
378
379
```solidity
380
pragma solidity ^0.8.0;
381
382
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
383
import "@openzeppelin/contracts/access/Ownable.sol";
384
385
contract MyToken is ERC20, Ownable {
386
constructor() ERC20("MyToken", "MTK") {
387
_mint(msg.sender, 1000000 * 10**decimals());
388
}
389
390
function mint(address to, uint256 amount) public onlyOwner {
391
_mint(to, amount);
392
}
393
}
394
```
395
396
### Creating an ERC721 NFT
397
398
```solidity
399
pragma solidity ^0.8.0;
400
401
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
402
import "@openzeppelin/contracts/utils/Counters.sol";
403
import "@openzeppelin/contracts/access/Ownable.sol";
404
405
contract MyNFT is ERC721, Ownable {
406
using Counters for Counters.Counter;
407
Counters.Counter private _tokenIds;
408
409
constructor() ERC721("MyNFT", "MNFT") {}
410
411
function mintNFT(address recipient, string memory tokenURI) public onlyOwner returns (uint256) {
412
_tokenIds.increment();
413
uint256 newItemId = _tokenIds.current();
414
_mint(recipient, newItemId);
415
_setTokenURI(newItemId, tokenURI);
416
return newItemId;
417
}
418
}
419
```
420
421
### Safe Token Transfers
422
423
```solidity
424
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
425
426
contract MyContract {
427
using SafeERC20 for IERC20;
428
429
function transferTokens(IERC20 token, address to, uint256 amount) external {
430
token.safeTransfer(to, amount);
431
}
432
}
433
```