Разработка платформы токенизации активов
Токенизация актива — это представление права собственности или доли в реальном активе в виде токена на блокчейне. Звучит концептуально, но за этим стоит конкретный набор юридических и технических проблем, которые нужно решить последовательно. Технология — меньшая часть задачи. Юридическая обёртка, compliance, KYC/AML, вторичное обращение в рамках регуляторики — это 60–70% работы на любом серьёзном проекте токенизации.
Типы активов разные и требуют разных подходов: недвижимость, акции SPV, долговые инструменты, произведения искусства, интеллектуальная собственность, товарные запасы. Но базовые компоненты платформы — общие.
Стандарты токенов для RWA
Обычный ERC-20 не подходит для регулируемых активов. Нужны:
ERC-1400 (Security Token Standard) — расширение ERC-20 с transfer restrictions, forced transfers, document management. Разработан под требования securities регуляторов. Поддерживает partitions (транши с разными правами):
// ERC-1400 ключевые интерфейсы
interface IERC1400 is IERC20 {
// Проверка можно ли выполнить transfer (возвращает статус код + reason)
function canTransferByPartition(
bytes32 partition,
address from,
address to,
uint256 value,
bytes calldata data
) external view returns (byte, bytes32, bytes32);
// Transfer с данными (для compliance metadata)
function transferByPartition(
bytes32 partition,
address to,
uint256 value,
bytes calldata data
) external returns (bytes32);
// Принудительный transfer (для регулятора или судебного решения)
function operatorTransferByPartition(
bytes32 partition,
address from,
address to,
uint256 value,
bytes calldata data,
bytes calldata operatorData
) external returns (bytes32);
// Документы привязанные к токену (проспект, аудит, legal)
function getDocument(bytes32 name)
external view returns (string memory, bytes32);
}
ERC-3643 (T-REX: Token for Regulated EXchanges) — более современный стандарт, разработан Tokeny Solutions и принят как основа многими платформами (Société Générale Forge, ABN AMRO). Включает identity layer (ONCHAINID) и automated compliance checks:
// T-REX compliance check пример
contract TokenCompliance {
IIdentityRegistry public identityRegistry;
ICompliance public compliance;
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal {
if (from != address(0) && to != address(0)) {
// Проверяем identity получателя
require(
identityRegistry.isVerified(to),
"Recipient identity not verified"
);
// Проверяем compliance правила
require(
compliance.canTransfer(from, to, amount),
"Transfer not compliant"
);
}
}
}
ERC-1155 для фракционных активов — когда один актив делится на несколько видов прав (например, здание с разными типами помещений или произведение искусства с разными правами использования).
Identity Layer: KYC/AML on-chain
Каждый держатель токенов регулируемого актива должен быть верифицирован. On-chain identity — сложнее чем просто mapping адрес → bool.
ONCHAINID (ERC-734/735)
Стандарт для decentralized identity, совместимый с T-REX:
// Identity контракт (один на пользователя)
interface IIdentity {
// Claims — верифицированные утверждения от claim issuers
function getClaim(bytes32 claimId)
external view returns (
uint256 topic, // тип клейма: KYC, AML, accredited investor
uint256 scheme, // метод верификации
address issuer,
bytes memory signature,
bytes memory data,
string memory uri
);
function addClaim(
uint256 topic,
uint256 scheme,
address issuer,
bytes memory signature,
bytes memory data,
string memory uri
) external returns (bytes32 claimId);
}
// Claim Topics для securities
uint256 constant KYC_CLAIM = 1;
uint256 constant AML_CLAIM = 2;
uint256 constant ACCREDITED_INVESTOR_CLAIM = 3;
uint256 constant COUNTRY_CLAIM = 4;
uint256 constant PROFESSIONAL_INVESTOR_CLAIM = 5;
Провайдер KYC (Sumsub, Fractal, Identix) проводит верификацию, выдаёт claim с подписью. Claim записывается в ONCHAINID контракт пользователя. При попытке transfer токена — compliance модуль проверяет наличие нужных claims.
Ограничения по юрисдикции
Регуляторы требуют ограничить продажу в определённых юрисдикциях (например, нельзя продавать US-резидентам без регистрации в SEC):
contract CountryRestrictionsCompliance {
// Разрешённые коды стран (ISO 3166-1 numeric)
mapping(uint16 => bool) public allowedCountries;
// Ограничения владения для каждой страны
mapping(uint16 => uint256) public countryMaxInvestors;
mapping(uint16 => uint256) public countryCurrentInvestors;
function canTransfer(
address from,
address to,
uint256 amount
) external view returns (bool) {
uint16 recipientCountry = getInvestorCountry(to);
if (!allowedCountries[recipientCountry]) {
return false;
}
// Не превышаем лимит инвесторов в стране
if (isNewInvestor(to, recipientCountry)) {
if (countryCurrentInvestors[recipientCountry] >=
countryMaxInvestors[recipientCountry]) {
return false;
}
}
return true;
}
}
Lifecycle токенизированного актива
Issuance (эмиссия)
Перед минтингом токенов:
- Юридическая структура: SPV, траст или другая структура, которая держит реальный актив
- Legal opinion что токены не являются незарегистрированными securities (или регистрация)
- Проспект/offering memorandum (зависит от юрисдикции и объёма)
- Custody arrangement: кто держит документы, кто является transfer agent
function mintSecurityTokens(
address investor,
uint256 amount,
bytes32 partition, // например: "CLASS_A_SHARES"
bytes calldata data // reference к legal document hash
) external onlyRole(ISSUER_ROLE) {
require(identityRegistry.isVerified(investor), "Not verified");
require(compliance.canTransfer(address(0), investor, amount), "Not compliant");
_issueByPartition(partition, investor, amount, data);
emit TokensIssued(investor, amount, partition, data);
}
Corporate Actions
Токенизированные акции требуют обработки корпоративных событий:
Дивиденды:
contract DividendDistributor {
IERC1400 public securityToken;
IERC20 public paymentToken; // USDC обычно
function distributeDividends(
uint256 totalDividend,
uint256 snapshotId
) external onlyRole(CORPORATE_ACTIONS_ROLE) {
uint256 totalSupplyAtSnapshot = securityToken.totalSupplyAt(snapshotId);
// Каждый держатель получает пропорционально
// Используем snapshot для точного расчёта (ERC20Snapshot или ERC20Votes)
uint256 dividendPerToken = totalDividend * 1e18 / totalSupplyAtSnapshot;
// Сохраняем snapshot dividend для клэйма
dividendSnapshots[snapshotId] = DividendSnapshot({
totalDividend: totalDividend,
dividendPerToken: dividendPerToken,
paymentToken: address(paymentToken),
snapshotBlock: block.number
});
}
function claimDividend(uint256 snapshotId) external {
uint256 balance = securityToken.balanceOfAt(msg.sender, snapshotId);
require(balance > 0, "No balance at snapshot");
require(!claimed[msg.sender][snapshotId], "Already claimed");
claimed[msg.sender][snapshotId] = true;
uint256 amount = balance * dividendSnapshots[snapshotId].dividendPerToken / 1e18;
paymentToken.safeTransfer(msg.sender, amount);
}
}
Сплиты и обратные сплиты:
function executeSplit(uint256 splitRatio) external onlyRole(CORPORATE_ACTIONS_ROLE) {
// splitRatio = 200 означает 2:1 сплит (каждый токен → 2 токена)
// splitRatio = 50 означает 1:2 обратный сплит
address[] memory holders = getAllHolders(); // ведётся отдельно через события
for (uint i = 0; i < holders.length; i++) {
uint256 currentBalance = balanceOf(holders[i]);
if (splitRatio > 100) {
// Прямой сплит: минтим дополнительные токены
_mint(holders[i], currentBalance * (splitRatio - 100) / 100);
} else {
// Обратный сплит: сжигаем
_burn(holders[i], currentBalance * (100 - splitRatio) / 100);
}
}
emit SplitExecuted(splitRatio, block.timestamp);
}
Вторичный рынок и ликвидность
Вторичное обращение токенизированных активов — отдельная проблема. В отличие от обычных ERC-20, нельзя просто листинговать на Uniswap: каждый buyer должен пройти KYC, покупка должна проходить compliance проверку.
Permissioned DEX — кастомный AMM или order book с встроенным compliance gate:
contract ComplianceAwareOrderBook {
ICompliance public compliance;
struct Order {
address seller;
uint256 amount;
uint256 pricePerToken; // в USDC wei
bool isActive;
}
mapping(uint256 => Order) public orders;
function fillOrder(uint256 orderId, uint256 amount) external nonReentrant {
Order storage order = orders[orderId];
require(order.isActive, "Order not active");
// Compliance check ПЕРЕД любыми transfers
require(
compliance.canTransfer(order.seller, msg.sender, amount),
"Transfer not compliant"
);
uint256 cost = amount * order.pricePerToken / 1e18;
// Atomic swap
paymentToken.safeTransferFrom(msg.sender, order.seller, cost);
securityToken.operatorTransferByPartition(
"DEFAULT",
order.seller,
msg.sender,
amount,
"",
""
);
emit OrderFilled(orderId, msg.sender, amount, cost);
}
}
Интеграция с регулируемыми платформами — INX, tZERO, STO Global X принимают токены в стандарте T-REX. Это готовая ликвидность для эмитентов без построения собственной торговой площадки.
Оракулы и оценка активов
Для займов под залог токенизированных активов нужна on-chain цена. В отличие от криптоактивов — нет ликвидного рынка. Решения:
Verified appraiser model — аккредитованный оценщик подписывает оценку, публикует on-chain. Контракт принимает оценки от N аккредитованных оценщиков, берёт медиану:
contract AssetValuationOracle {
struct Valuation {
uint256 value; // в USD, 8 decimals
uint256 timestamp;
address appraiser;
bytes signature;
}
mapping(bytes32 => Valuation[]) public valuations; // assetId → valuations
uint256 public constant MAX_VALUATION_AGE = 90 days;
uint256 public constant MIN_APPRAISERS = 2;
function getAssetValue(bytes32 assetId) external view returns (uint256) {
Valuation[] storage vals = valuations[assetId];
// Фильтруем актуальные оценки
uint256[] memory freshValues = new uint256[](vals.length);
uint256 freshCount = 0;
for (uint i = 0; i < vals.length; i++) {
if (block.timestamp - vals[i].timestamp <= MAX_VALUATION_AGE) {
freshValues[freshCount++] = vals[i].value;
}
}
require(freshCount >= MIN_APPRAISERS, "Insufficient fresh valuations");
return median(freshValues, freshCount);
}
}
Технологический стек
| Компонент | Выбор | Обоснование |
|---|---|---|
| Token standard | ERC-3643 (T-REX) | Широкое принятие в RWA, compliance built-in |
| Identity | ONCHAINID | Стандарт экосистемы T-REX |
| KYC provider | Sumsub / Synaps | API + claim issuance |
| Settlement chain | Polygon PoS / Base | Дёшево, EVM, активная RWA экосистема |
| Payment | USDC / EURC | Circle стабильность, regulatory clarity |
| Document storage | IPFS + Filecoin | Долгосрочное хранение юридических документов |
Этапы проекта
| Фаза | Содержание | Срок |
|---|---|---|
| Legal & structure | Юридическая структура, compliance requirements | 4–8 нед |
| Core contracts | ERC-3643 + identity + compliance модули | 4–6 нед |
| Corporate actions | Dividends, splits, forced transfer | 2–3 нед |
| KYC integration | Identity registry + KYC provider API | 2–3 нед |
| Secondary market | Order book или DEX с compliance | 3–4 нед |
| Investor portal | Dashboard, claims, documents | 3–4 нед |
| Audit | Контракты | 3–4 нед |
| Issuance pilot | Реальный актив в тестовой среде | 2–3 нед |
Итого: 23–35 недель. Юридический этап — переменная с наибольшим разбросом: зависит от актива, юрисдикции и наличия опытного securities-lawyer в команде клиента.







