Functions
Every external function exposed by VaultRegistrar and its base. Functions defined in IVaultRegistrar are listed first; inherited operational functions are at the bottom.
IVaultRegistrar functions
registerVault
function registerVault(
address vaultAddress,
address investorWalletAddress,
uint256 deadline,
bytes calldata signature
) external;
The primary operator entrypoint. Registers vaultAddress against investorWalletAddress in the DS Registry, after verifying that the investor signed an EIP-712 RegisterVault payload authorizing msg.sender as the operator.
Modifiers / role checks
whenNotPaused- caller (
msg.sender) is the operator that the signature was issued to — verified implicitly by the EIP-712 recovery - caller must hold
OPERATOR_ROLE(enforced byaddOperatorflow up front)
Preconditions
block.timestamp <= deadlineinvestorWalletAddressis non-zerovaultAddressis non-zeroinvestorWalletAddressresolves to a non-empty investor ID in the DS RegistryvaultAddressis either unknown to the registry, or already bound to the same investor (idempotency on identical pairs is treated as a revert — seeVaultAlreadyRegistered)- The signature must EIP-712-recover to
investorWalletAddressover the typed data
RegisterVault(
investor=investorWalletAddress,
operator=msg.sender,
token=token(),
nonce=operatorNonce(investorWalletAddress, msg.sender),
deadline=deadline
)
Verification uses SignatureChecker.isValidSignatureNow, so EOA signatures and ERC-1271 contract-wallet signatures are both accepted.
State changes
- Calls
IDSRegistryService(registry).addWallet(vaultAddress, investorId)so the vault address resolves to the investor's ID. - Does not modify
_operatorNonces(this is the standing-permission model).
Emits
VaultRegistered(investor, vault, token, investorId, sender)InvestorSignatureVerified(investor, operator, nonce, deadline, signature)
Reverts
| Selector | Error | Cause |
|---|---|---|
0x0819bdcd | SignatureExpired() | block.timestamp > deadline |
0xac94b822 | InvalidInvestorSignature() | EIP-712 recovery did not yield investorWalletAddress |
0xfed39497 | InvestorNotFound(address) | registry.getInvestor(investor) == "" |
0x38bfcc16 | VaultAlreadyRegistered(address) | Vault is already bound to this investor |
0x8df63830 | VaultBelongsToDifferentInvestor(address,string) | Vault is bound to a different investor ID |
0xe6c4247b | InvalidAddress() | Vault or investor is the zero address |
| OZ | EnforcedPause() | Contract is paused |
Standing-permission box. A successful
registerVault()call does not consume the operator nonce. The same signature can be used to register additional vaults under the same(investor, operator)pair until the deadline passes or the investor callsinvalidateOperatorPermission(operator). This is intentional — see EIP-712.
Gateway caveat box. When you call this through
bc-labs-gw(POST /api/v1/vault-registrar/register),msg.senderis the gateway's operator wallet, not your factory. Your investor signatures must encode the gateway operator as theoperatorfield. Also: the gateway returns 200 on submit, not on confirmation. Watch the tx hash.
isRegistered
function isRegistered(
address vaultAddress,
address investorWalletAddress
) external view returns (bool);
Read helper for downstream protocols that want to gate on registration. Returns true iff the DS Registry maps both addresses to the same non-empty investor ID.
Implementation:
investorId = registry.getInvestor(investorWalletAddress)
vaultInvestorId = registry.getInvestor(vaultAddress)
return investorId != "" &&
vaultInvestorId != "" &&
keccak256(investorId) == keccak256(vaultInvestorId)
Notes
- This is a stateless read; safe to call from anywhere, including off-chain.
- It does not prove that
registerVault()was called — only that the registry currently agrees the two addresses share an investor. In practice these are equivalent because the only way the registry will have made the binding is viaregisterVault(or a manual admin action).
unregisterVault
function unregisterVault(
address vaultAddress,
address investorWalletAddress
) external;
Status: not implemented. The current
VaultRegistrarimplementation always reverts withNotImplemented()(selector0xd6234725). Do not build off-ramp logic that depends on this function.
The off-ramp lives at the protocol layer (vault withdraw back to investor) plus optional invalidateOperatorPermission from the investor. See Step 7: Return Tokens.
token
function token() external view returns (address);
Returns the DS token address bound to this VaultRegistrar instance at initialize() time. Use it whenever you build an EIP-712 payload or any read that needs the canonical DST address — do not hard-code, since one registrar can only ever be bound to one token, but a misconfigured frontend can easily diverge.
operatorNonce
function operatorNonce(
address investor,
address operator
) external view returns (uint256);
Returns the current operator nonce for one (investor, operator) pair.
Properties
- starts at
0for any new pair - does not change on a successful
registerVault() - increments by exactly
1only wheninvalidateOperatorPermission(operator)is called byinvestor - per-investor and per-operator — invalidating one operator does not affect any other
invalidateOperatorPermission
function invalidateOperatorPermission(address operator) external;
Investor-side revocation. Increments operatorNonce(msg.sender, operator) by 1, which makes every previously issued signature from msg.sender to operator unusable for future registerVault() calls.
State changes
_operatorNonces[msg.sender][operator] += 1
Does NOT
- unbind already-registered vaults from
msg.senderin the DS registry - affect other operators
- affect other investors who previously signed for the same
operator
Emits
The interface declares
NotAnOperator(address)for this function, but the live implementation does not enforce that the target address actually holdsOPERATOR_ROLE. Calling with an arbitrary address will still succeed and bump the per-pair nonce.
Inherited operational functions (BaseVaultRegistrar)
These are not part of IVaultRegistrar, but they govern who may operate the registrar and whether new registrations are accepted. Source: bc-vault-registrar/contracts/BaseVaultRegistrar.sol.
initialize
function initialize(address _token) public initializer;
Sets token and grants the deployer DEFAULT_ADMIN_ROLE. UUPS pattern — _disableInitializers() is called in the constructor to lock the implementation contract. Initializes the EIP-712 domain with name="VaultRegistrar", version="1".
addOperator
function addOperator(address operator) external;
Grants OPERATOR_ROLE to operator. Idempotent at the role level. Reverts on the zero address.
Permissioning note. The standard implementation gates this with
onlyRole(DEFAULT_ADMIN_ROLE). The testnet sandbox deployment used by this site has been deployed with permissionlessaddOperator()— any address can register itself as an operator. Use the Register as Operator page to do this via the UI. Production deployments will require admin approval.
removeOperator
function removeOperator(address operator) external onlyRole(DEFAULT_ADMIN_ROLE);
Revokes OPERATOR_ROLE from operator. Reverts on the zero address.
isOperator / isAdmin
function isOperator(address account) external view returns (bool);
function isAdmin(address account) external view returns (bool);
Convenience role helpers. isOperator is hasRole(OPERATOR_ROLE, account); isAdmin is hasRole(DEFAULT_ADMIN_ROLE, account).
pause / unpause / paused
function pause() external onlyRole(DEFAULT_ADMIN_ROLE);
function unpause() external onlyRole(DEFAULT_ADMIN_ROLE);
function paused() external view returns (bool);
registerVault() is whenNotPaused. Pausing is the kill switch for new registrations; it does not affect existing bindings, isRegistered reads, or invalidateOperatorPermission.
getImplementationAddress / getInitializedVersion
function getImplementationAddress() external view returns (address);
function getInitializedVersion() external view returns (uint64);
UUPS introspection helpers. Useful for audit / upgrade verification.
DOMAIN_SEPARATOR / eip712Domain
function DOMAIN_SEPARATOR() external view returns (bytes32);
function eip712Domain() external view returns (
bytes1, string memory, string memory, uint256, address, bytes32, uint256[] memory
);
Standard EIP-712 introspection. Use when debugging signature mismatches: hash your typed data manually with _hashTypedDataV4-equivalent code and compare against the on-chain domain separator.
_authorizeUpgrade
function _authorizeUpgrade(address) internal override onlyRole(DEFAULT_ADMIN_ROLE);
Internal — listed here so operators are aware that upgrades require DEFAULT_ADMIN_ROLE. Operators do not need to call this directly.