Proof of Humanity Group Token

Hello everyone,

I’m Andrei, dev @ Kleros, working on Proof of Humanity. Proof of Humanity is coming to Gnosis Chain very soon. A Proof of Humanity <> Circles synergy would be great for both projects.

To register on Proof of Humanity, you have to make a request using your wallet, take a photo and a video of yourself following the instructions, put some deposit, get a vouched from someone else and then wait for challenging period to pass. If you are challenged in that period, a Kleros dispute is created. If you win any challenge or are not challenged at all, you are registered to PoH.

To check whether a wallet address belongs to someone registered on PoH, one can simply call isHuman(address) on the contract. In PoH v2 there will also be a soulbound id for each human (when re/registering the requester always have to point to the soulbound id corresponding to him, otherwise would be challenged). 1 human <-> 1 wallet address <-> 1 soulbound id. This could be used as social recovery :thinking:

As a simple first PoC, using Alex’s GroupCurrencyToken I thought there could be a contract PoHTokenManager owning the PoH group token PoHGCT.

The idea would be that owner of a personal circles token should be registered on PoH in order to use that token as collateral.

PoHTokenManager could be both owner of the PoHGCT and the treasury. It would add/remove members depending and allow redeeming personal tokens from PoHGCT:

	address humanToken = hub.userToToken(walletOfHuman)
	require(humanToken != address(0x0))

	require(poh.isHuman(walletOfHuman) == false)

redeem(redeemer, token, amount)
	IGCT(gct).transfer_from(redeemer, address(0x0), amount)
	token.transfer(redeemer, amount)

Someone could exchange any tokens corresponding to people registered on PoH (mint using TokenAlice as collateral -> redeem TokenBob).

I’m not fully sure on how to best leverage circles mechanisms so looking forward to suggestions :slight_smile:


Thanks for this input, sounds like a great solution for combining PoH with Circles!

Would be nice to try it, the implementation should work like this, redeem is really clever, but I currently can’t evaluate potential risks with this swap possibility.
But the idea to enable this swap for PoH GCT is nice. Just I am not sure if the transfer_from will always work wrt. the allowances set. Would the PoHTokenManager have “unlimited” allowance or how would this work?

As for the other possibility you mentioned in the Telegram Chat, using addDelegateMembers this would translate to “the GCT trustee is a human”, but not all of her trustees. You addMember solution looks better to me, the “delegate” solution could be a scalability “boost” if necessary.

Added from the Telegram Chat:

There is a problem with minting if a user lists several times as there is no check on minting if the user “is still human”.

Possible Solutions (Martin)

  • configure the group currency in such a way that only the owner is allowed to mint (onlyOwner flag in GCT)
  • the user needs to call mint in the token manager contract which again checkes wether the user is still a member and call mint on the GCT

Just another small note: @andrei - in Circles we use Safes (Gnosis Safe) as a wallet for users. I assume this is not a problem for PoH or do you expect the wallet to be an EOA? E.g. do you need the ability to directly sign with this address (obviously a smart contract can not do that directly)

Note: Some remarks on the PoH group currency found their way into the CRC V2 discussion (see Proposal to update the Hub contract (Circles v2) - #11 by jaensen)

Picking up a question from Alex in Proposal to update the Hub contract (Circles v2) - #14 by alculexum

To quote Andrei:

So we’ve got some facts that we can rely on:

  • One CRC safe is always mapped to exactly one CRC token (so we can use the terms Token and Safe interchangeably for this purpose)
  • Every (PoH) human got a soul-id that never changes and always identifies one individual
  • We can lookup if a safe belongs to a PoH human by calling isHuman(safeAddress)

Also I make the assumptions that (@andrei is that right for v2 of PoH?)

  • … we can look up a soul-id by a safe address
  • … we can look up a safe address by soul-id

So I guess what we want, is a group currency that accepts all tokens of any PoH human as collateral.

I image the process as following:

  1. a token is added to the GC
  2. we retrieve the soul-id via the path “token → safe → soul-id” and store it together with the collateral token address
  3. The token/safe is now a valid collateral/member.

So far so good. The problem appears when a user looses access to the safe or starts acting maliciously by creating multiple UBI safes and then wants to add the associated tokens as collateral.

PoH allows to assign a new wallet address to a soul-id after the user successfully re-validates that he/she is the person that is identified by the soul-id. Since the GC accepts all tokens that lead to a soul-id (using the previously described path) it would also accept all fake/bot tokens as long as the user goes trough the effort of re-validating for each fake safe/token. So there could be 100 parallel CRC tokens (all minting for e.g. 1 y) and the user just has to rotate the safe address by verifying a hundred times and re-registering every token at GC.

The easy way to prevent this would be, to let the user only add one token per soul-id but the person would then be locked out forever if he/she looses access to the safe.

The other way (that requires a change in the CRC contracts - see other thread) is to add a creation timestamp- and predecessor-field to the token. With these changes the process would look like the following:

  1. a token is added to the GC
  2. we retrieve the soul-id via the path “token → safe → soul-id” and store it together with the collateral token address
  3. The token/safe is now a valid collateral/member.
  4. User looses access
  5. 3 month go by and the original token is automatically stopped
  6. User creates a new token and sets the address of the old token as ‘predecessor’
  7. User registers again at the GC
  8. GC retrieves the soul-id via the path “token → safe → soul-id”
  9. GC sees that there is already a registered token for the same soul-id
  10. GC checks if the old token is stopped
  11. GC checks if the new token is the successor of the old token
  12. GC checks if the new token was created after the old was stopped
  13. User is member again and can use the new token as collateral in the GC

P.S.: As of writing I see that a user would need to wait three month before a new token can be safely created which is not ideal :confused:

But couldn’t I create a new Token on my own, so eg. you are in a GC (and I know it) and you lose interest in Circles and your Token is stopped, can’t I just create a new Token with your Token as a predecessor and so “reuse” your Soul-ID?

For the 3 months there could be an optional user assignment who can stop my Token? So I can nominate a Safe that can stop my Token (with one week or something quite short as veto period) and then the 3 months would become one week?

1 Like

I don’t think so because I would need to update my wallet address in PoH so that it points to you safe instead. But you could say that your token is the successor of my token. It wouldn’t do any harm tough (except for the confusion).

So if my token is the successor of your token, I could swap my new token for GC?

No because if you would try to do that then the process would be as follows:

  1. my token is deactivated because of inactivity
  2. you create a new token and set my old token as predecessor
  3. you register the token at the GC
  4. the GC retrieves the soul-id via the path “token → safe → soul-id”
  5. a) either your token doesn’t resolve to a soul-id
    b) or your token resolves to a different soul-id

In both cases the GC can detect that your token is not a valid successor of my token.
It would be if I previously changed my soul-id → safe mapping to your safe address which I wouldn’t do :wink:

However, everyone can claim to have the successor of a specific token because its just a field that can be set in the token constructor. So there could be more than one token claiming to be the successor of some other token. The field value alone cannot be trusted and there need to be other means to verify the claim.