Перейти к основному контенту
Change page

Стандарт асинхронных токенизированных хранилищ ERC-7540

Введение

ERC-7540 расширяет стандарт токенизированных хранилищ ERC-4626, добавляя поддержку асинхронных процессов депозита и выкупа. Он вводит паттерн «запрос-затем-востребование»: пользователи сначала отправляют запрос (блокируя свои активы или доли), а затем востребуют результат после того, как хранилище его обработает.

Это необходимо, когда хранилище не может выполнить финализацию расчетов мгновенно в одной транзакции, например:

  • Протоколы для активов реального мира (RWA), такие как токенизированные казначейские облигации, частные кредиты и другие активы с циклами финализации расчетов T+1 или T+2
  • Недостаточно обеспеченное кредитование, где оценка кредитоспособности происходит офчейн
  • Кроссчейн-стратегии хранилищ, где использование мостов вносит задержки
  • Токены ликвидного стейкинга (LST) с периодами отвязки

Хранилища могут быть асинхронными только для депозитов, только для выкупов или для обоих процессов. Эта гибкость позволяет разработчикам хранилищ добавлять асинхронные процессы только там, где этого требует базовая стратегия, оставляя другую сторону синхронной.

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

Для лучшего понимания этой страницы мы рекомендуем сначала прочитать про стандарты токенов, ERC-20 и ERC-4626.

ERC-4626 против ERC-7540

В ERC-4626 депозит проходит финализацию расчетов атомарно: инвестор отправляет активы и получает обратно доли в рамках одной транзакции.

ERC-4626 synchronous deposit flow

ERC-7540 разделяет это на два шага. Инвестор сначала вызывает requestDeposit() для блокировки активов, затем ждет, пока управляющий хранилищем обработает запрос. После выполнения инвестор вызывает deposit(), чтобы востребовать свои доли. Обменные курсы определяются в момент выполнения, а не в момент запроса.

ERC-7540 asynchronous deposit flow

Процесс выкупа работает аналогичным образом: requestRedeem() блокирует доли, и после выполнения инвестор вызывает redeem(), чтобы востребовать активы.

Функции и особенности ERC-7540

ERC-7540 наследует полный интерфейс ERC-4626, но перепрофилирует deposit/mint/withdraw/redeem как функции востребования. Новые функции requestDeposit и requestRedeem обрабатывают начальный этап запроса.

Каждый запрос проходит через три состояния: в ожидании (отправлен, ожидает обработки), доступный для востребования (выполнен и оценен) и востребованный (инвестор забрал свои доли или активы).

Request lifecycle: Pending, Claimable, Claimed

Процесс запроса депозита

requestDeposit

function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId)

Переводит assets от owner в хранилище и отправляет запрос на депозит. Адрес controller получает контроль над запросом. Возвращает requestId, идентифицирующий пакет запросов.

pendingDepositRequest

function pendingDepositRequest(uint256 requestId, address controller) external view returns (uint256 assets)

Возвращает количество assets в ожидающем (еще не доступном для востребования) запросе на депозит для заданных controller и requestId.

claimableDepositRequest

function claimableDepositRequest(uint256 requestId, address controller) external view returns (uint256 assets)

Возвращает количество assets в доступном для востребования (выполненном, но еще не востребованном) запросе на депозит для заданных controller и requestId.

Востребование депозитов

Как только запрос на депозит становится доступным для востребования, пользователь вызывает стандартную функцию ERC-4626 deposit или mint, чтобы востребовать свои доли. В ERC-7540 эти функции больше не переводят активы (это уже произошло во время запроса). Они только чеканят доли для получателя.

Процесс запроса выкупа

requestRedeem

function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 requestId)

Блокирует shares от owner и отправляет запрос на выкуп. Адрес controller получает контроль над запросом.

pendingRedeemRequest

function pendingRedeemRequest(uint256 requestId, address controller) external view returns (uint256 shares)

Возвращает количество shares в ожидающем запросе на выкуп для заданных controller и requestId.

claimableRedeemRequest

function claimableRedeemRequest(uint256 requestId, address controller) external view returns (uint256 shares)

Возвращает количество shares в доступном для востребования запросе на выкуп для заданных controller и requestId.

Востребование выкупов

Как только запрос на выкуп становится доступным для востребования, пользователь вызывает стандартную функцию ERC-4626 redeem или withdraw, чтобы востребовать свои активы.

Управление операторами

ERC-7540 включает паттерн оператора (из ERC-6909 (открывается в новой вкладке)), который позволяет третьим лицам управлять запросами от имени пользователя.

setOperator

function setOperator(address operator, bool approved) external returns (bool)

Одобряет или отзывает у operator право действовать от имени msg.sender для запросов на депозит/выкуп и востребований.

isOperator

function isOperator(address controller, address operator) external view returns (bool)

Возвращает информацию о том, одобрен ли operator для действий от имени controller.

Идентификаторы запросов

Идентификаторы запросов различают разные пакеты запросов. Все запросы, имеющие один и тот же requestId, взаимозаменяемы: они переходят между состояниями вместе и получают одинаковый обменный курс.

Когда хранилище возвращает requestId = 0 для всех запросов, только адрес controller различает состояние запроса. Несколько запросов от одного и того же контроллера агрегируются.

События

Событие DepositRequest

ДОЛЖНО генерироваться, когда запрос на депозит отправляется через requestDeposit.

event DepositRequest(
    address indexed controller,
    address indexed owner,
    uint256 indexed requestId,
    address sender,
    uint256 assets
)

Событие RedeemRequest

ДОЛЖНО генерироваться, когда запрос на выкуп отправляется через requestRedeem.

event RedeemRequest(
    address indexed controller,
    address indexed owner,
    uint256 indexed requestId,
    address sender,
    uint256 shares
)

Событие OperatorSet

ДОЛЖНО генерироваться, когда оператор одобряется или отзывается через setOperator.

event OperatorSet(
    address indexed controller,
    address indexed operator,
    bool approved
)

Функции предварительного просмотра

Функции предварительного просмотра должны выполнять откат только для асинхронных процессов, поскольку обменный курс неизвестен до выполнения запроса. В хранилище с асинхронным депозитом previewDeposit и previewMint ДОЛЖНЫ выполнять откат, в то время как previewRedeem и previewWithdraw продолжают работать как в ERC-4626 (и наоборот для хранилища с асинхронным выкупом). Это ключевое поведенческое отличие от ERC-4626.

Дополнительная литература