A Companion Guide to “First impressions with ERC 725 and ERC 735 - identity and claims” (Part 3)

KC Tam
5 min readJan 25, 2019

5. Detail Flow of the Demo: walking through main.js (cont.)

Step 5: Investor adds Fractal ID’s signed KYC claim to their identity contract

Now we have the signature of the claim from Fractal ID. Investor now adds the claim to Investor ClaimHolder contract using addClaim(). Here is the code in main.js.

The required arguments are passed to addClaim(). All the information is required according to the struct Claim defined in ERC-735.

Now we can inspect the struct Claim in Investor ClaimHolder contract. We use getClaimsIdByType() with type 7 (KYC), and getClaim() to get more detail about this claim.

If we match the struct Claim we will see

  • the claim type (KYC, 7)
  • scheme (ECDSA, 1)
  • the issuer, which is the Fractal ID ClaimHolder Contract address
  • signature generated in Step 4
  • data upon which signature is created (which is a hex of the phrase added at Step 4)
  • a URI

We also see the Claim ID, which is computed as the hash of issuer and claim type according to the ClaimHolder.sol (line 22).

bytes32 claimId = keccak256(_issuer, _claimType)
Step 5: Investor adds the claim issued by Fracter ID to its own Identity Contract.

Step 6: Very Good deploys their token and crowdsale contracts

In real life the deployment of token and crowdsale contracts should be done independently but for sake of demo, the deployment happens in this step.

Note the fractalLpAccount in the main.js corresponds to the accounts[2], which is the Very Good Company.

When deployed, the crowdsale contract comes with these arguments,

  • rate is 10 tokens per wei
  • beneficiary is Very Good Company
  • the token address is the Very Good Coin’s contract address deployed (note the Very Good Coin is deployed before the Crowdsale contract)
  • the KYC claim provider that this Crowdsale contract accepts

The last item is an addition as it is a specific need for this crowdsale. If we see the inheritance of these contracts and compare the constructors among them, we can tell that trsutedClaimHolder in VeryGoodCrowdsale.sol is now keeping the Fractal ID ClaimHolder contract.

Contract inheritance

We can take a look on the trustedClaimHolder from the deployed Very Good Crowdsale contract,

The result is a 32-byte version of the Fractal ID ClaimHolder contract (see the table in the introduction part of this session).

Note: I use function selector to call this public variable. With this I do not need the ABI of the Crowdsale contract. The format is

> eth.call({to: <target contract address>, data: <function selector + arguments if needed>})
Step 6: Very Good Company deploys Token and Crowdsale Contract

Step 7: Investor participates in Very Good’s ICO by making a transfer through their identity contract to Very Good’s crowdsale contract

After the Coin and Crowdsale contracts are deployed, Investor is issuing buyTokens() through the Investor ClaimHolder contract. Here is the code in main.js.

This buyTokens() is done in a proxy way,

  • Investor Account (i.e. eth.accounts[3]) calls execute() in Investor ClaimHolder contract, passing the 1 ether and target Crowdsale contract address.
  • Investor ClaimHolder Contract executes buyTokens() in Crowdsale contract.
Step 7: Investor buys Token through Investor’s Identity (ClaimHolder) contract

Step 8: Very Good’s crowdsale contract confirms that the Investor’s identity contract contains a KYC claim by Fractal ID before accepting the investment

The last step is to see how Very Good Crowdsale contract performs the checking. It is done by a function claimIsValid() in VeryGoodCrowdsale.sol.

It is taken from VeryGoodCrowdsale.sol

The logic to check the validity of a claim

  1. Obtain the Investor ClaimHolder contract and the Claim Type (KYC, 7) required in this validity check.
  2. Construct back the Claim ID, which is from the Fractal ID ClaimHolder contract and the Claim Type. This should have the same result on the Claim ID when Investor is adding claim using addClaim() (see Step 5).
  3. Fetch the Claim from Investor ClaimHolder contract with the computed Claim ID, and collect all the required information from that Claim (see the Claim content in Step 5).
  4. Construct the data back for signature verification according to the specific algorithm.
  5. The way of validation is through recovery of the address based on the information available (stored in recovered).
  6. Perform the same hash on the recovered address to obtain the key, and check whether this key is inside Fractal ID ClaimHolder contract, and the type of the key is a Claim key (CLAIM, 3).

When it returns back a True, the requirement of _preValidatePurchase() is fulfilled in buyTokens(). What remains is the normal process of token handling, i.e. issue tokens to buyer.

We see it is the Investor ClaimHolder contract account (0xa86eb0…), not the Investor account (0x988b5e…), keeping the balance in the Very Good Coin Contract (0x8ac7230489e8000 = 10^19 tokens).

Finally we check the ether balance of both Crowdsale beneficiary account (accounts[2], ~101 ethers) and the Investor account (accounts[3], ~99 ethers). It is 1 ether being transferred from Investor to beneficiary account. Note some gas is paid from both accounts for transactions.

Step 8: After KYC validity check tokens are issued to Investor

Closing

I wish this lengthy article can serve as a companion guide to Julio’s article and demo, showing more detail how ERC-725/735 is implemented and used in a crowdsale case.

Kudos again to Julio Santos of Fractal as his work really helps me understand more on ERC-725/735, and I also hope all reading this work can benefit as much as I did.

--

--