or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

access-control.mdaccount-abstraction.mdfinance.mdgovernance.mdindex.mdmathematical-utilities.mdmeta-transactions.mdproxy-patterns.mdsecurity-utilities.mdtoken-standards.md

token-standards.mddocs/

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

```