Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On the architechture of Circles contracts #23

Closed
MrChico opened this issue Dec 5, 2018 · 6 comments
Closed

On the architechture of Circles contracts #23

MrChico opened this issue Dec 5, 2018 · 6 comments

Comments

@MrChico
Copy link
Contributor

MrChico commented Dec 5, 2018

Architecture comparison

Here is a break down of differences between the contracts in this repo and the old "contract sketches" and my thoughts generally on what the architecture for the Circles contracts should look like.
The minimal functionality these architectures are trying to achieve is a system of personal currencies and a way to exchange these currencies (transitive transfer) based on a network of trust.
##Circles token contract
Both approaches center around an extended ERC20 contract with a couple of added features. In this repo, this contract is called TimeIssuedToken and in the old sketches it is known as CirclesToken. Since these contracts are very similar, I will sometimes refer to the "archetype" of this contract as a PersonalToken

Similarities

  • The token specifies an address, a designated person that we should understand of the owner / source of the token. This makes it a personal token.
  • There is a minting function which continuously increases the balance of the person based on the time elapsed since the function was last called. The rate of tokens minted over time is decided by another variable issuanceRate a.k.a. factor. The minting function is automatically triggered whenever a transfer occurs.

Differences

  • The TimeIssuedToken has a quirky way of referencing the balance of the person as totalSupply - elsewhere instead of through the balances mapping.
  • The math in TimeIssuedToken is not overflow safe (see Add overflow protection #10)
  • The person of the TimeIssuedToken seems to be intended to be a Person proxy contract, rather than an end user.
  • The CirclesToken has an owner address specified, which is exempt from requiring approval from token holders to move tokens on their behalf (implemented as an added clause in transferFrom). The owner of all CirclesToken contracts is intended to be the CirclesHub contract.

Transitive transfer functionality

Besides the personal currency contracts, a key feature of Circles is the ability to do transitive transfers in the web of trust.

Differences

Here approaches start to differ a lot.
The old sketches rely on a single CirclesHub.sol to keep track of trust relations and execute transitive transfer using its special authority in the CirclesTokens. Here a trust relation is specified by a limit, a value and a time lastTouched. We should understand this relation as specifying a daily limit of their own tokens that the truster is willing to substitute for the trustees tokens. Circle users join the network, specify their trust relations and make transitiveTransfers all using this one contract. Trust relations are from a person to a currency, or from a person to a validator (which we can regard as a person). The transitive transfer supports transfers facilitated by validators.

This repo takes a different approach. For each user, there is a Person.sol contract, which has an owner (the user). The owner can select tokens that it is willing to accept as input and output in an exchange. If Bob trusts Alice (here meaning that Bob has specified Alice's token as an valid "exchange input", and his own tokens as a valid "exchange output"), Alice can perform a swap by first approving Bobs Person contract for transferFroms of AliceTokens by calling ExchangeApprove and then call the ExchangeTransfer function of Bobs Person contract. The two actions must be performed in the same transaction, as anyone can call the ExchangeTransfer function after Alice has approved Bobs Personcontract to transact on her behalf.
By this method, Alice can make one transitive exchange, i.e. transfer A -> B -> C.
If a longer transitive transaction is needed, then they can be performed as a series of ExchangeTransfers, executed by the sender.

My take

I prefer the first architecture, the "old sketch" model, for a number of reasons:

  • I prefer having the person of the PersonalToken be an arbitrary address, and not necessarily a proxy contract. The proxy solution is more complex, both from a smart contract perspective and for the user to deal with.
  • I prefer having one central point where trust relations are kept. To gather data about the trust graph in the version where everyone states their trust relations in their ownPerson contract, the trust graph is scattered among all these contracts.
  • It is my opinion that the ExchangeTransfer procedure is a lot more complicated than the swapping of tokens that happens in CirclesHubs transferThrough function. The latter also provides an arbitrary amount of hops while the former only allows for one transitive hop. In order to facilitate a longer transitive transfer with the ExchangeTransfer method, one would essentially need to write a function that performs the logic of transferThrough anyway.
  • Having a central Hub that is "in charge" of the PersonalToken contracts gives a clear entry point to implement monetary policy. If we want to be able to change the issuance rate or the starting balance, or implement demurrage, we will need a managing entity that has special privileges in the PersonalTokens. I think making CirclesHub be this contract is an easy change.
  • My critique of our old sketches right now is that they are somewhat opaque as much of the functionality is hidden in its library contracts, and in a kind of "quick and dirty" state.
  • The ExchangeTransfer mechanism has an upside in that it allows people to automatically swap tokens other than their own. I.e. if Bob holds 10 EveCoins, then Alice can make a transitive transfer to Carol passing through Bob, but now exchanging AliceCoin for EveCoin which she sends to Carol. It's a slightly more general functionality than the old sketches.

Ways forward:

Of course, I am slightly biased and I would be happy to hear @Jake-Gillberg's comments on the two different approaches. But if I were to go ahead with this, I would modify the old contracts sketches and update them with the following things:

  • The ds libraries are out of date, and a lot of complexity is hidden by relying on their functionality. I think there is still motivation to use them in some scenarios, like logging, but I think for the sake of understandability and security, we should not sweep complexity under the carpet. The transferThrough function looks a little bit gnarly right now and can be simplified a lot.
  • The CirclesToken should ask the CirclesHub what the issuance rate is so that we can update it centrally.
  • The CirclesHub should be given a (replaceable) owner/admin, that can modify certain system parameters, like the issuance rate, starting balance, and whether there is demurrage in place.
  • A lot more tests. And in particular of cases that you DONT want to work!
  • Since the CirclesHub essentially acts as an operator, it can adhere to some of the conventions in erc777 (although I don't like the calling hooks very much, so I would skip those).
    Optionally, we can also make it so that these contracts can be interacted with signed messages, instead of ethereum transactions. I think this is out of scope for the MVP though.
@Jake-Gillberg
Copy link
Contributor

Alice can perform a swap by first approving Bobs Person contract for transferFroms of AliceTokens by calling ExchangeApprove and then call the ExchangeTransfer function of Bobs Person contract.

Slight clarification here. I think the function naming is a bit confusing, but I couldn't think of better names. One doesn't need to call ExchangeApprove before an ExchangeTransfer. ExchangeApprove is there in case you want to spend transitively to a contract. With ExchangeApprove you can exchange AToken for BToken spent at contractC without having to first put BToken in your account, and then calling approve( contractC....

@Jake-Gillberg
Copy link
Contributor

The CirclesToken has an owner address specified, which is exempt from requiring approval from token holders to move tokens on their behalf (implemented as an added clause in transferFrom). The owner of all CirclesToken contracts is intended to be the CirclesHub contract... Having a central Hub that is "in charge" of the PersonalToken contracts gives a clear entry point to implement monetary policy. If we want to be able to change the issuance rate or the starting balance, or implement demurrage, we will need a managing entity that has special privileges in the PersonalTokens. I think making CirclesHub be this contract is an easy change.

I think this is the biggest difference that needs to be addressed. Personally, I don't like having this sort of ambient authority as a part of the contracts. I am of the opinion that monetary-policy type things like issuance rate changes and demurage falling to the central locus of authority in the contracts strays from the mission of "connected personal currencies". Is it really a personal currency if an organization can destroy it (i.e. through infinite issuance or infinite demurage) at any point? I think that these sorts of changes could be implemented on the "layer 2" level of the Circles application, with consent of the user. So maybe a user wants to change their issuance rate to near infinity. IMO we should allow this, but no longer call that currency "Circles". (It is removed from the circles-app registry)

@ana0
Copy link
Contributor

ana0 commented Dec 20, 2018

I've been stewing too on to what extent the hub architecture can be considered permissioned, and what it makes sense to allow users to do .. aka, to what extent does Circles need to allow users to defend against an adversarial hub?

My proposal would be to have a hub that stores issuanceRate and demurrageRate, the user cannot change these except by participating in a community governance process - but they can fork the hub. We can even create a hubFactory (where anyone can deploy a hub) and a switchHub function, permitted by onlyOwner on each personal currency. True transitive transactions are only permissible between users who share the same hub, though users who don't share the same hub can still transact with all normal erc20 methods.

A system that allows concentration of power is fine if it's also easy to change where power is concentrated.

@Jake-Gillberg
Copy link
Contributor

@ana0 I like this idea. What, are you thinking, is the difference between a Hub and a Validator?

If these are synonymous, I think this changes the flavor of what a validator is (not necessarily in a bad way). Before, a user being validated by multiple "validators" made sense. I don't see how it would make sense to have a user subscribed to multiple hubs.

@JuliointheStudio
Copy link

In practice, at the beginning the idea is to have workshops where people who want can be properly onboarded into the system, where we explain our vision and intentions and we facilitate to let them think of how to design their specific community governance hub (which could be the people who attend the workshop but could be wider). Ideally we want these people to then go on and try to play with the app and add other people in their specific collectives, kinship groups, social organizations, etc.

At the very start, from what Ed says, we would be the only validator. In my opinion, we need a strategy to transition from being the sole validator to facilitating governance processes where there can be a hub/group (defined itself by its interests, values and relationships) who can decide how will they change their issuance rates accordingly. If you are an individual and do not belong to any group, then they are free to do what they please. But there should be a way of letting others know that these people gave themselves one million coins and no groups who they decided to have these rates with.

So the idea is to first try to nurture the commons into being by us actively trying to bring communities together and then have them decide over how they want to govern their money system. In terms of smart contracts, I am not sure if this means moving from Martin to Jakes' architecture. Is there a way to merge the best of both worlds?

What we want to avoid is this super abstract problem of having one issuance rate for the whole world. We need plurality grounded locally, not a universality which is abstracted from each place.

@ana0
Copy link
Contributor

ana0 commented Jan 6, 2019

@Jake-Gillberg I've always thought hub and validator are separate roles. Agree it makes sense for a user to be trusted by many validators but have only one hub.

In the old contracts, validator is nothing but an address that is signed up to be a validator, and stores trust relationships like any other. A hub has many possible validators, but otherwise this section of the code seems a lil incomplete/in need of further though. Personally, I like open validators, but think they might need to have reputation. Unclear to me at the moment whether validator reputation could be offchain, but I think maybe yes.

@JuliointheStudio I agree we'll need a transition plan to move away from being the only validator - and I think maybe also from being the only hub, but I think these are probably best kept as different roles.

@ana0 ana0 closed this as completed Apr 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants