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
IVaultRegistrarinterface used throughout this guide is being standardized — see the ERC discussion at Vault Registrar Interface for Permissioned ERC-20 Vaults.
Roles
| Role | Address type | What it does |
|---|---|---|
| Investor | EOA or contract wallet | Owns the DS position. Signs the EIP-712 standing permission once. |
| Operator | Contract address | Holds OPERATOR_ROLE on VaultRegistrar. Calls registerVault(). Usually your vault factory or protocol entrypoint. |
| Vault | Contract address | Per-investor custody bucket. Free-form contract; the registrar only stores its address. |
| Faucet operator | EOA | Holds DST and submits requestTokens() calls on behalf of requesters. |
| Registrar admin | EOA | Holds 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.
| Capability | Status |
|---|---|
| Faucet drip (DST) | Fully implemented in bc-labs-gw and bc-securitize-faucet-sc |
| Auto-registration of new wallets | Implemented inside Faucet.requestTokens() |
| Investor EIP-712 signing UI | Implemented in bc-partners-sandbox-fe (/mock-protocol route) |
registerVault() direct call | Implemented in bc-vault-registrar |
| Vault deployment | Your responsibility — there is no on-chain vault factory shipped |
| Token movement into the vault | Your 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
- Get DS Tokens — request DST from the faucet.
- Register Operator — distinguish the contract operator from the gateway service account, and grant
OPERATOR_ROLE. - Deploy Vault — pick the deployment pattern that fits your protocol shape.
- Register Vault — sign the EIP-712 permission and call
registerVault(). - Transfer Tokens — move DST into the vault (and why this fails before step 4).
- Protocol Interaction — your strategy logic, plus how to gate downstream contracts on
isRegistered(). - 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 oninvalidateOperatorPermission(operator)from the investor side.