Смарт-контракты ATRIA: токенизация долей в объектах недвижимости (RWA).
Каркас — Foundry. Контракты вынесены в отдельный репозиторий, потому что у них свой цикл сборки, тестирования и аудита.
| Контракт | Назначение |
|---|---|
src/AtriaPropertyToken.sol |
Токен долей одного объекта. Неделимая доля, белый список, приостановка, заморозка, сжигание, принудительный перевод, приём данных об обеспечении |
src/Allowlist.sol |
Реестр разрешённых адресов. Перенесён из Tessera (chains/evm/contracts) с минимальными изменениями |
src/IdentityRegistry.sol |
Якорь слоя идентичности. Перенесён из Tessera без изменений, кроме закреплённой версии компилятора |
src/interfaces/IAllowlist.sol |
Интерфейс ограничения переводов, который запрашивает токен |
Имена функций Allowlist совпадают со значениями по умолчанию в EvmAllowlistGateway из
Tessera — настраивать шлюз на бэкенде не нужно.
Доли одного объекта живут только в одной сети. Никаких мостов, обёрнутых токенов и зеркальных выпусков: реестр держателей сверяется с состоянием сети, обеспечение одно, в пакет на регистрацию подаётся один адрес контракта, аудит оплачивается за каждый контракт отдельно.
Мультичейн реализуется на уровне выпусков: объект А может быть выпущен в одной сети, объект Б — в другой. Первый выпуск делается на BNB Chain.
Поэтому адрес контракта хранится на объекте (Property.TokenContractAddress через
Property.SetTokenContract в бэкенде), а не в конфигурации приложения. В этом репозитории ведётся
только справочный перечень развёрнутых адресов: deployments/README.md.
Один владелец на все действия недопустим: компрометация единственного ключа даёт возможность и выпустить доли, и списать их у держателей.
| Роль | Кто держит ключ | Что может |
|---|---|---|
DEFAULT_ADMIN_ROLE |
мультисиг | управление ролями, замена адреса белого списка, уменьшение размера выпуска |
MINTER_ROLE |
кастоди / операционный ключ выпуска | выпуск долей на адрес инвестора |
COMPLIANCE_ROLE |
комплаенс | заморозка и разморозка, сжигание, принудительный перевод |
PAUSER_ROLE |
отдельный ключ | приостановка и возобновление операций |
ORACLE_ROLE |
оракул обеспечения | передача верифицированных данных об обеспечении |
Действия комплаенса намеренно работают при приостановке и по замороженным адресам: предписание регулятора приходит именно в таком состоянии. Каждое такое действие требует роли и записывает код основания в событие.
| Что | Зачем |
|---|---|
decimals = 0 |
доля неделима, минимальная покупка задаётся в штуках |
Жёсткий потолок maxSupply |
количество долей должно точно соответствовать зарегистрированному выпуску |
reduceMaxSupply |
аннулирование части выпуска (глава 11 проекта Указа) |
| Приостановка и возобновление | требование проекта Указа, глава 8 |
| Заморозка и разморозка адреса | блокировка отдельного держателя |
| Сжигание, включая частичное и принудительное | возврат при отказе в течение 14 дней (пункт 44), погашение, аннулирование, изъятие из обращения (пункт 73) |
| Принудительный перевод | исполнение судебных решений и обращение взыскания |
| Разделение ролей вместо одного владельца | компрометация одного ключа не даёт полного контроля |
reportCollateral |
передача верифицированных данных об обеспечении в контракт (пункт 16) |
Сохранено из референса: проверка белого списка при переводе с обеих сторон и при минте.
forge install # зависимости (forge-std, openzeppelin-contracts)
forge build
forge test -vvv
forge fmt --checkСборка и прогон тестов идут в CI: .github/workflows/ci.yml.
Пошаговый порядок: docs/deployment-runbook.md.
Пакет и периметр аудита: docs/audit.md.
Параметры вынесены в переменные окружения, приватные ключи в репозиторий не попадают — см.
.env.example. .env в .gitignore.
Для боевой сети ключ подписи берётся из keystore или аппаратного кошелька, а не из переменной:
cast wallet import atria-deployer --interactive # один раз
# тестовая сеть BNB (chain id 97)
forge script script/Deploy.s.sol:Deploy \
--rpc-url bsc_testnet --account atria-deployer --broadcast --verify
# боевая сеть BNB (chain id 56)
forge script script/Deploy.s.sol:Deploy \
--rpc-url bsc --account atria-deployer --broadcast --verifyСкрипт разворачивает IdentityRegistry, Allowlist и токен, выдаёт роли ключам из .env,
передаёт DEFAULT_ADMIN_ROLE мультисигу и отзывает права у деплойера. Владение белым списком
переходит мультисигу, агентом остаётся сервисный ключ бэкенда.
После развёртывания раскладка ключей проверяется по состоянию сети, а не по логу скрипта:
TOKEN_ADDRESS=0x... DEPLOYER_ADDRESS=0x... \
forge script script/CheckDeployment.s.sol:CheckDeployment --rpc-url bsc_testnetАдреса из вывода скрипта заносятся в объект через Property.SetTokenContract и в
deployments/README.md.
- Контракт дорабатывается до развёртывания. Исправить развёрнутый контракт нельзя — потребуется новый контракт и перенос держателей.
- Развёртывание в тестовой сети BNB.
- Внешний аудит — входит в пакет документов на государственную регистрацию выпуска, время и бюджет закладываются заранее.
- Только после этого боевое развёртывание и минт.