Создание в 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:
Прокси токенов ДОЛЖНЫ быть развернуты из
rome-contracts/out— никогда изcontracts/out, никогда из другой сборки. Именно эта компиляция закрепляется каноническим codehash фабрики.bytecode_hash = "none"иcbor_metadata = falseвrome-contracts/foundry.tomlимеют критическое значение. При включённых метаданныхArcTokenProxyruntime встроенный в фабрику (type().runtimeCode) содержит другой CBOR/IPFS-хвост, чем отдельный артефактout/из которого мастер выполняет развертывание — поэтому on-chainregisterTokenвозвращает ошибку, тогда как все тесты Foundry из исходников проходят (Foundry встраивает обе копии, поэтому не видит несоответствия).rome-contracts/test/ArtifactProvenance.t.solзакрепляет это свойство; именно финансируемый прогон первоначально обнаружил проблему.
Зелёный in-source suite не доказывает происхождение. Перед выпуском образа и после ЛЮБОГО изменения настроек компилятора докажите это свойство для развернутой фабрики (только чтение, без ключей):
Он хеширует ваш локальный
ArcTokenProxyартефакт и проверяет, что этот хеш дословно присутствует внутри байткода развернутой фабрики.
Если настройки компилятора необходимо изменить, ротация фабрики — разверните новую, чья immutable-переменная закрепит новый codehash, и переподключите её — вместо ручной правки проверки:
При ротации старый адрес сохраняется в квитанции; токены, зарегистрированные в старой фабрике, должны заново зарегистрироваться в новой.
Шаг 4 — Откройте продажу через общую витрину
Продажа — это отдельное действие от создания, и она выполняется через одну общую ArcTokenPurchase витрину. Перед открытием продажи должны выполняться три условия, и ArcTokenPurchase.enableToken проверяет каждое из них ончейн:
Есть и четвёртое, неявное требование, которое накладывает ограниченный актив: поскольку каждый перевод проходит через gate allowlist, перемещение запаса на витрину возможно только в том случае, если адрес витрины сам включён в whitelist вашего токена. Полная последовательность открытия продажи такова:
Внести витрину в whitelist в модуле whitelist вашего токена (
batchAddToWhitelist([storefront])— см. шаг 5). Без этого перевод запаса в (2) завершится ошибкойTransferRestricted()после введения ограничений.Перевести запас на адрес витрины (из квитанции infra,
arcTokenPurchase).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), совместимая по байтам с правилом в блокчейне:
Что делает разработчик, чтобы поддержать этот канал — обратите внимание, что ничто из этого не требует изменений контракта:
Добавьте пользователя Solana в allowlist по его синтетическому адресу. Для уровня комплаенса синтетический адрес — обычный адрес: вставьте публичный ключ Solana пользователя, выведите синтетический адрес и
batchAddToWhitelist([synthetic]). Один allowlist охватывает оба мира кошельков.Подготовьте signing PDA один раз, до их первой транзакции. PDA внешнего полномочия, которое авторизует подпись синтетического адреса, должно существовать заранее, и его создание — это вызов в EVM-канале (
create_pda) — пользователь только с Solana не может сделать это сам, поэтому это обеспечивает эмитент. Подготовка — этоexternal_auth, а не ленивая инициализация.Отправляйте через библиотеку канала, а не вручную.
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 (руководство оператора).
Последнее обновление
Это было полезно?