Skip to main content

Integration Guide

This guide walks an operator through the full on-ramp / off-ramp lifecycle on testnet using the testnet DS Token and the VaultRegistrar contract as the DS registry bridge.

It is opinionated: the goal is for a developer with a fresh repo to go from "no testnet tokens" to "vault registered, DS in custody, protocol logic exercised, tokens returned to the investor" without any tribal knowledge.

:::tip Validate before you build Before working through this guide, consider running the full flow in the sandbox UI first — no scripts required. See the Quick Start for a 5-minute browser-based walkthrough using the Faucet, Mock Protocol Example, and Protocol Tester pages. :::

The IVaultRegistrar interface used throughout this guide is being standardized — see the ERC discussion at Vault Registrar Interface for Permissioned ERC-20 Vaults.

Roles

RoleAddress typeWhat it does
InvestorEOA or contract walletOwns the DS position. Signs the EIP-712 standing permission once.
OperatorContract addressHolds OPERATOR_ROLE on VaultRegistrar. Calls registerVault(). Usually your vault factory or protocol entrypoint.
VaultContract addressPer-investor custody bucket. Free-form contract; the registrar only stores its address.
Faucet operatorEOAHolds DST and submits requestTokens() calls on behalf of requesters.
Registrar adminEOAHolds DEFAULT_ADMIN_ROLE on VaultRegistrar. Grants/revokes operator role.

Lifecycle at a glance

┌──────────────────┐
│ 1. Faucet drip │ POST /api/v1/drip → DST sent to investor wallet
│ (auto-registers │ Investor wallet now resolves to a DS investor ID
│ the wallet) │
└────────┬─────────┘


┌──────────────────┐
│ 2. Operator role │ Admin calls vaultRegistrar.addOperator(yourFactory)
│ granted │ Skip this step if going through the gateway
└────────┬─────────┘


┌──────────────────┐
│ 3. Vault deployed│ Inline (factory creates on first deposit)
│ │ OR pre-deployed standalone
└────────┬─────────┘


┌──────────────────┐
│ 4. EIP-712 signed│ Investor signs RegisterVault typed-data
│ + registered │ Operator submits registerVault(vault, investor, ...)
└────────┬─────────┘


┌──────────────────┐
│ 5. DST moved into│ approve() → transferFrom into the vault
│ the vault │ Vault transfer only succeeds because the vault is
│ │ now bound to the investor in the DS registry
└────────┬─────────┘


┌──────────────────┐
│ 6. Protocol logic│ Strategy uses DST
└────────┬─────────┘


┌──────────────────┐
│ 7. Off-ramp │ Withdraw to investor + (optional)
│ │ invalidateOperatorPermission(operator)
└──────────────────┘

Reality check: what the repos actually implement

Before you start, know which seams are real and which are still your responsibility.

CapabilityStatus
Faucet drip (DST)Fully implemented in bc-labs-gw and bc-securitize-faucet-sc
Auto-registration of new walletsImplemented inside Faucet.requestTokens()
Investor EIP-712 signing UIImplemented in bc-partners-sandbox-fe (/mock-protocol route)
registerVault() direct callImplemented in bc-vault-registrar
Vault deploymentYour responsibility — there is no on-chain vault factory shipped
Token movement into the vaultYour responsibility — the sandbox Sign → Approve → Deposit flow calls MockDeFiProtocol.deposit() directly on-chain
unregisterVault()Defined in IVaultRegistrar but reverts with NotImplemented() — off-ramp is protocol-level only

The seven steps

  1. Get DS Tokens — request DST from the faucet.
  2. Register Operator — distinguish the contract operator from the gateway service account, and grant OPERATOR_ROLE.
  3. Deploy Vault — pick the deployment pattern that fits your protocol shape.
  4. Register Vault — sign the EIP-712 permission and call registerVault().
  5. Transfer Tokens — move DST into the vault (and why this fails before step 4).
  6. Protocol Interaction — your strategy logic, plus how to gate downstream contracts on isRegistered().
  7. Return Tokens — the off-ramp and standing-permission revocation.

Glossary

  • Standing permission — A single EIP-712 signature that authorizes the operator to register any number of vaults under the investor until the deadline passes or the investor revokes. Successful registerVault() calls do not consume the nonce.
  • DS Registry Service — The Securitize on-chain registry that maps wallet addresses to investor IDs. Discovered via IDSToken(token).getDSService(4).
  • Investor ID — Opaque string identifier for an investor in the DS Registry. Two wallets are "the same investor" iff getInvestor(walletA) == getInvestor(walletB) and both are non-empty.
  • Operator nonce — Per-pair counter operatorNonce(investor, operator) that only increments on invalidateOperatorPermission(operator) from the investor side.