Abstract
This ERC introduces a companion contract interface ("Vault Registrar") for permissioned ERC-20 ecosystems. The interface enables third-party protocols to register investor-bound vault contracts under the investor's compliance identity, using explicit, revocable authorization granted by the investor via EIP-712 signed permissions.
The ERC is additive to ERC-20, does not modify the ERC-20 interface, and intentionally leaves identity and compliance logic implementation-defined.
Motivation
Many permissioned ERC-20 tokens (e.g. regulated real-world assets) must maintain investor-level ownership attribution for regulatory compliance, lifecycle events, and corporate actions.
Common DeFi patterns — such as pooled contracts — aggregate balances across investors and obscure beneficial ownership. A widely adopted alternative is investor-bound vaults: protocols deploy a dedicated vault contract per investor, the vault holds and manages the permissioned token on the investor's behalf, and ownership attribution remains tied to the investor.
Today, authorizing such vaults requires bespoke, issuer-specific flows, forcing protocols to implement custom integrations for each permissioned token ecosystem. This ERC standardizes the integration surface between protocols and permissioned-token ecosystems.
Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Overview
A Vault Registrar is a standalone companion contract that permissioned ERC-20 ecosystems MAY expose. It acts as a policy-enforcing registry. Before registering a vault under an investor's identity, it verifies:
- The operator (protocol) is authorized.
- A valid investor permission exists (via EIP-712 signed authorization).
- Compliance rules are satisfied.
The high-level flow is as follows:
- An investor signs an EIP-712 authorization message granting a protocol permission to register vaults under their identity.
- The protocol deploys a vault contract for the investor.
- The protocol calls the Vault Registrar, presenting the signed authorization.
- The registrar verifies the authorization and compliance rules.
- If all checks pass, the vault is registered under the investor's identity.
EIP-712 Authorization
Vault authorization MUST be explicitly granted by the investor and MUST be revocable. The investor signs a structured EIP-712 message authorizing a specific operator to register vaults under their identity.
Domain:
name = "VaultRegistrar"
version = "1"
chainId = <deployment chain>
verifyingContract = <VaultRegistrar address>Struct:
RegisterVault(
address investor,
address operator,
address token,
uint256 nonce,
uint256 deadline
)Type hash:
REGISTER_VAULT_TYPEHASH = keccak256(
"RegisterVault(address investor,address operator,address token,uint256 nonce,uint256 deadline)"
)Investors can invalidate all previously granted permissions to an operator on-chain via invalidateOperatorPermission, which increments the nonce and renders any outstanding signatures void.
Interface
interface IERC_VaultRegistrar {
/// @notice Emitted when a vault is successfully registered under an investor's identity.
event VaultRegistered(
address indexed investor,
address indexed vault,
address token,
string investorId,
address indexed sender
);
/// @notice Emitted when a vault registration is revoked.
event VaultUnregistered(
address indexed investor,
address indexed vault,
address token,
string investorId,
address indexed sender
);
/// @notice Emitted when an investor invalidates all outstanding permissions for an operator.
event OperatorPermissionInvalidated(
address indexed investor,
address indexed operator,
uint256 newNonce
);
/// @notice Register a vault under an investor's identity.
/// @dev The caller (operator) MUST present a valid EIP-712 signed authorization from the
/// investor. Implementations MUST revert if the authorization is missing, invalid,
/// or revoked, or if compliance checks fail. Intended to be called by authorized
/// protocol contracts as part of an atomic transaction.
/// @param vaultAddress The vault contract address to register.
/// @param investorWalletAddress The investor's wallet address that signed the authorization.
/// @param deadline Unix timestamp after which the signature is invalid.
/// @param signature EIP-712 signed permission from the investor. Supports both
/// EOA (ECDSA) and smart contract wallets (ERC-1271).
function registerVault(
address vaultAddress,
address investorWalletAddress,
uint256 deadline,
bytes calldata signature
) external;
/// @notice Check whether a vault is registered for a given investor.
/// @param vaultAddress The vault contract address.
/// @param investorWalletAddress The investor's wallet address.
/// @return True if the vault is currently registered under the investor's identity.
function isRegistered(
address vaultAddress,
address investorWalletAddress
) external view returns (bool);
/// @notice Revoke the registration of a vault.
/// @param vaultAddress The vault contract address.
/// @param investorWalletAddress The investor's wallet address.
function unregisterVault(
address vaultAddress,
address investorWalletAddress
) external;
/// @notice The permissioned ERC-20 token this registrar serves.
/// @return The token contract address.
function token() external view returns (address);
/// @notice Returns the current nonce for an investor-operator pair.
/// Used to construct and verify EIP-712 authorization signatures.
/// @param investor The investor's wallet address.
/// @param operator The operator (protocol) address.
/// @return The current nonce value.
function operatorNonce(
address investor,
address operator
) external view returns (uint256);
/// @notice Invalidates all EIP-712 signatures previously granted by the caller to an operator.
/// Increments the nonce for the caller-operator pair, rendering any outstanding
/// signatures void.
/// @param operator The operator address whose permissions are being invalidated.
function invalidateOperatorPermission(address operator) external;
}Behavior Requirements
registerVaultMUST revert if the provided signature is invalid, expired, or has been revoked viainvalidateOperatorPermission.registerVaultMUST revert if implementation-defined compliance checks fail.unregisterVaultMUST emit aVaultUnregisteredevent upon success.registerVaultMUST emit aVaultRegisteredevent upon success.invalidateOperatorPermissionMUST increment the nonce and MUST emitOperatorPermissionInvalidated.- Revocation MUST be enforced synchronously — a revoked authorization MUST NOT be usable in any subsequent call.
Rationale
Standalone Companion Interface
This ERC is designed as a standalone contract interface rather than an ERC-20 extension for the following reasons:
- Many permissioned tokens cannot be upgraded to add new methods.
- Compliance logic is often externalized for regulatory or operational reasons.
- Protocols prefer a predictable "call this contract during the flow" pattern.
- The design avoids imposing identity semantics on token contracts.
The registrar acts as an adapter between protocols and permissioned ERC-20 ecosystems.
EIP-712 Signed Authorization
The choice to require explicit EIP-712 investor authorization rather than implicit protocol trust provides three key properties:
Clear user consent. The authorization message makes the permission explicit and user-visible. Investors cryptographically authorize vault creation rather than implicitly trusting protocol flows.
Revocable permissions. Investors can revoke authorization by invalidating the operator nonce. This aligns with familiar wallet-based permission patterns.
Protocol lifecycle flexibility. Many real integrations involve collateral management strategies where new vaults may need to be created over time — for example, collateral rebalancing, leverage loops, liquidation protection, or strategy upgrades. The signed authorization allows those vaults to be created without requiring the investor to manually re-authorize every step.
Relationship to ERC-4626 and ERC-7575
While this proposal involves vault contracts, it is orthogonal to ERC-4626 and ERC-7575. This ERC does not define vault accounting or asset semantics. It focuses exclusively on standardizing authorization of investor-bound vault addresses in permissioned ERC-20 ecosystems.
Non-Goals
This proposal explicitly does not attempt to:
- Standardize identity models, KYC, or accreditation logic.
- Define how investor identities are represented or stored.
- Replace or subsume ERC-3643 or other permissioned token standards.
- Mandate specific compliance checks or policies.
- Define vault accounting, asset semantics, or identity models.
All compliance semantics remain implementation-defined.
Backwards Compatibility
This ERC introduces a new standalone interface and has no backwards compatibility issues with ERC-20 or any existing standard. Permissioned token contracts may adopt the Vault Registrar pattern without modifying their ERC-20 interface.
This ERC is compatible with:
- ERC-20
- ERC-3643 and custom permissioned token implementations
- ERC-1271 (smart contract wallet signatures)
- Regulated ERC-20 tokens, permissioned vault protocols, collateral and lending systems, and looping strategies
Reference Implementation
A reference implementation is available at https://github.com/securitize-io/bc-vault-registrar/tree/feature/BC-1833
Security Considerations
Operator authorization scope. Implementations SHOULD restrict which callers may invoke registerVault. Vault authorization SHOULD be treated as equivalent to investor authorization, as a registered vault will be able to hold and operate permissioned tokens on the investor's behalf.
EIP-712 signature validation. Signatures MUST be validated against the correct domain separator and struct hash. Implementations MUST support both ECDSA (EOA) and ERC-1271 (smart contract wallet) signatures. Replay protection is provided by the nonce mechanism; implementations MUST verify the nonce matches the current value for the investor-operator pair.
Deadline enforcement. Implementations MUST reject signatures with a deadline in the past. The deadline field MUST be checked against block.timestamp.
Revocation synchronicity. Revocation via invalidateOperatorPermission MUST take effect immediately. A revoked authorization MUST NOT be accepted in any subsequent registerVault call within the same block or thereafter.
Reentrancy. Implementations SHOULD follow the checks-effects-interactions pattern. registerVault is intended to be called within complex protocol flows; implementations should be safe against reentrancy attacks.
Denial of service. Implementations SHOULD ensure that registerVault cannot be griefed by an adversary racing to invalidate an investor's nonce. Callers SHOULD construct transactions to minimize the window between signature issuance and on-chain submission.
Copyright
Copyright and related rights waived via CC0.
