0
# Token Standards
1
2
Comprehensive implementations of Ethereum token standards including ERC20 (fungible tokens), ERC721 (NFTs), and ERC1155 (multi-tokens) with extensive extensions and utilities.
3
4
## Capabilities
5
6
### ERC20 Fungible Tokens
7
8
Implementation of the ERC20 standard for fungible tokens with full compliance and security features.
9
10
```solidity { .api }
11
/**
12
* @dev Implementation of the {IERC20} interface.
13
* Abstract contract requiring supply mechanism in derived contracts.
14
*/
15
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
16
/**
17
* @dev Sets the values for {name} and {symbol}
18
* Both values are immutable: they can only be set once during construction
19
*/
20
constructor(string memory name_, string memory symbol_);
21
22
/**
23
* @dev Returns the name of the token
24
*/
25
function name() public view virtual returns (string memory);
26
27
/**
28
* @dev Returns the symbol of the token
29
*/
30
function symbol() public view virtual returns (string memory);
31
32
/**
33
* @dev Returns the number of decimals used to get its user representation
34
*/
35
function decimals() public view virtual returns (uint8);
36
37
/**
38
* @dev Returns the value of tokens in existence
39
*/
40
function totalSupply() public view virtual returns (uint256);
41
42
/**
43
* @dev Returns the value of tokens owned by `account`
44
*/
45
function balanceOf(address account) public view virtual returns (uint256);
46
47
/**
48
* @dev Moves a `value` amount of tokens from the caller's account to `to`
49
*/
50
function transfer(address to, uint256 value) public virtual returns (bool);
51
52
/**
53
* @dev Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner`
54
*/
55
function allowance(address owner, address spender) public view virtual returns (uint256);
56
57
/**
58
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the caller's tokens
59
*/
60
function approve(address spender, uint256 value) public virtual returns (bool);
61
62
/**
63
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
64
*/
65
function transferFrom(address from, address to, uint256 value) public virtual returns (bool);
66
67
/**
68
* @dev Creates a `value` amount of tokens and assigns them to `account`
69
* Internal function that can be called by derived contracts
70
*/
71
function _mint(address account, uint256 value) internal;
72
73
/**
74
* @dev Destroys a `value` amount of tokens from `account`
75
* Internal function that can be called by derived contracts
76
*/
77
function _burn(address account, uint256 value) internal;
78
79
/**
80
* @dev Sets `value` as the allowance of `spender` over `owner`'s tokens
81
* Internal function that can be called by derived contracts
82
*/
83
function _approve(address owner, address spender, uint256 value) internal;
84
}
85
```
86
87
**Usage Example:**
88
89
```solidity
90
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
91
import "@openzeppelin/contracts/access/Ownable.sol";
92
93
contract MyToken is ERC20, Ownable {
94
constructor(address initialOwner)
95
ERC20("MyToken", "MTK")
96
Ownable(initialOwner)
97
{}
98
99
function mint(address to, uint256 amount) public onlyOwner {
100
_mint(to, amount);
101
}
102
103
function burn(uint256 amount) public {
104
_burn(msg.sender, amount);
105
}
106
}
107
```
108
109
### ERC20 Extensions
110
111
Extended functionality for ERC20 tokens including permits, pausability, burning, and more.
112
113
```solidity { .api }
114
// ERC20 Permit - Gasless approvals via signatures
115
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {
116
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual;
117
function nonces(address owner) public view virtual returns (uint256);
118
function DOMAIN_SEPARATOR() external view virtual returns (bytes32);
119
}
120
121
// ERC20 Pausable - Emergency pause functionality
122
abstract contract ERC20Pausable is ERC20, Pausable {
123
function _update(address from, address to, uint256 value) internal virtual override whenNotPaused;
124
}
125
126
// ERC20 Burnable - Token burning functionality
127
abstract contract ERC20Burnable is Context, ERC20 {
128
function burn(uint256 value) public virtual;
129
function burnFrom(address account, uint256 value) public virtual;
130
}
131
132
// ERC20 Capped - Supply cap functionality
133
abstract contract ERC20Capped is ERC20 {
134
constructor(uint256 cap_);
135
function cap() public view virtual returns (uint256);
136
function _update(address from, address to, uint256 value) internal virtual override;
137
}
138
139
// ERC20 FlashMint - Flash loan functionality
140
abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
141
function maxFlashLoan(address token) public view virtual returns (uint256);
142
function flashFee(address token, uint256 value) public view virtual returns (uint256);
143
function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 value, bytes calldata data) public virtual returns (bool);
144
}
145
146
// ERC20 Votes - Voting weight tracking for governance
147
abstract contract ERC20Votes is ERC20, Votes {
148
function _update(address from, address to, uint256 value) internal virtual override;
149
function getVotes(address account) public view virtual returns (uint256);
150
function getPastVotes(address account, uint256 timepoint) public view virtual returns (uint256);
151
}
152
153
// ERC4626 Tokenized Vaults - Vault standard for yield-bearing tokens
154
abstract contract ERC4626 is ERC20, IERC4626 {
155
constructor(IERC20 asset_, string memory name_, string memory symbol_);
156
function asset() public view virtual returns (address);
157
function totalAssets() public view virtual returns (uint256);
158
function convertToShares(uint256 assets) public view virtual returns (uint256);
159
function convertToAssets(uint256 shares) public view virtual returns (uint256);
160
function maxDeposit(address) public view virtual returns (uint256);
161
function maxMint(address) public view virtual returns (uint256);
162
function maxWithdraw(address owner) public view virtual returns (uint256);
163
function maxRedeem(address owner) public view virtual returns (uint256);
164
function previewDeposit(uint256 assets) public view virtual returns (uint256);
165
function previewMint(uint256 shares) public view virtual returns (uint256);
166
function previewWithdraw(uint256 assets) public view virtual returns (uint256);
167
function previewRedeem(uint256 shares) public view virtual returns (uint256);
168
function deposit(uint256 assets, address receiver) public virtual returns (uint256);
169
function mint(uint256 shares, address receiver) public virtual returns (uint256);
170
function withdraw(uint256 assets, address receiver, address owner) public virtual returns (uint256);
171
function redeem(uint256 shares, address receiver, address owner) public virtual returns (uint256);
172
}
173
174
// ERC1363 Payable Token - Callbacks after transfers and approvals
175
abstract contract ERC1363 is ERC20, ERC165, IERC1363 {
176
function transferAndCall(address to, uint256 value) public returns (bool);
177
function transferAndCall(address to, uint256 value, bytes memory data) public virtual returns (bool);
178
function transferFromAndCall(address from, address to, uint256 value) public returns (bool);
179
function transferFromAndCall(address from, address to, uint256 value, bytes memory data) public virtual returns (bool);
180
function approveAndCall(address spender, uint256 value) public returns (bool);
181
function approveAndCall(address spender, uint256 value, bytes memory data) public virtual returns (bool);
182
}
183
184
// ERC20Wrapper - Wrap existing ERC20 tokens
185
abstract contract ERC20Wrapper is ERC20 {
186
constructor(IERC20 underlyingToken, string memory name_, string memory symbol_);
187
function underlying() public view returns (IERC20);
188
function depositFor(address account, uint256 value) public virtual returns (bool);
189
function withdrawTo(address account, uint256 value) public virtual returns (bool);
190
function recover(address account) public virtual returns (uint256);
191
}
192
```
193
194
### ERC721 Non-Fungible Tokens
195
196
Implementation of the ERC721 standard for non-fungible tokens (NFTs) with metadata support.
197
198
```solidity { .api }
199
/**
200
* @dev Implementation of the {IERC721} Non-Fungible Token Standard
201
*/
202
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
203
/**
204
* @dev Sets the values for {name} and {symbol}
205
*/
206
constructor(string memory name_, string memory symbol_);
207
208
/**
209
* @dev Returns the token collection name
210
*/
211
function name() public view virtual returns (string memory);
212
213
/**
214
* @dev Returns the token collection symbol
215
*/
216
function symbol() public view virtual returns (string memory);
217
218
/**
219
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token
220
*/
221
function tokenURI(uint256 tokenId) public view virtual returns (string memory);
222
223
/**
224
* @dev Returns the number of tokens in `owner`'s account
225
*/
226
function balanceOf(address owner) public view virtual returns (uint256);
227
228
/**
229
* @dev Returns the owner of the `tokenId` token
230
*/
231
function ownerOf(uint256 tokenId) public view virtual returns (address);
232
233
/**
234
* @dev Gives permission to `to` to transfer `tokenId` token to another account
235
*/
236
function approve(address to, uint256 tokenId) public virtual;
237
238
/**
239
* @dev Returns the account approved for `tokenId` token
240
*/
241
function getApproved(uint256 tokenId) public view virtual returns (address);
242
243
/**
244
* @dev Approve or remove `operator` as an operator for the caller
245
*/
246
function setApprovalForAll(address operator, bool approved) public virtual;
247
248
/**
249
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`
250
*/
251
function isApprovedForAll(address owner, address operator) public view virtual returns (bool);
252
253
/**
254
* @dev Transfers `tokenId` token from `from` to `to`
255
*/
256
function transferFrom(address from, address to, uint256 tokenId) public virtual;
257
258
/**
259
* @dev Safely transfers `tokenId` token from `from` to `to`
260
*/
261
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual;
262
263
/**
264
* @dev Safely transfers `tokenId` token from `from` to `to` with additional data
265
*/
266
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual;
267
268
/**
269
* @dev Mints `tokenId` and transfers it to `to`
270
* Internal function that can be called by derived contracts
271
*/
272
function _mint(address to, uint256 tokenId) internal;
273
274
/**
275
* @dev Destroys `tokenId` token
276
* Internal function that can be called by derived contracts
277
*/
278
function _burn(uint256 tokenId) internal;
279
}
280
```
281
282
**Usage Example:**
283
284
```solidity
285
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
286
import "@openzeppelin/contracts/access/Ownable.sol";
287
288
contract MyNFT is ERC721, Ownable {
289
uint256 private _tokenIdCounter;
290
291
constructor(address initialOwner)
292
ERC721("MyNFT", "MNFT")
293
Ownable(initialOwner)
294
{}
295
296
function safeMint(address to) public onlyOwner {
297
uint256 tokenId = _tokenIdCounter++;
298
_safeMint(to, tokenId);
299
}
300
301
function tokenURI(uint256 tokenId) public view override returns (string memory) {
302
_requireOwned(tokenId);
303
return string(abi.encodePacked("https://api.example.com/token/", tokenId));
304
}
305
}
306
```
307
308
### ERC721 Extensions
309
310
Extended functionality for ERC721 tokens including enumeration, URI storage, and more.
311
312
```solidity { .api }
313
// ERC721 Enumerable - Token enumeration functionality
314
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
315
function totalSupply() public view virtual returns (uint256);
316
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256);
317
function tokenByIndex(uint256 index) public view virtual returns (uint256);
318
}
319
320
// ERC721 URI Storage - Per-token URI storage
321
abstract contract ERC721URIStorage is IERC4906, ERC721 {
322
function tokenURI(uint256 tokenId) public view virtual override returns (string memory);
323
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual;
324
}
325
326
// ERC721 Burnable - Token burning functionality
327
abstract contract ERC721Burnable is Context, ERC721 {
328
function burn(uint256 tokenId) public virtual;
329
}
330
331
// ERC721 Pausable - Emergency pause functionality
332
abstract contract ERC721Pausable is ERC721, Pausable {
333
function _update(address to, uint256 tokenId, address auth) internal virtual override whenNotPaused returns (address);
334
}
335
336
// ERC721 Royalty - EIP-2981 royalty functionality
337
abstract contract ERC721Royalty is ERC721, ERC2981 {
338
function _burn(uint256 tokenId) internal virtual override;
339
}
340
```
341
342
### ERC1155 Multi-Token Standard
343
344
Implementation of the ERC1155 standard supporting multiple token types in a single contract.
345
346
```solidity { .api }
347
/**
348
* @dev Implementation of the {IERC1155} Multi Token Standard
349
*/
350
abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors {
351
/**
352
* @dev Sets the URI for all token types
353
*/
354
constructor(string memory uri_);
355
356
/**
357
* @dev Returns the URI for token type `id`
358
*/
359
function uri(uint256 id) public view virtual returns (string memory);
360
361
/**
362
* @dev Returns the value of tokens of token type `id` owned by `account`
363
*/
364
function balanceOf(address account, uint256 id) public view virtual returns (uint256);
365
366
/**
367
* @dev Batched version of {balanceOf}
368
*/
369
function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual returns (uint256[] memory);
370
371
/**
372
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens
373
*/
374
function setApprovalForAll(address operator, bool approved) public virtual;
375
376
/**
377
* @dev Returns true if `operator` is approved to transfer `account`'s tokens
378
*/
379
function isApprovedForAll(address account, address operator) public view virtual returns (bool);
380
381
/**
382
* @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`
383
*/
384
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual;
385
386
/**
387
* @dev Batched version of {safeTransferFrom}
388
*/
389
function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data) public virtual;
390
391
/**
392
* @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`
393
* Internal function that can be called by derived contracts
394
*/
395
function _mint(address to, uint256 id, uint256 value, bytes memory data) internal;
396
397
/**
398
* @dev Batched version of {_mint}
399
*/
400
function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal;
401
402
/**
403
* @dev Destroys a `value` amount of tokens of type `id` from `from`
404
* Internal function that can be called by derived contracts
405
*/
406
function _burn(address from, uint256 id, uint256 value) internal;
407
408
/**
409
* @dev Batched version of {_burn}
410
*/
411
function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal;
412
}
413
```
414
415
**Usage Example:**
416
417
```solidity
418
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
419
import "@openzeppelin/contracts/access/Ownable.sol";
420
421
contract MyMultiToken is ERC1155, Ownable {
422
constructor(address initialOwner)
423
ERC1155("https://api.example.com/token/{id}.json")
424
Ownable(initialOwner)
425
{}
426
427
function mint(address to, uint256 id, uint256 amount, bytes memory data) public onlyOwner {
428
_mint(to, id, amount, data);
429
}
430
431
function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) public onlyOwner {
432
_mintBatch(to, ids, amounts, data);
433
}
434
}
435
```
436
437
### ERC6909 Multi-Token with Allowances
438
439
Draft implementation of ERC6909 standard providing multi-token functionality with per-token allowances.
440
441
```solidity { .api }
442
/**
443
* @dev Implementation of ERC6909 multi-token standard with per-token-type allowances
444
* Combines benefits of ERC20 (per-token allowances) with ERC1155 (multi-token support)
445
*/
446
abstract contract ERC6909 is Context, ERC165, IERC6909 {
447
/**
448
* @dev Returns the balance of `owner` for token `id`
449
*/
450
function balanceOf(address owner, uint256 id) public view virtual returns (uint256);
451
452
/**
453
* @dev Returns the allowance `owner` has given `spender` for token `id`
454
*/
455
function allowance(address owner, address spender, uint256 id) public view virtual returns (uint256);
456
457
/**
458
* @dev Returns true if `spender` is approved as an operator for `owner`
459
*/
460
function isOperator(address owner, address spender) public view virtual returns (bool);
461
462
/**
463
* @dev Approve `spender` to spend `amount` of token `id` on behalf of caller
464
*/
465
function approve(address spender, uint256 id, uint256 amount) public virtual returns (bool);
466
467
/**
468
* @dev Set `spender` as operator for all tokens owned by caller
469
*/
470
function setOperator(address spender, bool approved) public virtual returns (bool);
471
472
/**
473
* @dev Transfer `amount` of token `id` to `receiver`
474
*/
475
function transfer(address receiver, uint256 id, uint256 amount) public virtual returns (bool);
476
477
/**
478
* @dev Transfer `amount` of token `id` from `sender` to `receiver`
479
*/
480
function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public virtual returns (bool);
481
482
/**
483
* @dev Internal function to update balances during transfers
484
*/
485
function _update(address from, address to, uint256 id, uint256 amount) internal virtual;
486
487
/**
488
* @dev Internal function to mint tokens
489
*/
490
function _mint(address to, uint256 id, uint256 amount) internal;
491
492
/**
493
* @dev Internal function to burn tokens
494
*/
495
function _burn(address from, uint256 id, uint256 amount) internal;
496
}
497
```
498
499
**Usage Example:**
500
501
```solidity
502
import "@openzeppelin/contracts/token/ERC6909/draft-ERC6909.sol";
503
import "@openzeppelin/contracts/access/Ownable.sol";
504
505
contract MyERC6909Token is ERC6909, Ownable {
506
constructor(address initialOwner) Ownable(initialOwner) {}
507
508
function mint(address to, uint256 id, uint256 amount) public onlyOwner {
509
_mint(to, id, amount);
510
}
511
512
function burn(address from, uint256 id, uint256 amount) public {
513
require(from == msg.sender || isOperator(from, msg.sender) || allowance(from, msg.sender, id) >= amount, "Insufficient permission");
514
_burn(from, id, amount);
515
}
516
}
517
```
518
519
#### ERC6909 Extensions
520
521
**ERC6909ContentURI** - Provides URI functionality for tokens:
522
523
```solidity { .api }
524
abstract contract ERC6909ContentURI is ERC6909 {
525
function contractURI() public view virtual returns (string memory);
526
function tokenURI(uint256 id) public view virtual returns (string memory);
527
}
528
```
529
530
**ERC6909Metadata** - Adds name and symbol metadata:
531
532
```solidity { .api }
533
abstract contract ERC6909Metadata is ERC6909 {
534
function name(uint256 id) public view virtual returns (string memory);
535
function symbol(uint256 id) public view virtual returns (string memory);
536
function decimals(uint256 id) public view virtual returns (uint8);
537
}
538
```
539
540
**ERC6909TokenSupply** - Tracks total supply per token:
541
542
```solidity { .api }
543
abstract contract ERC6909TokenSupply is ERC6909 {
544
function totalSupply(uint256 id) public view virtual returns (uint256);
545
function exists(uint256 id) public view virtual returns (bool);
546
}
547
```
548
549
### Token Utilities
550
551
Utility contracts and libraries for safe token interactions and common patterns.
552
553
```solidity { .api }
554
// Safe ERC20 Operations
555
library SafeERC20 {
556
function safeTransfer(IERC20 token, address to, uint256 value) internal;
557
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal;
558
function safeApprove(IERC20 token, address spender, uint256 value) internal;
559
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal;
560
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal;
561
}
562
563
// ERC721 Holder - Safe NFT recipient
564
contract ERC721Holder is IERC721Receiver {
565
function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4);
566
}
567
568
// ERC1155 Holder - Safe multi-token recipient
569
contract ERC1155Holder is ERC1155Receiver {
570
function onERC1155Received(address, address, uint256, uint256, bytes memory) public virtual returns (bytes4);
571
function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory) public virtual returns (bytes4);
572
}
573
574
// ERC2981 Royalty Standard
575
abstract contract ERC2981 is IERC2981, ERC165 {
576
function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual returns (address, uint256);
577
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal;
578
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal;
579
function _deleteDefaultRoyalty() internal;
580
function _deleteTokenRoyalty(uint256 tokenId) internal;
581
}
582
```
583
584
## Common Interfaces
585
586
```solidity { .api }
587
// ERC20 Interface
588
interface IERC20 {
589
event Transfer(address indexed from, address indexed to, uint256 value);
590
event Approval(address indexed owner, address indexed spender, uint256 value);
591
592
function totalSupply() external view returns (uint256);
593
function balanceOf(address account) external view returns (uint256);
594
function transfer(address to, uint256 value) external returns (bool);
595
function allowance(address owner, address spender) external view returns (uint256);
596
function approve(address spender, uint256 value) external returns (bool);
597
function transferFrom(address from, address to, uint256 value) external returns (bool);
598
}
599
600
// ERC721 Interface
601
interface IERC721 {
602
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
603
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
604
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
605
606
function balanceOf(address owner) external view returns (uint256 balance);
607
function ownerOf(uint256 tokenId) external view returns (address owner);
608
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
609
function safeTransferFrom(address from, address to, uint256 tokenId) external;
610
function transferFrom(address from, address to, uint256 tokenId) external;
611
function approve(address to, uint256 tokenId) external;
612
function setApprovalForAll(address operator, bool approved) external;
613
function getApproved(uint256 tokenId) external view returns (address operator);
614
function isApprovedForAll(address owner, address operator) external view returns (bool);
615
}
616
617
// ERC1155 Interface
618
interface IERC1155 {
619
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
620
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
621
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
622
event URI(string value, uint256 indexed id);
623
624
function balanceOf(address account, uint256 id) external view returns (uint256);
625
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
626
function setApprovalForAll(address operator, bool approved) external;
627
function isApprovedForAll(address account, address operator) external view returns (bool);
628
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
629
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external;
630
}
631
```