Разработка системы сегрегации активов для кастодиана

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка системы сегрегации активов для кастодиана
Сложная
~1-2 недели
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1258
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1170
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    873
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1092
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    563
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    830

Разработка системы сегрегации активов для кастодиана

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

Регуляторный контекст

Требования к сегрегации активов определяются юрисдикцией. MiCA (EU) требует отделения клиентских активов от собственных. FCA (UK) — аналогично. SEC для крипто-кастодианов в США — пока в разработке, но NYDFS BitLicense уже содержит требования к сегрегации.

Ключевое требование: возможность аудита. Аудитор в любой момент должен иметь возможность сопоставить on-chain адреса с записями о клиентах и подтвердить, что активы клиента A не перемешаны с активами клиента B.

Архитектурные модели сегрегации

Один адрес на клиента (Full Segregation)

Каждый клиент получает уникальный on-chain адрес (или набор адресов — по одному на каждый поддерживаемый blockchain). Активы физически разделены на уровне блокчейна.

Преимущества:

  • Максимальная прозрачность для клиента и аудитора
  • Простое доказательство права собственности
  • Изоляция рисков: проблема одного клиента не затрагивает других

Недостатки:

  • Высокие operational costs при большом числе клиентов (тысячи адресов, отдельные gas пополнения для каждого)
  • Сложнее оптимизировать ликвидность

Виртуальная сегрегация с общим пулом

Активы хранятся на общих адресах, но внутренняя база данных ведёт точный учёт доли каждого клиента. Аналог: банковский счёт (вы не знаете в каком физическом хранилище лежат ваши деньги).

Преимущества:

  • Низкие operational costs
  • Проще управлять ликвидностью

Недостатки:

  • Регуляторно сложнее обосновать как «сегрегацию»
  • При банкротстве кастодиана — активы клиентов могут быть оспорены кредиторами

Гибридная модель

Для крупных клиентов (институты) — выделенные адреса. Для розничных — виртуальная сегрегация с возможностью перевода на dedicated address по запросу.

Детальная архитектура системы

Управление адресами

Ключи хранятся в HSM. Адреса генерируются детерминированно через HD-derivation:

m/44'/60'/{clientId}'/0/0 → основной адрес клиента
m/44'/60'/{clientId}'/0/1 → адрес для конкретного актива
m/44'/60'/{clientId}'/1/0 → change адрес

Это позволяет восстановить все адреса из master seed без дополнительного хранилища.

interface ClientWallet {
  clientId: string;
  blockchain: string;
  address: string;
  derivationPath: string;
  createdAt: Date;
  keyStorageLocation: 'hsm_slot_1' | 'hsm_slot_2'; // для geo-redundancy
}

class AddressManager {
  async createClientAddress(
    clientId: string,
    blockchain: string
  ): Promise<ClientWallet> {
    // Атомарная операция: проверяем что адрес ещё не создан
    return this.db.transaction(async (trx) => {
      const existing = await trx('client_wallets')
        .where({ clientId, blockchain })
        .first();
      
      if (existing) return existing;
      
      const index = await this.getNextIndex(trx, blockchain);
      const derivationPath = `m/44'/60'/${clientId}'/0/${index}`;
      const address = await this.hsm.deriveAddress(derivationPath);
      
      return trx('client_wallets').insert({
        clientId,
        blockchain,
        address,
        derivationPath,
        createdAt: new Date(),
      }).returning('*');
    });
  }
}

Бухгалтерский учёт (Ledger)

Двойная запись обязательна. Каждое движение активов должно балансироваться:

CREATE TABLE ledger_entries (
    id BIGSERIAL PRIMARY KEY,
    entry_type VARCHAR(32) NOT NULL, -- debit/credit
    client_id UUID NOT NULL REFERENCES clients(id),
    asset VARCHAR(64) NOT NULL,    -- ETH, USDC, BTC
    blockchain VARCHAR(32) NOT NULL,
    amount NUMERIC(36, 18) NOT NULL CHECK (amount > 0),
    balance_after NUMERIC(36, 18) NOT NULL,
    reference_type VARCHAR(32), -- deposit, withdrawal, fee, transfer
    reference_id UUID,
    tx_hash VARCHAR(66),
    block_number BIGINT,
    created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    created_by VARCHAR(64) NOT NULL, -- system, user_id
    CONSTRAINT no_negative_balance CHECK (balance_after >= 0)
);

CREATE TABLE client_balances (
    client_id UUID REFERENCES clients(id),
    asset VARCHAR(64),
    blockchain VARCHAR(32),
    balance NUMERIC(36, 18) NOT NULL DEFAULT 0,
    last_updated_at TIMESTAMPTZ DEFAULT NOW(),
    PRIMARY KEY (client_id, asset, blockchain)
);

Reconciliation. Ежедневно система должна сверять on-chain балансы с записями в ledger:

async function reconcile(blockchain: string, asset: string): Promise<ReconciliationResult> {
  const clientWallets = await db.clientWallets.findAll({ blockchain });
  
  const results = await Promise.all(
    clientWallets.map(async (wallet) => {
      const onChainBalance = await getOnChainBalance(wallet.address, asset);
      const ledgerBalance = await db.clientBalances.getBalance(
        wallet.clientId, asset, blockchain
      );
      
      const discrepancy = onChainBalance - ledgerBalance;
      
      return {
        clientId: wallet.clientId,
        address: wallet.address,
        onChainBalance,
        ledgerBalance,
        discrepancy,
        status: Math.abs(discrepancy) < TOLERANCE ? 'ok' : 'mismatch',
      };
    })
  );
  
  const mismatches = results.filter(r => r.status === 'mismatch');
  if (mismatches.length > 0) {
    await this.alertService.sendAlert('RECONCILIATION_MISMATCH', mismatches);
  }
  
  return { results, mismatches, timestamp: new Date() };
}

Мониторинг входящих депозитов

Система должна отслеживать все входящие транзакции на адреса клиентов и автоматически зачислять:

class DepositMonitor {
  async watchAddress(address: string, clientId: string) {
    // Подписка на новые блоки через WebSocket
    this.provider.on('block', async (blockNumber) => {
      const block = await this.provider.getBlock(blockNumber, true);
      
      for (const tx of block.transactions) {
        if (tx.to?.toLowerCase() === address.toLowerCase()) {
          await this.processDeposit({
            clientId,
            txHash: tx.hash,
            amount: tx.value,
            asset: 'ETH',
            blockNumber,
          });
        }
      }
    });
    
    // Также отслеживаем ERC-20 Transfer события
    this.monitorERC20Transfers(address, clientId);
  }
  
  private async processDeposit(deposit: DepositEvent) {
    // Ждём confirmations (обычно 12-20 для finality)
    await this.waitForConfirmations(deposit.txHash, REQUIRED_CONFIRMATIONS);
    
    await this.db.transaction(async (trx) => {
      // Проверяем идемпотентность
      const existing = await trx('deposits').where({ txHash: deposit.txHash }).first();
      if (existing) return;
      
      // Записываем депозит
      await trx('deposits').insert(deposit);
      
      // Обновляем ledger
      await this.ledger.credit(trx, deposit.clientId, deposit.asset, deposit.amount);
    });
  }
}

Вывод средств (Withdrawal)

Вывод всегда требует approval workflow (см. multi-approval систему). После approval:

  1. Проверка баланса клиента в ledger
  2. Резервирование средств (debit pending)
  3. Подпись транзакции в HSM
  4. Broadcast on-chain
  5. Ожидание confirmations
  6. Финальное списание из ledger (или reversal при failure)

Idempotency. Каждый withdrawal request имеет уникальный idempotency key. Повторный запрос с тем же ключом возвращает статус существующего, не создаёт новый.

Proof of Reserves

Для публичного подтверждения платёжеспособности — Merkle tree на основе client balances:

// Каждый клиент получает proof что его баланс включён в общее дерево
// Без раскрытия данных других клиентов
async function generateProofOfReserves(): Promise<ProofOfReserves> {
  const balances = await db.getAllClientBalances();
  
  // Строим Merkle tree
  const leaves = balances.map(b => 
    keccak256(encode(['address', 'uint256'], [b.address, b.balance]))
  );
  
  const tree = new MerkleTree(leaves, keccak256, { sort: true });
  
  // Публикуем root on-chain
  await proofOfReservesContract.updateRoot(tree.getRoot());
  
  return {
    root: tree.getRoot(),
    totalBalance: balances.reduce((sum, b) => sum + b.balance, 0n),
    timestamp: Date.now(),
    proofs: balances.map((b, i) => ({
      clientId: b.clientId,
      proof: tree.getProof(leaves[i]),
    })),
  };
}

Compliance и аудит

Audit trail. Все операции с неизменяемой историей. Логи хранятся в append-only хранилище (AWS QLDB или PostgreSQL с audit triggers).

Reporting. Ежемесячные отчёты для каждого клиента: движение средств, комиссии, текущие балансы. Ежеквартальные для аудиторов: reconciliation reports, proof of reserves.

KYT (Know Your Transaction). Интеграция с Chainalysis, Elliptic или TRM Labs для проверки входящих транзакций на связь с санкционными адресами и mixer-ами.

Стек

Компонент Технология
HSM AWS CloudHSM или Thales
Database PostgreSQL + AWS QLDB (audit log)
Blockchain monitoring Alchemy/Infura + собственный indexer
Reconciliation Cron job + alerting
KYT Chainalysis Reactor API
API Node.js + TypeScript, REST + gRPC
Frontend React (admin dashboard)

Сроки

  • Core ledger + address management: 6-8 недель
  • Deposit monitoring + withdrawal flow: 4-6 недель
  • Reconciliation + proof of reserves: 3-4 недели
  • KYT интеграция + compliance reporting: 3-4 недели
  • Security audit: обязателен, +4-8 недель

Итого: 5-6 месяцев до production-ready системы.