Last week, the Centre Consortium announced its new Verite project:
Verite provides an open architecture for facilitating the verification of credentials among decentralized apps. It is designed with particular use-cases in mind such as verifying that a user has completed KYC or an accreditation check, but it can be used for a wide range of credentials. Verite is designed to be private by design, minimizing the amount of personally identifiable information that needs to be shared outside of the credential setup process with an issuer such as an exchange.
The Verite documentation provides a helpful overview of patterns for issuing and verifying credentials, and implementing credential verification in a smart contract.
The section of the Verite documentation on smart contract patterns describes two primary patterns. The first is a Verifier Submission Pattern. To quote the documentation:
In the verifier submission pattern, a verifier executes the off-chain verification of a credential and then registers verification success with a registry smart contract. A relying decentralized application or other client never accesses the credential or the Verification Result.
After verification and registration, wallets, dapps, apps, and smart contracts can determine whether a given address has an active verification by executing a view (no cost) function on the registry contract containing the registration.
A variation of this pattern is also described in which a service that is completing ID verification and KYC directly submits a verification record to a registry, where it can be accessed by smart contracts. This combines the steps of setting up credentials with verifying those credentials and storing that verification record on-chain:
Regardless of how the verification records are made available on-chain, there are a couple of notable problems with verification registries as presented in the Verite docs. With the limited data structures available in Solidity, one contract must be used for each type of credential check and there may be dozens if not hundreds of on-chain verification registries. Smart contracts utilizing these records need to know in advance which smart contract address to use for the verification. Even if a smart contract is able to have its code updated or is designed to allow an admin to specify new registries to use, this creates a potentially significant maintenance burden for the smart contract developer.
The other problem with verification registries is that there is likely to not be a single registry used by all smart contracts . This is a good thing from the perspective of not allowing dependencies of smart contracts to become overly centralized, but users are likely to need to have credentials on different registries and as a result set up credentials with multiple issuers and have them verified separately. At best this is poor UX that does not minimize the sharing of personally identifiable information, and at worst it could be a vector for bad actors to maliciously collect PII under the guise of being a legitimate KYC or accreditation checking process.
The Verite documentation does describe an alternative to verification registries in the form of the Subject Submission Pattern:
In the subject submission pattern, a dapp still utilizes an off-chain verifier for verification, but the verifier does not directly register the result with a smart contract. Instead, the verifier returns the Verification Result and its signature to the subject, and the subject passes the Verification Result and verifier’s signature to a smart contract's custom function, which can validate the result in addition to other logic in the same transaction.
This pattern does not require the use of an on-chain verification registry, but it requires custom functions for additional parameters for verification data provided by the user, and as a result the pattern breaks compatibility with ERC-20 and other common standards that almost all token contracts and wallets use.
This post briefly describes a proposal for how to simultaneously accomplish the following outcomes:
The Verification Registry Proxy Pattern is a modified version of the Verifier Submission Pattern in which the smart contract makes a call to a verification registry proxy contract setup for a particular type of credential, such as credentials verifying whether the address is associated with a user who has completed KYC or an investor accreditation check. These proxy contracts allow for users to specify with which registry out of a number of supported registries they have verified. This specification could also be provided by the verifier uploading the verification record to the chosen registry so the user does not need to perform a separate transaction to specify this information. The registries supported by the proxy are determined by the contract administrator, which could be an organization such as a DAO or an individual.
Just like with the Subject Submission Pattern, users are able to use their choice of verifier, and presumably issuer as well. But no additional parameters are needed in transactions to transfer tokens are perform other common actions, as this choice has been previously specified to the registry proxy.
The proxy pattern also enables a variety of other possibilities. For example, a contract developer may need to check that a user has completed KYC, but is willing to accept the completion of an investor accreditation check as being equivalent to having completed KYC. In a variation that would be more practically easy to implement for contract developers, they would be willing to delegate this type of nuanced decision making to the DAO managing the registry proxy they are using. The proxy pattern enables contract developers to accomplish outcomes such as being in regulatory compliance in a straightforward way that does not require specialized expertise.
The smart contract utilizing a registry proxy can use code identical to that of how it would normally verify credentials with a verification registry:
function _validCounterparty(address registryAddress) private view returns (bool) {
return kycRegistry.isVerified(registryAddress);
}
Instead of kycRegistry
mapping to a verification registry address, it would simply map to a registry proxy address instead.
A follow up to this post will include example solidity code demonstrating how a verification registry proxy could be implemented, and additional considerations and potential improvements that could be made to the pattern.