Mock Protocol Reference
MockDeFiProtocol is the reference implementation deployed in this sandbox. It shows the minimal contract shape needed to integrate DS Token with VaultRegistrar: one vault per investor, created on first deposit, registered with an EIP-712 signature in the same transaction.
Use it as a starting point when designing your own protocol contract.
What it does
- Deploys a per-investor vault on first
deposit()call. - Calls
VaultRegistrar.registerVault()with the investor's EIP-712 signature in the same transaction. - Pulls DS Tokens from the investor's wallet into the vault via
transferFrom. - Emits
VaultCreatedandDepositevents. - Provides
withdraw(amount)to return tokens to the investor. - Provides
clearVault(investor)andclearMyVault()as admin escape hatches.
Interface
// Constructor
constructor(address _vaultRegistrar, address _dsToken)
// Core flow
function deposit(uint256 amount, uint256 deadline, bytes calldata signature) external
// Off-ramp
function withdraw(uint256 amount) external
// Admin escape hatches
function clearVault(address investor) external
function clearMyVault() external
// View
function investorVaults(address investor) external view returns (address vault)
function dsToken() external view returns (address)
function vaultRegistrar() external view returns (address)
Events
event VaultCreated(address indexed investor, address indexed vault)
event Deposit(address indexed investor, address indexed vault, uint256 amount)
event Withdraw(address indexed investor, address indexed vault, uint256 amount)
How deposit() works
investor wallet
│
│ 1. signTypedData(RegisterVault { investor, operator: MockDeFiProtocol, ... })
│
▼
MockDeFiProtocol.deposit(amount, deadline, signature)
│
├─ 2. Deploy MockVault for investor (if not already deployed)
│ emit VaultCreated(investor, vault)
│
├─ 3. VaultRegistrar.registerVault(vault, investor, deadline, signature)
│ ↳ verifies EIP-712 signature
│ ↳ links vault → investor in DS registry
│ ↳ emit VaultRegistered(...)
│
└─ 4. DSToken.transferFrom(investor, vault, amount)
↳ succeeds because vault is now registered
↳ emit Deposit(investor, vault, amount)
Critical: the operator in the EIP-712 signature
The operator field in the RegisterVault typed-data message must equal msg.sender of the registerVault() call. Since MockDeFiProtocol is the contract calling registerVault(), the investor must sign with:
operator = MockDeFiProtocol contract address
Not the deployer EOA. Not the investor's wallet. Not any backend relay address.
This is the most common cause of InvalidInvestorSignature(). The sandbox UI (Mock Protocol Example) handles this correctly automatically.
The deposit prerequisite checklist
Before deposit() will succeed:
| Requirement | How to satisfy |
|---|---|
MockDeFiProtocol has OPERATOR_ROLE on VaultRegistrar | Permissionless on testnet — call addOperator(mockProtocolAddress) or use Register as Operator |
VaultRegistrar has EXCHANGE role on DS Token | Pre-configured by Securitize for the sandbox deployment |
| Investor has DS Tokens | Use the Faucet |
Investor approved MockDeFiProtocol to spend DS Tokens | Done automatically by the sandbox UI; in code: dsToken.approve(mockProtocolAddress, amount) |
| EIP-712 signature is valid and unexpired | Sign with the correct operator, nonce, and deadline |
Adapting this pattern for your protocol
The key integration points that any DeFi protocol needs to implement:
- Store a vault per investor — any per-investor mapping works; the registrar only stores the vault address, not what's inside it.
- Call
registerVault()before any DS Token transfer — the registry binding must exist beforetransferFromwill succeed. - Use
msg.senderas the operator — your contract is the operator, so the investor's EIP-712operatorfield must be your contract address. - Accept
deadlineandsignatureas parameters — these come from the investor's off-chain signing step and are passed through toregisterVault().
For a simpler starting point (no events, no escape hatches), see Minimal Vault Factory.
Try it interactively
- Mock Protocol Example — sandbox UI pre-wired to this contract: Sign → Approve → Deposit.
- Protocol Tester — upload any ABI and call your own protocol contract with the same flow.