Стандарт асинхронных токенизированных хранилищ ERC-7540
Введение
ERC-7540 расширяет стандарт токенизированных хранилищ ERC-4626, добавляя поддержку асинхронных процессов депозита и выкупа. Он вводит паттерн «запрос-затем-востребование»: пользователи сначала отправляют запрос (блокируя свои активы или доли), а затем востребуют результат после того, как хранилище его обработает.
Это необходимо, когда хранилище не может выполнить финализацию расчетов мгновенно в одной транзакции, например:
- Протоколы для активов реального мира (RWA), такие как токенизированные казначейские облигации, частные кредиты и другие активы с циклами финализации расчетов T+1 или T+2
- Недостаточно обеспеченное кредитование, где оценка кредитоспособности происходит офчейн
- Кроссчейн-стратегии хранилищ, где использование мостов вносит задержки
- Токены ликвидного стейкинга (LST) с периодами отвязки
Хранилища могут быть асинхронными только для депозитов, только для выкупов или для обоих процессов. Эта гибкость позволяет разработчикам хранилищ добавлять асинхронные процессы только там, где этого требует базовая стратегия, оставляя другую сторону синхронной.
Предварительные требования
Для лучшего понимания этой страницы мы рекомендуем сначала прочитать про стандарты токенов, ERC-20 и ERC-4626.
ERC-4626 против ERC-7540
В ERC-4626 депозит проходит финализацию расчетов атомарно: инвестор отправляет активы и получает обратно доли в рамках одной транзакции.
ERC-7540 разделяет это на два шага. Инвестор сначала вызывает requestDeposit() для блокировки активов, затем ждет, пока управляющий хранилищем обработает запрос. После выполнения инвестор вызывает deposit(), чтобы востребовать свои доли. Обменные курсы определяются в момент выполнения, а не в момент запроса.
Процесс выкупа работает аналогичным образом: requestRedeem() блокирует доли, и после выполнения инвестор вызывает redeem(), чтобы востребовать активы.
Функции и особенности ERC-7540
ERC-7540 наследует полный интерфейс ERC-4626, но перепрофилирует deposit/mint/withdraw/redeem как функции востребования. Новые функции requestDeposit и requestRedeem обрабатывают начальный этап запроса.
Каждый запрос проходит через три состояния: в ожидании (отправлен, ожидает обработки), доступный для востребования (выполнен и оценен) и востребованный (инвестор забрал свои доли или активы).
Процесс запроса депозита
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.