0
# Token Standards
1
2
Complete implementations of popular token standards including ERC-20 fungible tokens, ERC-721 NFTs, ERC-1155 multi-tokens, and the draft ERC-6909 standard. All token contracts follow the upgradeable pattern with initialization functions.
3
4
## Capabilities
5
6
### ERC-20 Fungible Tokens
7
8
Standard implementation of the ERC-20 token interface for fungible tokens.
9
10
```solidity { .api }
11
/**
12
* @dev Implementation of the ERC-20 token standard
13
*/
14
contract ERC20Upgradeable {
15
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing;
16
17
/**
18
* @dev Returns the name of the token
19
*/
20
function name() external view returns (string memory);
21
22
/**
23
* @dev Returns the symbol of the token
24
*/
25
function symbol() external view returns (string memory);
26
27
/**
28
* @dev Returns the number of decimals used to get user representation
29
*/
30
function decimals() external view returns (uint8);
31
32
/**
33
* @dev Returns the total token supply
34
*/
35
function totalSupply() external view returns (uint256);
36
37
/**
38
* @dev Returns the balance of account
39
*/
40
function balanceOf(address account) external view returns (uint256);
41
42
/**
43
* @dev Moves value tokens from the caller's account to to
44
*/
45
function transfer(address to, uint256 value) external returns (bool);
46
47
/**
48
* @dev Returns the remaining number of tokens that spender can spend on behalf of owner
49
*/
50
function allowance(address owner, address spender) external view returns (uint256);
51
52
/**
53
* @dev Sets value as the allowance of spender over the caller's tokens
54
*/
55
function approve(address spender, uint256 value) external returns (bool);
56
57
/**
58
* @dev Moves value tokens from from to to using the allowance mechanism
59
*/
60
function transferFrom(address from, address to, uint256 value) external returns (bool);
61
}
62
63
// Events
64
event Transfer(address indexed from, address indexed to, uint256 value);
65
event Approval(address indexed owner, address indexed spender, uint256 value);
66
```
67
68
### ERC-20 Extensions
69
70
#### Burnable Extension
71
72
```solidity { .api }
73
/**
74
* @dev Extension that allows token holders to destroy tokens
75
*/
76
abstract contract ERC20BurnableUpgradeable {
77
/**
78
* @dev Destroys value tokens from the caller
79
*/
80
function burn(uint256 value) external;
81
82
/**
83
* @dev Destroys value tokens from account, deducting from the caller's allowance
84
*/
85
function burnFrom(address account, uint256 value) external;
86
}
87
```
88
89
#### Capped Extension
90
91
```solidity { .api }
92
/**
93
* @dev Extension that adds a cap to the supply of tokens
94
*/
95
abstract contract ERC20CappedUpgradeable {
96
function __ERC20Capped_init(uint256 cap_) internal onlyInitializing;
97
98
/**
99
* @dev Returns the cap on the token's total supply
100
*/
101
function cap() external view returns (uint256);
102
}
103
```
104
105
#### Pausable Extension
106
107
```solidity { .api }
108
/**
109
* @dev ERC-20 token with pausable token transfers, minting and burning
110
*/
111
abstract contract ERC20PausableUpgradeable {
112
function __ERC20Pausable_init() internal onlyInitializing;
113
// Inherits pause functionality, automatically pauses transfers when contract is paused
114
}
115
```
116
117
#### Permit Extension (EIP-2612)
118
119
```solidity { .api }
120
/**
121
* @dev Implementation of EIP-2612 permit functionality
122
*/
123
abstract contract ERC20PermitUpgradeable {
124
function __ERC20Permit_init(string memory name) internal onlyInitializing;
125
126
/**
127
* @dev Sets value as the allowance of spender over owner's tokens via signature
128
*/
129
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
130
131
/**
132
* @dev Returns the current nonce for owner
133
*/
134
function nonces(address owner) external view returns (uint256);
135
136
/**
137
* @dev Returns the domain separator for the current chain
138
*/
139
function DOMAIN_SEPARATOR() external view returns (bytes32);
140
}
141
```
142
143
#### Votes Extension
144
145
```solidity { .api }
146
/**
147
* @dev Extension of ERC-20 to support Compound-like voting and delegation
148
*/
149
abstract contract ERC20VotesUpgradeable {
150
function __ERC20Votes_init() internal onlyInitializing;
151
152
/**
153
* @dev Returns the current amount of votes that account has
154
*/
155
function getVotes(address account) external view returns (uint256);
156
157
/**
158
* @dev Returns the amount of votes that account had at the end of the last completed checkpoint
159
*/
160
function getPastVotes(address account, uint256 timepoint) external view returns (uint256);
161
162
/**
163
* @dev Delegates votes from the sender to delegatee
164
*/
165
function delegate(address delegatee) external;
166
167
/**
168
* @dev Delegates votes from signer to delegatee
169
*/
170
function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
171
}
172
```
173
174
#### Wrapper Extension
175
176
```solidity { .api }
177
/**
178
* @dev Extension that allows wrapping of an underlying ERC-20 token
179
*/
180
abstract contract ERC20WrapperUpgradeable {
181
function __ERC20Wrapper_init(IERC20 underlyingToken) internal onlyInitializing;
182
183
/**
184
* @dev Returns the underlying token
185
*/
186
function underlying() external view returns (IERC20);
187
188
/**
189
* @dev Allow a user to deposit underlying tokens and mint the corresponding wrapper tokens
190
*/
191
function depositFor(address account, uint256 value) external returns (bool);
192
193
/**
194
* @dev Allow a user to burn wrapper tokens and withdraw the corresponding underlying tokens
195
*/
196
function withdrawTo(address account, uint256 value) external returns (bool);
197
}
198
```
199
200
#### ERC-4626 Tokenized Vault
201
202
```solidity { .api }
203
/**
204
* @dev Implementation of the ERC-4626 "Tokenized Vault Standard"
205
*/
206
contract ERC4626Upgradeable {
207
function __ERC4626_init(IERC20 asset_) internal onlyInitializing;
208
209
/**
210
* @dev Returns the address of the underlying token used for the Vault
211
*/
212
function asset() external view returns (address);
213
214
/**
215
* @dev Returns the total amount of the underlying asset managed by the Vault
216
*/
217
function totalAssets() external view returns (uint256);
218
219
/**
220
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided
221
*/
222
function convertToShares(uint256 assets) external view returns (uint256);
223
224
/**
225
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided
226
*/
227
function convertToAssets(uint256 shares) external view returns (uint256);
228
229
/**
230
* @dev Returns the maximum amount of the underlying asset that can be deposited
231
*/
232
function maxDeposit(address receiver) external view returns (uint256);
233
234
/**
235
* @dev Returns the amount of shares that would be minted for a deposit
236
*/
237
function previewDeposit(uint256 assets) external view returns (uint256);
238
239
/**
240
* @dev Mints shares to receiver by depositing exactly assets of underlying tokens
241
*/
242
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
243
244
/**
245
* @dev Mints exactly shares to receiver by depositing assets of underlying tokens
246
*/
247
function mint(uint256 shares, address receiver) external returns (uint256 assets);
248
249
/**
250
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver
251
*/
252
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
253
254
/**
255
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver
256
*/
257
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
258
}
259
260
// Events
261
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
262
event Withdraw(address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares);
263
```
264
265
#### Flash Mint Extension (ERC-3156)
266
267
```solidity { .api }
268
/**
269
* @dev Extension that adds flash loan functionality to ERC-20 tokens
270
*/
271
abstract contract ERC20FlashMintUpgradeable {
272
function __ERC20FlashMint_init() internal onlyInitializing;
273
274
/**
275
* @dev Returns the maximum amount of tokens available for loan
276
*/
277
function maxFlashLoan(address token) external view returns (uint256);
278
279
/**
280
* @dev Returns the fee for a flash loan
281
*/
282
function flashFee(address token, uint256 amount) external view returns (uint256);
283
284
/**
285
* @dev Initiates a flash loan
286
*/
287
function flashLoan(
288
IERC3156FlashBorrower receiver,
289
address token,
290
uint256 amount,
291
bytes calldata data
292
) external returns (bool);
293
}
294
295
// Custom errors
296
error ERC3156UnsupportedToken(address token);
297
error ERC3156ExceededMaxLoan(uint256 maxLoan);
298
error ERC3156InvalidReceiver(address receiver);
299
```
300
301
#### Wrapper Extension
302
303
```solidity { .api }
304
/**
305
* @dev Extension that wraps an existing ERC-20 token
306
*/
307
abstract contract ERC20WrapperUpgradeable {
308
function __ERC20Wrapper_init(IERC20 underlyingToken) internal onlyInitializing;
309
310
/**
311
* @dev Returns the underlying token being wrapped
312
*/
313
function underlying() external view returns (IERC20);
314
315
/**
316
* @dev Deposits underlying tokens and mints wrapper tokens
317
*/
318
function depositFor(address account, uint256 amount) external returns (bool);
319
320
/**
321
* @dev Withdraws underlying tokens by burning wrapper tokens
322
*/
323
function withdrawTo(address account, uint256 amount) external returns (bool);
324
325
/**
326
* @dev Recovers any ERC-20 token sent by mistake to the contract
327
*/
328
function _recover(address account) internal returns (uint256);
329
}
330
```
331
332
#### Temporary Approval Extension (Draft)
333
334
```solidity { .api }
335
/**
336
* @dev Draft extension for temporary token approvals with expiration
337
*/
338
abstract contract ERC20TemporaryApprovalUpgradeable {
339
function __ERC20TemporaryApproval_init() internal onlyInitializing;
340
341
/**
342
* @dev Sets a temporary approval that expires at a specific timestamp
343
*/
344
function temporaryApprove(address spender, uint256 amount, uint256 validUntil) external returns (bool);
345
346
/**
347
* @dev Returns the temporary allowance details including expiration
348
*/
349
function temporaryAllowance(address owner, address spender) external view returns (uint256 amount, uint256 validUntil);
350
}
351
```
352
353
#### Bridgeable Extension (Draft)
354
355
```solidity { .api }
356
/**
357
* @dev Draft extension for cross-chain bridging functionality
358
*/
359
abstract contract ERC20BridgeableUpgradeable {
360
function __ERC20Bridgeable_init() internal onlyInitializing;
361
362
/**
363
* @dev Burns tokens for bridging to another chain
364
*/
365
function burnForBridge(address account, uint256 amount, bytes calldata bridgeData) external;
366
367
/**
368
* @dev Mints tokens from a bridge operation
369
*/
370
function mintFromBridge(address account, uint256 amount, bytes calldata bridgeData) external;
371
}
372
```
373
374
### ERC-721 Non-Fungible Tokens
375
376
Standard implementation of the ERC-721 token interface for non-fungible tokens (NFTs).
377
378
```solidity { .api }
379
/**
380
* @dev Implementation of the ERC-721 Non-Fungible Token Standard
381
*/
382
contract ERC721Upgradeable {
383
function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing;
384
385
/**
386
* @dev Returns true if this contract implements the interface defined by interfaceId
387
*/
388
function supportsInterface(bytes4 interfaceId) external view returns (bool);
389
390
/**
391
* @dev Returns the number of tokens in owner's account
392
*/
393
function balanceOf(address owner) external view returns (uint256);
394
395
/**
396
* @dev Returns the owner of the tokenId token
397
*/
398
function ownerOf(uint256 tokenId) external view returns (address);
399
400
/**
401
* @dev Returns the token collection name
402
*/
403
function name() external view returns (string memory);
404
405
/**
406
* @dev Returns the token collection symbol
407
*/
408
function symbol() external view returns (string memory);
409
410
/**
411
* @dev Returns the Uniform Resource Identifier (URI) for tokenId token
412
*/
413
function tokenURI(uint256 tokenId) external view returns (string memory);
414
415
/**
416
* @dev Gives permission to to to transfer tokenId token to another account
417
*/
418
function approve(address to, uint256 tokenId) external;
419
420
/**
421
* @dev Returns the account approved for tokenId token
422
*/
423
function getApproved(uint256 tokenId) external view returns (address);
424
425
/**
426
* @dev Approve or remove operator as an operator for the caller
427
*/
428
function setApprovalForAll(address operator, bool approved) external;
429
430
/**
431
* @dev Returns if the operator is allowed to manage all of the assets of owner
432
*/
433
function isApprovedForAll(address owner, address operator) external view returns (bool);
434
435
/**
436
* @dev Transfers tokenId token from from to to
437
*/
438
function transferFrom(address from, address to, uint256 tokenId) external;
439
440
/**
441
* @dev Safely transfers tokenId token from from to to
442
*/
443
function safeTransferFrom(address from, address to, uint256 tokenId) external;
444
445
/**
446
* @dev Safely transfers tokenId token from from to to with additional data
447
*/
448
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
449
}
450
451
// Events
452
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
453
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
454
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
455
```
456
457
### ERC-721 Extensions
458
459
#### Enumerable Extension
460
461
```solidity { .api }
462
/**
463
* @dev Extension of ERC-721 that adds enumerability of all the token ids in the contract
464
*/
465
abstract contract ERC721EnumerableUpgradeable {
466
function __ERC721Enumerable_init() internal onlyInitializing;
467
468
/**
469
* @dev Returns a token ID owned by owner at a given index of its token list
470
*/
471
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
472
473
/**
474
* @dev Returns the total amount of tokens stored by the contract
475
*/
476
function totalSupply() external view returns (uint256);
477
478
/**
479
* @dev Returns a token ID at a given index of all the tokens stored by the contract
480
*/
481
function tokenByIndex(uint256 index) external view returns (uint256);
482
}
483
```
484
485
#### URI Storage Extension
486
487
```solidity { .api }
488
/**
489
* @dev Extension that allows setting individual token URIs
490
*/
491
abstract contract ERC721URIStorageUpgradeable {
492
function __ERC721URIStorage_init() internal onlyInitializing;
493
494
/**
495
* @dev Returns the URI for a given token ID
496
*/
497
function tokenURI(uint256 tokenId) external view override returns (string memory);
498
499
/**
500
* @dev Sets tokenURI as the tokenURI of tokenId
501
*/
502
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal;
503
}
504
```
505
506
#### Royalty Extension
507
508
```solidity { .api }
509
/**
510
* @dev Extension of ERC-721 that adds ERC-2981 royalty support
511
*/
512
abstract contract ERC721RoyaltyUpgradeable {
513
function __ERC721Royalty_init() internal onlyInitializing;
514
515
/**
516
* @dev Returns how much royalty is owed and to whom for tokenId sold at salePrice
517
*/
518
function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address, uint256);
519
}
520
```
521
522
#### Consecutive Extension (ERC-2309)
523
524
```solidity { .api }
525
/**
526
* @dev Extension that allows efficient batch minting of consecutive token IDs
527
*/
528
abstract contract ERC721ConsecutiveUpgradeable {
529
function __ERC721Consecutive_init() internal onlyInitializing;
530
531
/**
532
* @dev Returns the first token ID in a consecutive batch
533
*/
534
function _firstConsecutiveId() internal view returns (uint96);
535
536
/**
537
* @dev Returns the next consecutive token ID to be minted
538
*/
539
function _nextConsecutiveId() internal view returns (uint96);
540
541
/**
542
* @dev Mints consecutive token IDs in a batch
543
*/
544
function _mintConsecutive(address to, uint96 batchSize) internal returns (uint256 first);
545
546
/**
547
* @dev Maximum batch size for consecutive minting (default: 5000)
548
*/
549
function _maxBatchSize() internal view virtual returns (uint256);
550
}
551
552
// Events (ERC-2309)
553
event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
554
```
555
556
#### Wrapper Extension
557
558
```solidity { .api }
559
/**
560
* @dev Extension that wraps existing ERC-721 tokens into new tokens
561
*/
562
abstract contract ERC721WrapperUpgradeable {
563
function __ERC721Wrapper_init(IERC721 underlyingToken) internal onlyInitializing;
564
565
/**
566
* @dev Returns the underlying token contract being wrapped
567
*/
568
function underlying() external view returns (IERC721);
569
570
/**
571
* @dev Deposits an underlying token and mints a wrapped token
572
*/
573
function depositFor(address account, uint256[] calldata tokenIds) external returns (bool);
574
575
/**
576
* @dev Withdraws underlying tokens by burning wrapped tokens
577
*/
578
function withdrawTo(address account, uint256[] calldata tokenIds) external returns (bool);
579
}
580
```
581
582
#### Burnable Extension
583
584
```solidity { .api }
585
/**
586
* @dev Extension that allows token holders to destroy their tokens
587
*/
588
abstract contract ERC721BurnableUpgradeable {
589
function __ERC721Burnable_init() internal onlyInitializing;
590
591
/**
592
* @dev Burns tokenId
593
*/
594
function burn(uint256 tokenId) external;
595
}
596
```
597
598
#### Pausable Extension
599
600
```solidity { .api }
601
/**
602
* @dev Extension that adds pausable functionality to transfers
603
*/
604
abstract contract ERC721PausableUpgradeable {
605
function __ERC721Pausable_init() internal onlyInitializing;
606
// Inherits pause functionality, automatically pauses transfers when contract is paused
607
}
608
```
609
610
#### Votes Extension
611
612
```solidity { .api }
613
/**
614
* @dev Extension that adds vote delegation functionality
615
*/
616
abstract contract ERC721VotesUpgradeable {
617
function __ERC721Votes_init() internal onlyInitializing;
618
619
/**
620
* @dev Returns the current amount of votes that account has
621
*/
622
function getVotes(address account) external view returns (uint256);
623
624
/**
625
* @dev Returns the amount of votes that account had at a specific timepoint
626
*/
627
function getPastVotes(address account, uint256 timepoint) external view returns (uint256);
628
629
/**
630
* @dev Delegates votes from the sender to delegatee
631
*/
632
function delegate(address delegatee) external;
633
634
/**
635
* @dev Delegates votes from signer to delegatee using signature
636
*/
637
function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
638
}
639
```
640
641
### ERC-1155 Multi-Token Standard
642
643
Implementation of the ERC-1155 Multi Token Standard that supports both fungible and non-fungible tokens.
644
645
```solidity { .api }
646
/**
647
* @dev Implementation of the basic standard multi-token
648
*/
649
contract ERC1155Upgradeable {
650
function __ERC1155_init(string memory uri_) internal onlyInitializing;
651
652
/**
653
* @dev Returns true if this contract implements the interface defined by interfaceId
654
*/
655
function supportsInterface(bytes4 interfaceId) external view returns (bool);
656
657
/**
658
* @dev Returns the URI for token type id
659
*/
660
function uri(uint256 id) external view returns (string memory);
661
662
/**
663
* @dev Returns the balance of account's tokens of token type id
664
*/
665
function balanceOf(address account, uint256 id) external view returns (uint256);
666
667
/**
668
* @dev Returns the balance of multiple account/token pairs
669
*/
670
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
671
672
/**
673
* @dev Grants or revokes permission to operator to transfer the caller's tokens
674
*/
675
function setApprovalForAll(address operator, bool approved) external;
676
677
/**
678
* @dev Returns true if operator is approved to transfer account's tokens
679
*/
680
function isApprovedForAll(address account, address operator) external view returns (bool);
681
682
/**
683
* @dev Transfers value tokens of token type id from from to to
684
*/
685
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
686
687
/**
688
* @dev Batch version of safeTransferFrom
689
*/
690
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external;
691
}
692
693
// Events
694
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
695
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
696
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
697
event URI(string value, uint256 indexed id);
698
```
699
700
### ERC-1155 Extensions
701
702
#### Supply Extension
703
704
```solidity { .api }
705
/**
706
* @dev Extension that adds tracking of total supply per token id
707
*/
708
abstract contract ERC1155SupplyUpgradeable {
709
function __ERC1155Supply_init() internal onlyInitializing;
710
711
/**
712
* @dev Total value of tokens with a given id
713
*/
714
function totalSupply(uint256 id) external view returns (uint256);
715
716
/**
717
* @dev Total value of tokens
718
*/
719
function totalSupply() external view returns (uint256);
720
721
/**
722
* @dev Indicates whether any token exist with a given id, or not
723
*/
724
function exists(uint256 id) external view returns (bool);
725
}
726
```
727
728
### Common Token Utilities
729
730
#### ERC-2981 Royalty Standard
731
732
```solidity { .api }
733
/**
734
* @dev Implementation of the NFT Royalty Standard
735
*/
736
abstract contract ERC2981Upgradeable {
737
function __ERC2981_init() internal onlyInitializing;
738
739
/**
740
* @dev Returns how much royalty is owed and to whom for tokenId sold at salePrice
741
*/
742
function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address, uint256);
743
744
/**
745
* @dev Sets the royalty information that all ids in this contract will default to
746
*/
747
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal;
748
749
/**
750
* @dev Sets the royalty information for a specific token id
751
*/
752
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal;
753
754
/**
755
* @dev Removes default royalty information
756
*/
757
function _deleteDefaultRoyalty() internal;
758
759
/**
760
* @dev Resets royalty information for the token id
761
*/
762
function _resetTokenRoyalty(uint256 tokenId) internal;
763
}
764
```
765
766
## Usage Examples
767
768
### Basic ERC-20 Token
769
770
```solidity
771
import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
772
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
773
774
contract MyToken is ERC20Upgradeable, OwnableUpgradeable {
775
function initialize(address initialOwner) initializer public {
776
__ERC20_init("MyToken", "MTK");
777
__Ownable_init(initialOwner);
778
}
779
780
function mint(address to, uint256 amount) public onlyOwner {
781
_mint(to, amount);
782
}
783
}
784
```
785
786
### ERC-721 NFT with Royalties
787
788
```solidity
789
import {ERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
790
import {ERC721RoyaltyUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721RoyaltyUpgradeable.sol";
791
792
contract MyNFT is ERC721Upgradeable, ERC721RoyaltyUpgradeable {
793
function initialize() initializer public {
794
__ERC721_init("MyNFT", "MNFT");
795
__ERC721Royalty_init();
796
_setDefaultRoyalty(msg.sender, 250); // 2.5% royalty
797
}
798
799
function mint(address to, uint256 tokenId) public {
800
_mint(to, tokenId);
801
}
802
}
803
```
804
805
### ERC-4626 Vault
806
807
```solidity
808
import {ERC4626Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol";
809
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
810
811
contract MyVault is ERC4626Upgradeable {
812
function initialize(IERC20 asset) initializer public {
813
__ERC4626_init(asset);
814
__ERC20_init("My Vault Token", "MVT");
815
}
816
817
function _totalAssets() internal view override returns (uint256) {
818
return IERC20(asset()).balanceOf(address(this));
819
}
820
}
821
```