Implementing a simple KYC claim verification for a crowdsale At , we’re focused on improving the ICO experience, from both a UX and a regulatory compliance perspective. One of the crucial bits of a successful ICO is proper participation eligibility verification (KYC, AML, CFT, capital markets regulations, etc). As such, we’re closely watching the identity space, following projects such as , , , and , and experimenting with potential integrations. Fractal Sovrin Taqanu uPort Civic , the creator of the and , is working on a new identity standard for Ethereum, . When used together with his other brainchild , a standard for the management of identity claims, it is a very powerful tool for working with real identities on-chain. Fabian Vogelsteller Mist Browser web3.js ERC 725 ERC 735 Inspired by , who took these standard drafts and created , I decided to put together a small write-up that’s more focused on code. Nick Poulden a great visual demonstration of how they can be combined An overview of the standards One of the best things about ERC 725 and 735 is that they’re open, community-driven, and participatory standards. They’re also quite simple to understand, as they’re small, targeted standards which do one thing each but do it really well: manage identities and claims on those identities. ERC 725: Identity The following describes standard functions for a unique identity for humans, groups, objects and machines.This identity can hold keys to sign actions (transactions, documents, logins, access, etc), and claims, which are attested from third parties (issuers) and self attested ( ), as well as a proxy function to act directly on the blockchain. #ERC735 ERC 725 is a standard for publishing and managing an identity via a smart contract on an EVM-based blockchain, such as Ethereum. This identity is represented by its chain address. We can associate several keys with this identity. These keys can have different purposes: the standard currently proposes , , and . Keys are s of public addresses¹, and as such map to externally owned accounts (wallets) or smart contracts. MANAGEMENT ACTION CLAIM ENCRYPTION keccak256 Another important concept is that an ERC 725 contract can be used as a proxy, through its / methods. If a third party recognizes the legitimacy of a given identity contract, its owner can call on it to transact with said third party, as we’ll see below in our KYC example. execute approve execute Multiple keys are particularly useful in the context of privileged access. For example, suppose this identity is not for an individual, but an organization. Members holding less privileged keys can submit transactions to , but only those with access to higher-privilege keys can the execution of those transactions. execute approve We can go even further down this rabbit hole. Since keys can also map to smart contracts instead of wallets, further access requirements could potentially be implemented. For example, having an key which maps to an contract allows us to build arbitrarily complex access control levels in this contract. This is important because it keeps the standard itself simple, while simultaneously supporting every imaginable use case. ACTION AccessControl Another example has to do with revoking claims. If we’re using our identity to make claims on another identity, it can be useful to have several keys — deleting any one of them would cause the associated claims to lose their validity. CLAIM For a real-world example, suppose Mozilla has an Identity contract. Aside from whatever else Mozilla chooses to do with that identity, The Firefox software team could hold one of the keys belonging to that identity, with which they’d sign software checksums upon release. For our KYC use case, described below, we to the standard which would make a method, allowing us to forward Ether with the transaction to execute. An alternate approach would be to use two separate transactions: send Ether to the contract first, and then move it with . proposed a change execute payable execute ERC 735: Claim Holder The following describes standard functions for adding, removing and holding of claims. These claims can attested from third parties (issuers) or self attested. This standardised claim holder interface will allow Dapps and smart contracts to check the claims about a claim holder. Trust is here transfered to the issuers of claims. ERC 735 deals with the management of claims made about an ERC 725 identity. It facilitates an emergence of a web of trust, by relying on the claims of trusted third parties about a given identity. These claims can be of several topics, from biometric data, to email account ownership. This is particularly useful for our KYC use case, described below. As ICO issuers, we can work with a to determine whether or not an investor is eligible for purchasing tokens. trusted KYC provider In order for someone to add a claim to their identity, they must first request it of a relevant trusted third party. This third party (the claim issuer) will sign a message containing three items: the identity’s address, the claim topic, and optionally some data to go along with it (for example, a hash of the KYC data). The identity owner would then store this claim in their identity contract (alternatively, the claim issuer can also add the claim themselves, which would have to be approved by the identity owner). Note that claims can also be self-attested, which can be enough for a lot of other use cases (email and name come to mind, for simple applications with no strict KYC requirements, like a regular news website). KYC claims for crowdsales Entities This demo considers the following entities. , a construction company looking to upend the real estate development market. Very Good , an identity provider who performs KYC/AML checks. Fractal ID , who needs to clear KYC to participate in a ’s ICO. Investor Very Good Flow overview After compiling the contracts, our demonstration takes the following steps. deploys its own identity contract. Fractal ID adds a key to its identity contract. Fractal ID CLAIM deploys their identity contract.² Investor After successfully undergoes KYC, signs a KYC claim for . Investor Fractal ID Investor adds ’s signed KYC claim to their identity contract.³ Investor Fractal ID deploys their token and crowdsale contracts. Very Good participates in ’s ICO by making a transfer through their identity contract to ’s crowdsale contract. Investor Very Good Very Good ’s crowdsale contract confirms that the ’s identity contract contains a KYC claim by before accepting the investment. Very Good Investor Fractal ID The smart contracts I took of the standards as a starting point for this work. I had to the way they worked: because of the issue described above, this implementation wasn’t prepared to relay value to the execution target. Here’s a simple inheritance diagram of the contracts, for clarity. Origin’s implementation slightly change payable +---------------+ +---------------+| | | || ERC 725 | | ERC 735 || | | |+-------+-------+ +-------+-------+^ ^| |+-------+-------+ || | || KeyHolder | || | |+-------+-------+ |^ || |+-------+-------+ || | || ClaimHolder +-------------+| |+---------------+ The token and crowdsale contracts were lifted out of . OpenZeppelin Solidity In order to deploy and interact with these contracts, I used web3.js to put together a simple JS script. (here’s if you’re curious) the full repo Step 1/4 — Deploying the identity contracts Both and need to deploy a contract, in order to hold all their keys and claims⁴. This contract implements both ERC 725 and ERC 735. Fractal ID Investor ClaimHolder After deployment, will create a purpose key. This is the key associated with the signature of KYC claims. Fractal ID CLAIM var fractalIdClaimsKey = web3.utils.keccak256(fractalIdClaimsAccount); fractalIdClaimHolder.methods.addKey(fractalIdClaimsKey,KEY_PURPOSES.CLAIM,KEY_TYPES.ECDSA,).send({from: fractalIdAccount,gas: 4612388,}); As described above, the key is the hash of the address of its controlling account. calls the method on the contract (ERC 725), passing it this key, the key’s , and its . keccak256 Fractal ID addKey ClaimHolder purpose keyType Finally, needs to deploy their token and crowdsale contracts, and transfer ’s ownership to the contract, so it can mint tokens as needed to reward contributions. Very Good VeryGoodCoin VeryGoodCrowdsale veryGoodCoin.methods.transferOwnership(veryGoodCrowdsale.options.address,).send({from: veryGoodAccount,}); Step 2/4 — Signing a KYC claim After goes through ’s , signs a KYC claim. Investor Fractal ID online KYC process Fractal ID var hexedData = web3.utils.asciiToHex("Investor is VBR V0 legit.");var hashedDataToSign = web3.utils.soliditySha3(investorClaimHolder.options.address,CLAIM_TYPES.KYC,hexedData,);var signature = await web3.eth.sign(hashedDataToSign,fractalClaimsAccount,); Step 3/4 — Adding the KYC claim to the Investor contract then facilitates this signed claim to , who adds it to their identity contract³. Fractal ID Investor var claimIssuer = fractalIdClaimHolder.options.address;var addClaimABI = await investorClaimHolder.methods.addClaim(CLAIM_TYPES.KYC,CLAIM_SCHEMES.ECDSA,claimIssuer,signature,hexedData," ",).encodeABI(); https://www.trustfractal.com/business/ investorClaimHolder.methods.execute(investorClaimHolder.options.address,0,addClaimABI,).send({gas: 4612388,from: investorAccount,}); This is done through the method (ERC 735) on the contract, which we feed a , a , the , the , the , and a ⁵. addClaim ClaimHolder topic scheme issuer signature data uri The way works is as follows. We pass it a destination address, an Ether value, and a serialized method call. If we call it with a or key, the request gets approved and executes. If we call it with a key of any other purpose, a higher privilege key has to subsequently approve the execution. execute MANAGEMENT ACTION Step 4/4 — Participating in the ICO In order for to participate in the ICO, we’ll also be making use of the method. The case here is much easier to understand: as ’s identity claim is present on ’s identity contract, and ’s crowdsale contract will be checking for a KYC claim on the message sender, this contract must necessarily be the caller. Investor execute Fractal ID Investor Very Good var investABI = veryGoodCrowdsale.methods.buyTokens(investorClaimHolder.options.address).encodeABI(); var investmentAmount = web3.utils.toWei("1", "ether");investorClaimHolder.methods.execute(veryGoodCrowdsale.options.address,investmentAmount,investABI,).send({gas: 4612388,from: investorAccount,value: investmentAmount,}); All checks should pass now, and ’s crowdsale contract will mint new tokens and assign their ownership to ’s identity contract! 🎉 Very Good Investor Thanks to Fabian Vogelsteller , Hugo Peixoto and João Gradim for reading drafts of this post. ¹ More precisely, _keccak256_ is only recommended by the standard for non-hex and keys longer than 32 bytes. ² Fractal ID could also do this on behalf of Investor. ³ There’s another flow suggested by ERC 725, which is for Fractal ID to call _addClaim_ on the Investor contract. This claim could be accepted by the Investor ’s identity contract immediately, or undergo an approval process first. ⁴ Technically, a _KeyHolder_ contract for Fractal ID would suffice. ⁵ Note that we’re using _encodeABI_ to serialize the _addClaim_ method call, and piping it through _execute_ . Investor could instead have called _addClaim_ directly, using the account mapping to the appropriate privileges. At , we offer a hassle-free, user-friendly launchpad solution combined with a comprehensive customer identification service (KYC/AML) to successfully deploy your token launch with ease. Planning an ICO? Fractal