Skip to main content

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 by addOperator flow up front)

Preconditions

  • block.timestamp <= deadline
  • investorWalletAddress is non-zero
  • vaultAddress is non-zero
  • investorWalletAddress resolves to a non-empty investor ID in the DS Registry
  • vaultAddress is either unknown to the registry, or already bound to the same investor (idempotency on identical pairs is treated as a revert — see VaultAlreadyRegistered)
  • The signature must EIP-712-recover to investorWalletAddress over 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

Reverts

SelectorErrorCause
0x0819bdcdSignatureExpired()block.timestamp > deadline
0xac94b822InvalidInvestorSignature()EIP-712 recovery did not yield investorWalletAddress
0xfed39497InvestorNotFound(address)registry.getInvestor(investor) == ""
0x38bfcc16VaultAlreadyRegistered(address)Vault is already bound to this investor
0x8df63830VaultBelongsToDifferentInvestor(address,string)Vault is bound to a different investor ID
0xe6c4247bInvalidAddress()Vault or investor is the zero address
OZEnforcedPause()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 calls invalidateOperatorPermission(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.sender is the gateway's operator wallet, not your factory. Your investor signatures must encode the gateway operator as the operator field. 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 via registerVault (or a manual admin action).

unregisterVault

function unregisterVault(
address vaultAddress,
address investorWalletAddress
) external;

Status: not implemented. The current VaultRegistrar implementation always reverts with NotImplemented() (selector 0xd6234725). 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 0 for any new pair
  • does not change on a successful registerVault()
  • increments by exactly 1 only when invalidateOperatorPermission(operator) is called by investor
  • 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.sender in 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 holds OPERATOR_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 permissionless addOperator() — 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.