Implementing a simple KYC claim verification for a crowdsale
At Fractal, 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 Sovrin, Taqanu, uPort, and Civic, and experimenting with potential integrations.
Fabian Vogelsteller, the creator of the Mist Browser and web3.js, is working on a new identity standard for Ethereum, ERC 725. When used together with his other brainchild ERC 735, a standard for the management of identity claims, it is a very powerful tool for working with real identities on-chain.
Inspired by Nick Poulden, who took these standard drafts and created a great visual demonstration of how they can be combined, I decided to put together a small write-up that’s more focused on code.
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 (#ERC735), as well as a proxy function to act directly on the blockchain.
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
ENCRYPTION. Keys are
keccak256s of public addresses¹, and as such map to externally owned accounts (wallets) or smart contracts.
Another important concept is that an ERC 725 contract can be used as a proxy, through its
approve methods. If a third party recognizes the legitimacy of a given identity contract, its owner can call
execute on it to transact with said third party, as we’ll see below in our KYC example.
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
execute, but only those with access to higher-privilege keys can
approve the execution of those transactions.
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
ACTION key which maps to an
AccessControl 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.
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
CLAIM keys — deleting any one of them would cause the associated claims to lose their validity.
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 proposed a change to the standard which would make
payable 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
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 trusted KYC provider to determine whether or not an investor is eligible for purchasing tokens.
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
This demo considers the following entities.
- Very Good, a construction company looking to upend the real estate development market.
- Fractal ID, an identity provider who performs KYC/AML checks.
- Investor, who needs to clear KYC to participate in a Very Good’s ICO.
After compiling the contracts, our demonstration takes the following steps.
- Fractal ID deploys its own identity contract.
- Fractal ID adds a
CLAIMkey to its identity contract.
- Investor deploys their identity contract.²
- After Investor successfully undergoes KYC, Fractal ID signs a KYC claim for Investor.
- Investor adds Fractal ID’s signed KYC claim to their identity contract.³
- Very Good deploys their token and crowdsale contracts.
- Investor participates in Very Good’s ICO by making a transfer through their identity contract to Very Good’s crowdsale contract.
- Very Good’s crowdsale contract confirms that the Investor’s identity contract contains a KYC claim by Fractal ID before accepting the investment.
The smart contracts
I took Origin’s implementation of the standards as a starting point for this work. I had to slightly change the way they worked: because of the
payable 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.
| | | |
| 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 the full repo if you’re curious)
Step 1/4 — Deploying the identity contracts
Both Fractal ID and Investor need to deploy a
ClaimHolder contract, in order to hold all their keys and claims⁴. This contract implements both ERC 725 and ERC 735.
After deployment, Fractal ID will create a
CLAIM purpose key. This is the key associated with the signature of KYC claims.
var fractalIdClaimsKey = web3.utils.keccak256(
As described above, the key is the
keccak256 hash of the address of its controlling account. Fractal ID calls the
addKey method on the
ClaimHolder contract (ERC 725), passing it this key, the key’s
purpose, and its
Finally, Very Good needs to deploy their token and crowdsale contracts, and transfer
VeryGoodCoin’s ownership to the
VeryGoodCrowdsale contract, so it can mint tokens as needed to reward contributions.
Step 2/4 — Signing a KYC claim
After Investor goes through Fractal ID’s online KYC process, Fractal ID signs a KYC claim.
var hexedData = web3.utils.asciiToHex("Investor is VBR V0 legit.");
var hashedDataToSign = web3.utils.soliditySha3(
var signature = await web3.eth.sign(
Step 3/4 — Adding the KYC claim to the Investor contract
Fractal ID then facilitates this signed claim to Investor, who adds it to their identity contract³.
var claimIssuer = fractalIdClaimHolder.options.address;
var addClaimABI = await investorClaimHolder.methods
This is done through the
addClaim method (ERC 735) on the
ClaimHolder contract, which we feed a
data, and a
execute works is as follows. We pass it a destination address, an Ether value, and a serialized method call. If we call it with a
ACTION 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.
Step 4/4 — Participating in the ICO
In order for Investor to participate in the ICO, we’ll also be making use of the
execute method. The case here is much easier to understand: as Fractal ID’s identity claim is present on Investor’s identity contract, and Very Good’s crowdsale contract will be checking for a KYC claim on the message sender, this contract must necessarily be the caller.
var investABI = veryGoodCrowdsale.methods.buyTokens(
var investmentAmount = web3.utils.toWei("1", "ether");
All checks should pass now, and Very Good’s crowdsale contract will mint new tokens and assign their ownership to Investor’s identity contract! 🎉
¹ 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.
Planning an ICO? At Fractal, 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.