Блокчейн

Стандарты: ERC-20, ERC-721, ERC-1155

На Ethereum существует более 500 000 контрактов токенов, и при этом любой кошелёк мгновенно показывает ваш баланс каждого из них, а любой DEX позволяет обменять один на другой без специальной интеграции. Как это возможно, если каждый токен - это отдельный контракт, написанный разными командами? Секрет в трёх стандартах - ERC-20, ERC-721 и ERC-1155 - наборах функций и событий, которые превращают хаос из полумиллиона контрактов в единую, совместимую экосистему. Без них DeFi, NFT-маркетплейсы и блокчейн-игры просто не существовали бы.

  • **USDC (Circle)** - стейблкоин на ERC-20 с расширениями Pausable и Blacklistable. В 2023 году Circle заморозил 63M в USDC на адресах, попавших под санкции OFAC - это возможно именно благодаря расширяемой архитектуре ERC-20 + Pausable. Любой DEX работает с USDC без специальной интеграции, потому что контракт соответствует стандарту
  • **Bored Ape Yacht Club (BAYC)** - коллекция из 10 000 ERC-721 NFT, достигшая капитализации 4B. Каждый tokenId - уникальная обезьяна с атрибутами, хранящимися в метаданных (tokenURI → IPFS JSON). Маркетплейсы OpenSea, Blur, LooksRare торгуют ими без интеграции с конкретным контрактом - достаточно поддержки ERC-721
  • **Enjin / The Sandbox** - блокчейн-игры, использующие ERC-1155 для тысяч типов предметов в одном контракте. Batch-операции позволяют раздавать стартовые наборы из 20 предметов за один вызов вместо 20 отдельных транзакций, экономя игрокам сотни долларов на gas

Предварительные знания

  • Solidity: Language Basics

ERC-20: взаимозаменяемые токены

**ERC-20** - стандарт взаимозаменяемых (fungible) токенов на Ethereum, предложенный Фабианом Фогельштеллером в ноябре 2015 года. «Взаимозаменяемый» означает, что каждый токен идентичен другому: 1 USDC = 1 USDC, так же как 1 доллар = 1 доллар. Стандарт определяет **интерфейс из 6 функций и 2 событий**, которому должен соответствовать контракт, чтобы кошельки, DEX-ы и другие контракты могли с ним взаимодействовать единообразно.

Ключевой паттерн ERC-20 - **двухшаговый трансфер через approve + transferFrom**. Когда вы хотите, чтобы DEX (например, Uniswap) списал ваши токены, вы не можете просто отправить их на контракт - контракт должен **сам** их забрать. Поэтому сначала вы вызываете `approve(uniswapRouter, amount)`, а затем контракт Uniswap вызывает `transferFrom(вы, пул, amount)`.

**Infinite approval** - распространённая практика вызова `approve(spender, type(uint256).max)`, чтобы не подтверждать каждую транзакцию. Но это создаёт огромный риск: если контракт spender-а будет взломан или содержит бэкдор, он сможет списать **все** ваши токены. В 2023 году через уязвимости в approve было украдено более 200M. Используйте точные суммы одобрения или стандарт ERC-2612 (permit) для gasless approvals.

Реальные примеры ERC-20 токенов: **USDC** (стейблкоин, 6 decimals вместо стандартных 18), **WETH** (обёрнутый ETH для совместимости с ERC-20), **UNI** (governance-токен Uniswap), **LINK** (utility-токен Chainlink). Используйте `SafeERC20` от OpenZeppelin для вызовов - некоторые токены (USDT) не возвращают `bool` из `transfer`, что ломает стандартные проверки.

Почему для взаимодействия с DEX (Uniswap, Sushiswap) используется двухшаговый паттерн approve + transferFrom, а не просто transfer?

ERC-721: невзаимозаменяемые токены (NFT)

**ERC-721** - стандарт невзаимозаменяемых токенов (NFT), принятый в январе 2018 года. В отличие от ERC-20, где все токены одинаковы, каждый ERC-721 токен **уникален** и идентифицируется своим `tokenId` (uint256). Один контракт - одна коллекция, где каждый tokenId имеет одного владельца. CryptoKitties - первый массовый проект на ERC-721 - настолько нагрузил Ethereum в 2017 году, что стала понятна необходимость формализации стандарта.

Ключевое отличие от ERC-20 - в ERC-721 есть `safeTransferFrom`, который проверяет, может ли получатель обработать NFT. Если контракт-получатель не реализует `IERC721Receiver`, токен будет навсегда **заблокирован** в контракте. Именно так были потеряны тысячи NFT, отправленных на обычные контракты через `transferFrom`.

**ERC721Enumerable** добавляет возможность перечислить все токены и все токены владельца, но значительно увеличивает gas при mint и transfer (дополнительные записи в storage). Для коллекций с тысячами NFT это может стоить на 50-100% больше gas. Альтернатива - **ERC721A** от Azuki, которая оптимизирует batch minting: минт 5 NFT стоит почти столько же, сколько минт 1.

Контракт-хранилище (vault) не реализует интерфейс IERC721Receiver. Что произойдёт при вызове safeTransferFrom для отправки NFT на этот контракт?

ERC-1155: мульти-токен стандарт

**ERC-1155** - стандарт мульти-токенов, предложенный командой Enjin в 2018 году. Главная идея: **один контракт управляет множеством типов токенов одновременно** - и fungible (как ERC-20), и non-fungible (как ERC-721). Это идеально подходит для игровых предметов: меч может существовать в 1 экземпляре (NFT), а зелье здоровья - в 10 000 экземпляров (fungible).

Главное преимущество ERC-1155 - **batch-операции**. Вместо 10 отдельных транзакций для передачи 10 разных токенов, вы отправляете одну `safeBatchTransferFrom`. Каждая транзакция на Ethereum стоит минимум 21000 gas за базовые расходы, поэтому батчинг может сэкономить **до 80% gas** при массовых операциях.

В ERC-1155 нет отдельного `approve` для каждого токена - только `setApprovalForAll`. Это упрощает UX (один approve вместо десяти), но означает «всё или ничего»: оператор получает доступ ко **всем** типам токенов владельца. Для URI используется паттерн `{id}` в строке - клиент заменяет `{id}` на hex-представление tokenId с нулями до 64 символов: `https://game.example.com/api/item/0000...0004.json`.

Игра хочет раздать 500 игрокам стартовый набор: 100 золота, 10 зелий и 1 уникальный меч. Почему ERC-1155 значительно эффективнее, чем отдельные ERC-20 + ERC-721 контракты?

Сравнение стандартов и новые ERC

Три основных стандарта токенов - ERC-20, ERC-721 и ERC-1155 - покрывают подавляющее большинство сценариев. Но выбор между ними зависит от конкретной задачи, а кроме них существуют новые стандарты, которые решают проблемы оригинальных ERC.

Помимо трёх основных стандартов, сообщество Ethereum создало ряд улучшений, решающих конкретные проблемы. **ERC-777** попытался заменить ERC-20, добавив hooks (автоматические вызовы при получении токенов) и операторов - но провалился из-за критической уязвимости к **reentrancy-атакам**.

**Почему ERC-777 провалился?** Hook `tokensReceived` вызывался через ERC-1820 Registry у получателя *до* завершения обновления балансов. Злоумышленник мог повторно вызвать функцию вывода внутри hook-а (reentrancy). Именно так был атакован **Imbtc** на Uniswap V1 в 2020 году, украдено ~300K. После этого сообщество де-факто отказалось от ERC-777 в пользу ERC-2612 permit.

В чём ключевая проблема стандарта ERC-777, из-за которой от него отказалось сообщество?

Расширения и продвинутые стандарты

OpenZeppelin предоставляет набор **расширений** для базовых стандартов токенов, которые добавляют часто востребованную функциональность. Вместо того чтобы писать логику с нуля (и рисковать ошибками), разработчики наследуют проверенные расширения - по принципу **composition over inheritance** через mixins.

**Wrapped-токены** решают проблему совместимости. ETH - нативная валюта Ethereum, но она не соответствует ERC-20. Контракт **WETH** (Wrapped ETH) позволяет обернуть ETH в ERC-20 токен: вносишь 1 ETH, получаешь 1 WETH (и наоборот). Аналогично **WBTC** - это Bitcoin, обёрнутый в ERC-20 через кастодиана (BitGo).

**ERC-6551 (Token Bound Accounts)** меняет парадигму: NFT из пассивного актива превращается в **активного участника** блокчейна. Каждый NFT получает свой детерминированный адрес (через CREATE2), который может хранить токены, отправлять транзакции и взаимодействовать с DeFi. При передаче NFT новому владельцу, всё содержимое аккаунта переходит вместе с ним - потому что только владелец NFT может управлять привязанным аккаунтом.

**Как выбрать расширения для токена:** Burnable - если нужна дефляция или механизм buy-and-burn. Pausable - если нужна аварийная остановка (регулируемые токены, стейблкоины). Permit (ERC-2612) - если хотите UX без отдельной approve-транзакции. Votes - если токен используется для governance (DAO). FlashMint - если хотите предоставлять flash loans. Snapshot - если нужна фиксация балансов на определённый блок (для аирдропов, голосований).

ERC-1155 - это просто комбинация ERC-20 и ERC-721 в одном контракте, без принципиальных отличий. Можно добиться того же результата, деплоя отдельные ERC-20 и ERC-721 контракты

ERC-1155 имеет фундаментальные архитектурные отличия: batch-операции (balanceOfBatch, safeBatchTransferFrom), единый approve для всех типов токенов через setApprovalForAll, один URI-шаблон с подстановкой {id}, и единый callback-интерфейс IERC1155Receiver. Отдельные ERC-20 + ERC-721 контракты не могут атомарно передавать разнотипные токены в одном вызове, требуют отдельных approve для каждого контракта и стоят значительно дороже по gas при массовых операциях

Это заблуждение возникает из-за поверхностного понимания: раз ERC-1155 поддерживает и fungible, и non-fungible, значит он просто объединяет ERC-20 + ERC-721. Но на практике разница не только количественная (меньше gas), а качественная: batch-операции позволяют реализовать атомарные обмены (trade), массовые раздачи (airdrop) и сложные игровые механики, которые невозможны или экономически нецелесообразны с отдельными контрактами. Один safeBatchTransferFrom заменяет десятки отдельных транзакций.

Что происходит с Token Bound Account (ERC-6551) NFT-персонажа, когда этот NFT продаётся на маркетплейсе другому пользователю?

Итоги

  • **ERC-20** определяет 6 функций и 2 события для взаимозаменяемых токенов. Ключевой паттерн - двухшаговый трансфер через `approve` + `transferFrom`, который позволяет контрактам (DEX, lending) атомарно списывать токены от имени пользователя. `SafeERC20` от OpenZeppelin решает проблему токенов, не возвращающих `bool`
  • **ERC-721** добавляет уникальность через `tokenId` и `safeTransferFrom` для защиты от потери NFT на контрактах без `IERC721Receiver`. Метаданные хранятся off-chain (IPFS/HTTP) и ссылаются через `tokenURI`. `ERC721Enumerable` позволяет перечислять токены, но увеличивает gas на mint
  • **ERC-1155** объединяет fungible и non-fungible токены в одном контракте с batch-операциями (`mintBatch`, `safeBatchTransferFrom`), экономя до 80% gas при массовых операциях. Один `setApprovalForAll` заменяет множество отдельных approve
  • **ERC-777** провалился из-за reentrancy через hooks, но идеи трансформировались в **ERC-2612** (gasless approve через permit-подписи) и **ERC-4626** (стандартный интерфейс yield-bearing хранилищ)
  • **Новые стандарты** расширяют возможности: **ERC-5192** (soul-bound tokens) делает токены непередаваемыми, а **ERC-6551** (token bound accounts) превращает каждый NFT в полноценный smart-account - и именно эта совместимая, расширяемая архитектура стандартов позволяет полумиллиону контрактов работать как единая экосистема

Связанные темы

Стандарты ERC - это интерфейсы, написанные на Solidity, которые реализуются через паттерны наследования и используются как строительные блоки DeFi-протоколов:

  • Solidity: основы языка — Интерфейсы, наследование, модификаторы и события - базовые конструкции Solidity, на которых построены все стандарты ERC
  • Паттерны Solidity — Checks-Effects-Interactions (против reentrancy в ERC-777), Proxy (для upgradeable-токенов), Factory (для деплоя токенов из фабрик)
  • AMM: автоматические маркетмейкеры — DEX-пулы (Uniswap, Curve) являются основными потребителями approve + transferFrom паттерна ERC-20 и часто сами выпускают LP-токены в формате ERC-20
  • Upgradeable-контракты — USDC, USDT и другие крупные токены используют proxy-паттерн для обновления логики ERC-20 без потери state (балансов, allowances)

Вопросы для размышления

  • ERC-20 не имеет safe-трансферов, и миллионы долларов были потеряны при отправке токенов на контракты без функции вывода. Почему сообщество не добавило safeTransfer в ERC-20, как это сделано в ERC-721 и ERC-1155? Какие trade-offs у обратной совместимости vs безопасности?
  • Soul-bound tokens (ERC-5192) запрещают передачу, но что если владелец потеряет ключ от кошелька? Как можно реализовать recovery-механизм для непередаваемых токенов, не нарушая их принцип «привязки к душе»?
  • ERC-6551 позволяет NFT владеть другими активами. Какие новые модели бизнеса и игровые механики это открывает? Как меняется ценообразование NFT, если в его аккаунте хранится ETH или другие токены?

Связанные уроки

  • comp-01-intro
Стандарты: ERC-20, ERC-721, ERC-1155

0

1

Войти