For the complete documentation index, see llms.txt. This page is also available as Markdown.

Создание в Bloom

Это руководство отвечает на один вопрос: как разработчик делает это самостоятельно? Возьмите контракт Solidity для реального актива, разверните его в цепочке Rome как разрешённый токен, откройте его как для кошельков Solana, так и для EVM-кошельков без моста и без второго токена, и подключите собственное решение KYC/комплаенса.

Аудитория — это разработчик, который оценивает или внедряет данный подход. Bloom на протяжении всего текста служит практическим примером — его актив ARCV ("Mineral Vault I") на Hadrian (200010) — это реальный экземпляр каждого шага ниже, а его квитанция о развертывании (deployments/200010.tokens/ARCV.json) фиксирует ровно три контракта и восемь транзакций, которые создаёт этот метод.

Ничто здесь не изменяет контракты актива. Bloom использует фреймворк Arc от Plume без изменений (вендоризированное дерево в contracts/, побайтно идентичное plumenetwork/contracts на закреплённой версии в NOTICE); единственный контракт на стороне Rome — это ArcTokenFactoryV2, который добавляет одну функцию. Работа заключается в том, как вы разворачиваете и том, как управляете контрактами — а не в их изменении.

Метод в общих чертах. Разрешённый токен — это три развернутых контракта. Он разворачивается поэтапно — по одному контракту на транзакцию — потому что вызов фабрики в одной транзакции превышает лимит Rome на количество аккаунтов в транзакции. Его прокси должны происходить из артефактов с закреплённым происхождением иначе ончейн-регистрация завершится неудачей по принципу fail-closed. Комплаенс — это один булев флаг на адрес, записываемый тем, кого авторизует ваш KYC-процесс. А то же самое развертывание доступно из кошелька Solana через синтетический отправитель который выводится ончейн — без моста, без обёрнутого токена, без второго allowlist.

Требования

Весь эталонный инструментарий находится в scripts/ (сначала выполните npm install там). Каждая команда получает сведения о цепочке из реестра, а не задаёт их жёстко, поэтому перенос на другую цепочку Rome — это изменение окружения, а не кода:

export PRIVATE_KEY=# ключ финансируемого деплойера/эмитента в целевой цепочке
export CHAIN_ID=200010     # выбирает цепочку
export REGISTRY_ROOT=# checkout реестра цепочек Rome
# Для потоков по линии Solana также требуется:
export SOLANA_KEYPAIR=# путь к JSON с финансируемой парой ключей Solana (плательщик комиссий)

Газ в цепочках Rome номинирован в USDC; полная последовательность развертывания стоит порядка 10–15 нативных единиц в devnet. Ключи берутся только из окружения — никогда из репозитория. Соберите контракты один раз перед развертыванием, потому что артефакты должны поступать из rome-contracts/out (см. шаг 3):

cd contracts       && forge build --via-ir     # вендоризированный набор Arc
cd rome-contracts  && forge build --via-ir     # ArcTokenFactoryV2 + канонический прокси

Шаг 1 — Поймите, что такое разрешённый токен есть здесь

Разрешённый токен Bloom — это не один контракт. Это три развернутых контракта, плюс четыре общих контракта, которые ops разворачивает один раз на цепочку, а каждый эмитент использует повторно.

Три контракта на каждый токен — у одного актива именно эти:

Контракт
Источник
Что это такое

ArcTokenProxy

contracts/src/proxy/ArcTokenProxy.sol

Сам токен — UUPS-прокси, указывающий на общий ArcToken реализацию. Балансы, держатели и роли находятся здесь.

WhitelistRestrictions

contracts/src/restrictions/WhitelistRestrictions.sol

Модуль allowlist. Один булев флаг на адрес; применяется при каждом переводе, пока актив находится под ограничением.

YieldBlacklistRestrictions

contracts/src/restrictions/YieldBlacklistRestrictions.sol

Модуль доходности. Исключает адреса из распределения доходности, не затрагивая их владение.

Четыре общих контракта, по одному на цепочку (развернуты deploy-infra.ts):

Контракт
Роль

RestrictionsRouter

Реестр типов модулей — цепочная настройка, выполняется ops один раз.

ArcTokenFactoryV2

Регистрация + канонический codehash прокси (шаги 2–3).

ArcToken (реализация)

Общая, многократно используемая логика актива, к которой проксирует каждый токен.

ArcTokenPurchase

Одна витрина, общая для каждого токена и эмитента (шаг 4).

wUSDC

Денежная сторона — валюта доходности и валюта продажи/покупки.

Ограничение переводов и ограничение доходности преднамеренно являются отдельными модулями: держателю может быть запрещён доход при сохранении актива, и именно так на практике работают санкции и судебные распоряжения.

Этот факт про «три контракта» критически важен для верификации. verify-deployments.ts и register-asset.ts оба ожидают, что токен будет разрешаться к трём развернутым контрактам — ручная проверка одного токена однажды пропустила семь из них в одной цепочке (все модули доходности и три модуля whitelist).

Жизненный цикл состоит из трёх фаз и одной двери только в одну сторону:

Ограничение доступно только в одну сторону для объёма, поскольку функции mint и burn используют address(0) в качестве контрагента, и address(0) никогда не может быть включён в allowlist — поэтому после введения ограничений новый объём уже невозможно создать. Именно такую гарантию разрешённый актив даёт своим держателям.


Шаг 2 — Разворачивайте поэтапно, никогда не одной транзакцией

Arc поставляет одношаговый createToken который разворачивает прокси и оба модуля и связывает их одним вызовом. В Rome использовать его нельзя. Для этой транзакции требуется 77 блокировок аккаунтов Solana, а лимит Rome на одну транзакцию составляет 62 блокировки. Оно никогда не поместится — ни при какой настройке, ни при каком проходе оптимизации.

Поэтому развертывание поэтапно: каждый контракт в отдельной транзакции, а токен получает статус, эквивалентный фабрике, через ArcTokenFactoryV2.registerToken вместо монолитного createToken. Это мастер создания, и именно так консоль эмитента выполняет процесс шаг за шагом:

мастер создания

Эталонная реализация — это arc/plan/create.ts (createSequence()), который приложение отображает как шесть карточек (bloom/lib/createCards.ts) поверх восьми транзакций, в точном порядке, который задают контракты:

#
Транзакция
Вызов контракта

1

Развернуть актив

new ArcTokenProxy(impl, initData) где initData = ArcToken.initialize(...)

2

Развернуть модуль allowlist

new WhitelistRestrictions()

3

Назначить вас его администратором

whitelist.initialize(issuer)

4

Применить это к переводам

token.setRestrictionModule(TRANSFER, whitelist)

5

Развернуть модуль доходности

new YieldBlacklistRestrictions()

6

Назначить вас его администратором

yieldBlacklist.initialize(issuer)

7

Применить это к доходности

token.setRestrictionModule(YIELD, yieldBlacklist)

8

Зарегистрировать в фабрике

factoryV2.registerToken(token, impl)

Скриптовая форма — одна команда:

Эмитент (PRIVATE_KEY) подписывает каждую транзакцию и в итоге получает роли токена (ArcToken.initialize назначает msg.sender — см. шаг 7). Регистрация (tx 8) — это то, что открывает витрине enableToken и любое обновление, выполняемое через фабрику.

Не «оптимизируйте» это обратно в монолит. Пакетирование этих вызовов в одну транзакцию ради сокращения числа обращений возвращает ровно тот overflow на 62 блокировки, которого поэтапный путь и призван избежать. Тот же лимит объясняет, почему распределение доходности проходит по одному держателю на транзакцию (шаг 8). Если вызов завершается ошибкой Too many accounts: N > 62, одна транзакция затрагивает слишком много аккаунтов — разделите её, не настраивайте.


Шаг 3 — Разворачивайте прокси только из артефактов с закреплённым происхождением

registerToken — это граница безопасности, которая делает поэтапные развертывания безопасными. Он принимает только токен, чей runtime codehash совпадает с каноническим ArcTokenProxy вшитым в фабрику на момент развертывания:

Поскольку этот codehash неизменяем, прокси, собранный из любого другого артефакта, завершится неудачей по принципу fail-closed с ProxyCodehashUnknown. Из этого следуют два правила, и оба они обеспечиваются CI и жёсткими правилами в CLAUDE.md:

  1. Прокси токенов ДОЛЖНЫ быть развернуты из rome-contracts/out — никогда из contracts/out, никогда из другой сборки. Именно эта компиляция закрепляется каноническим codehash фабрики.

  2. bytecode_hash = "none" и cbor_metadata = false в rome-contracts/foundry.toml имеют критическое значение. При включённых метаданных ArcTokenProxy runtime встроенный в фабрику (type().runtimeCode) содержит другой CBOR/IPFS-хвост, чем отдельный артефакт out/ из которого мастер выполняет развертывание — поэтому on-chain registerToken возвращает ошибку, тогда как все тесты Foundry из исходников проходят (Foundry встраивает обе копии, поэтому не видит несоответствия). rome-contracts/test/ArtifactProvenance.t.sol закрепляет это свойство; именно финансируемый прогон первоначально обнаружил проблему.

Зелёный in-source suite не доказывает происхождение. Перед выпуском образа и после ЛЮБОГО изменения настроек компилятора докажите это свойство для развернутой фабрики (только чтение, без ключей):

Он хеширует ваш локальный ArcTokenProxy артефакт и проверяет, что этот хеш дословно присутствует внутри байткода развернутой фабрики.

Если настройки компилятора необходимо изменить, ротация фабрики — разверните новую, чья immutable-переменная закрепит новый codehash, и переподключите её — вместо ручной правки проверки:

При ротации старый адрес сохраняется в квитанции; токены, зарегистрированные в старой фабрике, должны заново зарегистрироваться в новой.


Шаг 4 — Откройте продажу через общую витрину

Продажа — это отдельное действие от создания, и она выполняется через одну общую ArcTokenPurchase витрину. Перед открытием продажи должны выполняться три условия, и ArcTokenPurchase.enableToken проверяет каждое из них ончейн:

Есть и четвёртое, неявное требование, которое накладывает ограниченный актив: поскольку каждый перевод проходит через gate allowlist, перемещение запаса на витрину возможно только в том случае, если адрес витрины сам включён в whitelist вашего токена. Полная последовательность открытия продажи такова:

  1. Внести витрину в whitelist в модуле whitelist вашего токена (batchAddToWhitelist([storefront]) — см. шаг 5). Без этого перевод запаса в (2) завершится ошибкой TransferRestricted() после введения ограничений.

  2. Перевести запас на адрес витрины (из квитанции infra, arcTokenPurchase).

  3. enableToken(token, amount, price) — покупатели теперь платят wUSDC и получают RWA.

Разделение вывода стоит понимать на общей витрине, и оно несимметрично (arc/roles.ts определяет полномочия):

Действие
Полномочие
Кем удерживается

enableToken / disableToken / withdrawUnsoldArcTokens

у ADMIN_ROLE (onlyTokenAdmin)

вы, эмитент

withdrawPurchaseTokens (поступления в wUSDC)

у DEFAULT_ADMIN_ROLE

того, кто развернул витрину

В self-hosted-цепочке вы являетесь и тем, и другим. На общей витрине пул поступлений — это выручка каждого эмитента, поэтому вывод средств выполняется на уровне платформы — выстраивайте расчёты с учётом этого, а не исходя из предположения о единоличном контроле.


Шаг 5 — Подключите собственный KYC / комплаенс

Это раздел, который клиент читает перед согласием, поэтому это код, а не описание. Комплаенс обеспечивается самим контрактом токена — а не внешней проверкой, фильтром секвенсора или политикой площадки. Правила следуют за токеном по любому пути исполнения, по обеим линиям кошельков. В цепочке фиксируется результат вашего KYC-решения в виде одного булева значения:

Интерфейс, в который пишет ваш процесс

Решение вашего KYC-провайдера — одобрить или отклонить — становится ровно одним из этих вызовов:

Кто может записывать

Полномочие, необходимое для одобрения, — это MANAGER_ROLE на модуле — а не ADMIN_ROLE на токене. addToWhitelist / batchAddToWhitelist / removeFromWhitelist все onlyRole(MANAGER_ROLE), и эта роль находится на WhitelistRestrictions экземпляре. Аутентификация ADMIN_ROLE запись в токен, а затем запись в модуль — это реальный дефект, за который этот кодовой базе уже пришлось заплатить. Не предлагайте WHITELIST_ADMIN_ROLE в качестве исправления при отказе — он выдаётся при initialize и не проверяется нигде в наборе тестов (arc/roles.ts утверждает, что это единственная роль, которая ничего не ограничивает).

WhitelistRestrictions.initialize(issuer) (транзакция 3 мастера) предоставляет эмитенту DEFAULT_ADMIN_ROLE, ADMIN_ROLE, MANAGER_ROLE, WHITELIST_ADMIN_ROLE, и UPGRADER_ROLE в этом модуле. Таким образом, эмитент обладает MANAGER_ROLE из коробки и также может делегировать его: поскольку эмитент обладает DEFAULT_ADMIN_ROLE, grantRole(MANAGER_ROLE, serviceAccount) передаёт запись бэкенд-подписанту.

Решение, превращающееся в запись в блокчейне

Направьте вебхук вашего провайдера на подписанта, который обладает MANAGER_ROLE, и при получении approve пакетно обработайте адреса:

Определите whitelistModule из самого токена (ArcToken.getRestrictionModule(TRANSFER_RESTRICTION_TYPE)), а не из кэшированной проекции — нацеливание записи не в тот модуль и есть причина, по которой «approve on any asset» однажды записал в allowlist одного токена.

Вариант с подписью кошельком (демонстрация self-service)

Для тестового развёртывания без разрешений, где посетители допускают себя сами, выдайте MANAGER_ROLE в TestApprover (rome-contracts/src/TestApprover.sol) чей модуле есть неизменяем. Затем approve(address) может вызываться кем угодно из собственного кошелька, с оплатой своего газа — он вызывает addToWhitelist только если адрес ещё не в списке:

Это «ворота входа» — они показывают посетителю реальный механизм (одобрение, превращающееся в запись allowlist в блокчейне, которую затем применяет токен) без передачи чего-либо в управление. Никогда не выдавайте MANAGER_ROLE в TestApprover для производственного токена — это делает allowlist этого токена доступным без разрешений.

Когда ограничение вступает в силу и при смене провайдеров

Ограничение начинает действовать только после того, как актив ограничен (setTransfersAllowed(false), ADMIN_ROLE в модуле). Пока ограничение не включено, переводы открыты — сначала соберите allowlist, затем включите ограничение. После включения перевод, в котором хотя бы одна из сторон не в списке, откатывается с типизированной ошибкой TransferRestricted() (0xe827105e).

Поздняя смена провайдера KYC не требует изменений в блокчейне. Модуль allowlist, его интерфейс и хранимый им булев флаг не зависят от провайдера. Чтобы сменить вендора, направьте другой источник решений на тот же MANAGER_ROLE подписант — без повторного развёртывания, без миграции, без изменения состояния. Блокчейн никогда не знал, какой вендор сделал вызов, только итог.


Шаг 6 — Откройте тот же актив для кошельков Solana

Те же три контракта доступны из кошелька Solana без моста и без второго токена. У нативного пользователя Solana вообще нет EVM-ключа; вместо этого его EVM-идентичность является синтетической, полученной в блокчейне из фактического подписанта Solana в транзакции:

Программа Rome EVM выводит это из самого подписанта (do_tx_unsigned::derive_sender), поэтому это нельзя подделать, и соответствующего приватного ключа secp256k1 не существует — подпись Solana — единственное, что вообще может управлять этим адресом. Эталонная функция вывода: arc/materialise/solana/identity.ts (syntheticAddress), совместимая по байтам с правилом в блокчейне:

Что делает разработчик, чтобы поддержать этот канал — обратите внимание, что ничто из этого не требует изменений контракта:

  1. Добавьте пользователя Solana в allowlist по его синтетическому адресу. Для уровня комплаенса синтетический адрес — обычный адрес: вставьте публичный ключ Solana пользователя, выведите синтетический адрес и batchAddToWhitelist([synthetic]). Один allowlist охватывает оба мира кошельков.

  2. Подготовьте signing PDA один раз, до их первой транзакции. PDA внешнего полномочия, которое авторизует подпись синтетического адреса, должно существовать заранее, и его создание — это вызов в EVM-канале (create_pda) — пользователь только с Solana не может сделать это сам, поэтому это обеспечивает эмитент. Подготовка — это external_auth, а не ленивая инициализация.

  3. Отправляйте через библиотеку канала, а не вручную. submitDoTxUnsigned (arc/materialise/solana/submit.ts) формирует DoTxUnsigned инструкцию — неподписанный payload EIP-1559, авторизованный подписью Solana, — и обрабатывает четыре вещи, в которых вручную собранная транзакция обычно ошибается:

    • Обнаружение аккаунтов через rome_emulateCallAccounts, которая определяет записываемость каждого аккаунта. Значение value должны должно быть передано в discovery, иначе перевод value пометит PDA баланса получателя как read-only и завершится откатом в блокчейне.

    • Бюджет вычисленийDoTxUnsigned требует кадра heap на 250 КБ и 1,35 млн CU лимит (EVM Rome превышает стандартные 32 КБ / 200 K); при этом остаётся около 50 K запаса под потолком Solana в 1,4 млн.

    • PDA кошелька сокровищницы (fee), добавляемый как writable — discovery его не включает.

    • Альтернативный вариант v0 + lookup-table. Когда аккаунты вызова не помещаются в унаследованную оболочку транзакции размером 1232 байта, клиент повторно отправляет её как транзакцию v0 через новую таблицу адресов lookup. (По текущим измерениям покупка в storefront помещается в унаследованную оболочку примерно на 1 061 из 1232 байт; у держателя, для которого ещё нужно создать associated token account, лимит может быть превышен.)

Пользователь является плательщиком комиссии и платит lamports (SOL) из своего кошелька Solana; управляемый ими синтетический адрес хранит активы и никогда не хранит SOL. После каждой отправки по каналу запрашивайте EVM nonce перед следующей — индексатор немного отстаёт от подтверждения Solana.

Канал предназначен ТОЛЬКО для атомарных операций. A DoTxUnsigned — это одна транзакция EVM, выполняемая внутри одной транзакции Solana атомарной VM Rome. Итеративная VM (одна EVM-экзекуция, распределённая по нескольким транзакциям Solana) пока недоступна через этот канал. Вызов, который не помещается атомарно, не может использовать этот канал вовсе — решение состоит в меньшем вызове, а не в запасном варианте. Обратите внимание: fallback v0+ALT — это более крупная оболочка, а не другое исполнение; это всё ещё одна атомарная транзакция.

Почему RWA не может выйти за пределы периметра. Актив находится в состоянии EVM — его балансы хранятся внутри аккаунтов программы Rome EVM. Там нет SPL mint этого, и нет нативного для Solana объекта, который можно перемещать; примитивы перемещения активов в канале работают с SPL token accounts, которых у баланса в storage EVM нет. Любое перемещение, которое может выразить подпись Solana, — это вызов контракта токена, а он проходит через allowlist gate — тестовый набор подтверждает, что перевод на адрес вне allowlist откатывается одинаково, независимо от того, подписан ли он ключом EVM или Solana. Денежная часть (wUSDC) — сознательное исключение: она основана на SPL и может быть выведена на собственный token account пользователя.


Шаг 7 — Узнайте, кто обладает полномочиями после развёртывания

ArcToken.initialize выполняется из конструктора proxy (транзакция 1) и выдаёт роли msg.sender — оператору мастера, то есть эмитенту. Он выдаёт пять ролей явно:

Два последствия, которые разработчик не должен упустить:

  • MINTER_ROLE, BURNER_ROLE, и UPGRADER_ROLE НЕ выдаются при initialize. Начальный объём эмиссии минтится внутри initialize (внутренний _mint, роль не нужна), но позднее mint или burn требует, чтобы эмитент сначала выдал роль самому себе. Это возможно, поскольку у него есть DEFAULT_ADMIN_ROLE (администратор каждой роли — ничто не вызывает _setRoleAdmin, поэтому DEFAULT_ADMIN_ROLE он управляет всеми ими). Но это сознательный дополнительный шаг, а не неявная привилегия.

  • UPGRADER_ROLE никогда не выдаётся фабрике. Обновления через фабрику (ArcTokenFactoryV2.upgradeToken) требуют, чтобы сама фабрика обладала UPGRADER_ROLE на токене — выдача её самому себе ничего не даёт. Это односторонняя настройка, которую фабрика не может отменить, поэтому она включается по желанию: если вам нужны обновления через фабрику, grantRole(UPGRADER_ROLE, factory) явно вызовите; иначе эмитент обновляет токен напрямую.

Полная модель из 21 полномочия (11 имён ролей в шести контрактах — одно и то же имя означает разные полномочия в каждом контракте) зафиксирована в arc/roles.ts. Запрашивайте rolesRequiredFor(contract, functionName) вместо того чтобы читать контракт самой роли, поскольку четыре функции storefront и обе функции фабрики ограничены полномочием, которое находится в другом контракте.


Шаг 8 — Распределяйте доход

Токен выплачивает доход в wUSDC (зафиксирован в initialize, может быть изменён через setYieldToken под YIELD_MANAGER_ROLE). Распределение проходит по набору держателей:

Ключевые механики для корректного запуска:

  • Вся сумма извлекается у вызывающего только при окне startIndex == 0 окне (safeTransferFrom(msg.sender, this, totalAmount)). Предварительно одобрите эту сумму для токена до первого окна; последующие окна выплачиваются из уже имеющегося баланса.

  • nextIndex сбрасывается до 0 по завершении обхода. Повторяйте цикл distributeYieldWithLimit(total, nextIndex, …) пока nextIndex не вернётся 0.

  • Доли держателей, для которых доход ограничен, остаются в контракте токена — они пропускаются, а не перераспределяются.

В Rome практический предел составляет maxHolders = 1 за транзакцию — тот же лимит в 62 аккаунта из шага 2 — поэтому доход обходится по одному держателю за транзакцию (по измерениям около 318 K газа на держателя). Каждый держатель в allowlist, будь то EVM или нативный Solana, получает пропорционально; эталонный скрипт: measure-yield-batch.ts а шаг дохода в funded smoke проверяет это end-to-end.


Шаг 9 — Проверьте, что вы развернули

Ничто в Rome не отправляет исходники автоматически, поэтому верификацию нужно запускать вручную. После любого развёртывания — инфраструктуры или нового токена — запустите read-only, без ключей, идемпотентный верификатор (уже верифицированные контракты пропускаются, поэтому повторный запуск после выпуска токена проверит только новые):

Ожидается три наличие контрактов на токен (proxy + оба модуля) плюс инфраструктуры, и сообщает, что не удалось верифицировать, вместо того чтобы проваливать развёртывание. При ручном выполнении один раз было пропущено семь контрактов.

Регистрация актива в реестре Rome рассматривает верификацию как ворота, а не как украшение (register-asset.ts): токен получает свою apps/arc/<chain>.json запись — с standard: arc-permissioned-erc20 и transferRestriction именующую его allowlist gate — только когда все три его контракта верифицированы в Sourcify. Эта запись получает факты из цепочки (токен, развёрнутый мастером, не имеет зафиксированного receipt) и записывает только локальную копию реестра; доведение PR до мерджа — задача человека.

Для сквозного подтверждения всего цикла — создать, добавить в allowlist, включить ограничение, продать по обоим каналам, распределить доход — запустите funded smoke на любой цепочке:


Шаг 10 — Знайте, что остаётся вне блокчейна

Модель доверия намеренно прозрачна, и разработчик должен так же представлять её своим пользователям:

  • Флаг allowlist — это ваше решение вне блокчейна. KYC/AML выполняются в вашем процессе — ваши провайдеры, ваши правила. Блокчейн фиксирует и применяет только результат, isWhitelisted(addr).

  • Единственное состояние в блокчейне — один булев флаг на адрес. Никаких PII, никаких документов, никаких заявлений об идентичности, никаких аттестаций в блокчейне, никакого криптографического доказательства принадлежности адреса. Это модель Arc, используемая в Plume; она меняет более тяжёлые механизмы стандарта идентичности в блокчейне (например, ERC-3643) на более лёгкую механику и доверие, удерживаемое эмитентом.

  • Восстановление — это полномочие эмитента, а не аварийный обход. Утерянный кошелёк — EVM или Solana — восстанавливается путём добавления заменяющего адреса в allowlist и, при необходимости, использованием mint/burn/upgrade в рамках вашего юридического процесса (в Arc нет встроенного примитива принудительного перевода). Поэтому хранение ключей эмитентом является частью комплаенс-позиции.

  • Нет релея, нет поверхности хранения. Пользователи сами держат свой gas в обоих каналах. Сервис fee-payer означал бы хранение ключей — это поверхность, которую продукт RWA не должен добавлять.


Справка: инструменты

Каждый скрипт запускается из scripts/ после npm install, при этом PRIVATE_KEY, CHAIN_ID, и REGISTRY_ROOT экспортируются.

Скрипт
Что он делает

deploy-infra.ts

Однократно для каждой цепочки: четыре общих контракта, настроенные для wUSDC.

create-token.ts

Поэтапный мастер — восемь транзакций, один токен.

rotate-factory.ts

Разверните новую фабрику после изменения компилятора/артефакта; перенастройте связи.

verify-artifact-provenance.ts

Докажите, что ваш артефакт proxy принимается развёрнутой фабрикой (только чтение).

verify-deployments.ts

Верифицируйте все три контракта на токен + инфраструктуру в Sourcify (только чтение).

register-asset.ts

Сначала проверьте gate, затем подготовьте compliance-запись в реестре.

measure-yield-batch.ts

Повторно измерьте предел дохода на транзакцию в цепочке.

smoke.ts

Финансируемый end-to-end набор для обоих каналов.

sweep-synthetic-native.ts

Возвратите нативный gas с синтетического аккаунта (гигиена тестов).

Более подробный контекст находится рядом с этим руководством: docs/ARCHITECTURE.md (многоуровневая модель приложения), docs/LANES.md (два канала и хранение), docs/COMPLIANCE.md (модель доверия), и docs/USAGE.md (руководство оператора).

Последнее обновление

Это было полезно?