Giter Site home page Giter Site logo

andytudhope / recollections Goto Github PK

View Code? Open in Web Editor NEW
19.0 6.0 6.0 353 KB

A description of how to curate information optimally in the absence of a central authority

License: Mozilla Public License 2.0

Solidity 84.40% Makefile 0.52% Python 14.00% Dockerfile 1.08%

recollections's Introduction

Recollections

The beauty of Ethereum to me, can be summed up simply:

By deploying immutable contracts to a shared, public computational surface - contracts whose data can be read deterministically by anyone with access to the internet - we can encode idealism into the way we run society.

What's more, what's different this time, is that the idealism exists independently of the people who encoded it, who inevitably become corrupted, because we are all human. And to be human is to be corruptible, in some very real and simple way.

My idealism arises out of cryptoeconomics, which is not about egalitarianism, but about designing systems with no central point of control. Decentralisation is the goal, egalitarianism is a great success metric. But not the other way around, because egalitarianism is not something for which we can reasonably optimise.

  1. Watch the tech talk for a high-level overview here (now a bit outdated).

  2. Play with a live ObservableHQ notebook here.

  3. Read the contract in this repo.

  4. Look at the evolving designs.

DApp Store SNT Ranking

Summary

In order to fulfill one of our whitepaper promises, we need a mechanism in the Status DApp Store that uses SNT to curate DApps. While this is not the only mechanism we will make available to users to find interesting and relevant DApps, it is one of the most important, both for SNT utility and because economic mechanisms are at the heart of how we buidl sustainable peer-to-peer networks.

Abstract

We propose using an exponential bonded curve, which operates only on downvotes, to implement a simple ranking game. It is the most radical market feasible: the more SNT a DApp stakes, the higher it ranks, with one caveat. The more SNT staked, the cheaper it is for the community to move that DApp down the rankings.

Motivation

Token Curated Registries, and other bonded curve implementations try to incentivise the user with some kind of fungible reward token (often with governance rights/requirements attached to it) in order to decentralise the curation of interesting information. However, this creates mental overhead for users (who must manage multiple tokens, all with different on-chain transactions required) and is unlikely to see high adoption.

Making the ranking algorithm transparent - and giving users an ability to affect it at a small cost to them should they feel very strongly - is potentially a more effective way to achieve decentralised curation.

User Stories

An effective economic ranking mechanism, selected with the option Ranked by SNT (one of many filters), answers the following user stories from our swarm doc.

  1. I want to be confident a DApp is usable / not a scam.
    1. Having an economic mechanism ensures that the DApps which rank highly quite literally are those providing the "most value" to the community. This is because SNT staked to rank is locked out of circulation, meaning each SNT stakeholder's own holding of SNT should increase in value. Coincidentally, the more SNT staked in total in the store, the stronger the assurance that any given DApp which ranks highly is useful and not a scam.
  2. As an SNT stakeholder, I would like to signal using SNT that I find a listing useful.
    1. Achieved by "upvoting" in the UI. Importantly, upvotes do not effect the bonded curve, users simply donate SNT 1-1 directly to the DApp's balance.
  3. As an SNT stakeholder, I would like to signal using SNT that I find a listing to be not useful/poor quality/etc.
    1. Achieved, on an increasingly cheap basis the more well-resourced a DApp is, by "downvoting" in the UI. Uses an exponential bonded curve to mint downvotes.
  4. As a DApp developer, I want to be able to propose/vote my DApp for inclusion.
    1. Anybody can submit a DApp for inclusion and "vote" on it by calling upvote and adding SNT to its balance.

UI Mock-ups

Designs being worked on here.

  1. The "free complain" feature in the Downvote screen is not included for now.
  2. The "Add a DApp" screen (ideally, imo, opened from a fab + button on the home screen) is not included either. We need to figure out if any additional metadata is required before we can design that screen.

Specification

Constructor

Instantiates the MiniMe (or EIP20) interface so that the contract can receive and send tokens as necessary.

Constants

  1. uint total == 3470483788 - total SNT in circulation.
  2. uint ceiling - most influential parameter for shape of curves (votes minted per DApp and cost to effect a DApp by some set percent for users). Potentially controlled dynamically by governance mechanism.
  3. uint max = (total * ceiling)/10000 - max SNT that any one DApp can stake.

Data Struct

  1. address developer - the developer of the DApp, used to send SNT to when downvote or withdraw is called.
  2. bytes32 id - a unique identifier for each DApp, potentially with other metadata associated with it, hence the bytes32.
  3. uint balance - keep track of the total staked on each DApp.
  4. uint rate = 1 - (balance/max) - used to calculate available and v_minted.
  5. uint available = balance * rate - amount of SNT staked a developer can earn back. NB: this is equivalent to the cost of all downvotes.
  6. uint v_minted = available ** (1/rate) - total downvotes that are "minted".
  7. uint v_cast - keep track of the downvotes already cast.
  8. uint e_balance = balance - ((v_cast/(1/rate))*(available/v_minted))- the Effective Balance each DApp is actually ranked by in the UI.

Methods

  1. createData
    1. params: (bytes32 _id, uint _amount)

Accepts some nominal amount of tokens (> 0) and creates a new Data struct with the _id passed to it, setting the new struct's balance and using that to calculate balance, rate, available, v_minted_ and e_balance (which is == balance at first).

Emit event containing new e_balance.

  1. upvoteEffect
    1. params: (bytes32 _id, uint _amount)

Mock add _amount to balance, calculate mRate, mAvailable, mVMinted, and mEBalance. Subtract this from the actual e_balance and return the difference to be displayed in the UI to show the user what effect their "donation" will have when upvoting.

  1. upvote
    1. params:(bytes32 _id, uint _amount)

Transfer SNT directly to the contract, which means donating directly to the DApp's balance, no curve used, no money to the developer. Then recalculate rate, available, v_minted and e_balance.

Emit event containing new e_balance.

  1. downvoteCost
    1. params: (bytes32 _id, uint _percent_down)

Specifying the _percent_down allows us to calculate the cost without integrating anything. Calculate the v_required to effect the DApp by the specified % and the return cost for use in the UI.

NOTE: it's likely best to poll this method fairly often from Status and store the approx cost locally for a quicker, smoother UI and then double check that it's correct before the user confirms the transaction.

  1. downvote
    1. params: (bytes32 _id, uint _percent_down)

Send SNT from user directly to developer in order to downvote. Call downvoteCost to get balance_down_by, votes_required and cost.

Add v_required to v_cast, recalculate e_balance, and subtract cost from available so that withdraw works correctly.

Emit event containing new e_balance.

  1. withdraw
    1. params: (bytes32 _id, uint _amount)

Allow developers to reduce thier stake/exit the store provided that _amount <= available. Recalculate balance, rate, available and v_minted. If v_cast > v_minted, then set them equal so the maths is future-proof, and recalculate e_balance.

Emit event containing new e_balance.

  1. ??? updateCeiling
    1. params: (uint _newCeiling)

Potentially a simple multisig governance mechanism to change the ceiling dynamically in response to demand? It's not trivial to add though, because you would need to update most of the fields in each Data struct in storage, which could exceed the gas limit if there are large numbers of DApps in the store...

  1. receiveApproval
    1. params: (address _from, uint256 _amount, address _token, bytes _data)

Included so that users need only sign one transaction when creating a DApp, upvoting or downvoting. Checks that the token (SNT), sender, and data are correct. Decodes the _data using abiDecodeRegister, checks the amount is correct and figures out which of the three "payable" functions (createDApp, upvote, and downvote) is being called by looking at the signature.

  1. abiDecodeRegister
    1. params: (bytes _data)

Helps decode the data passed to receiveApproval using assembly magic.

Notes

What metadata we need to identify each DApp uniquely is still a topic for research and discussion. Ideally, we want these contracts to be used for curation in general, not necessarily just for DApps, so it needs to be as general as possible. For now, only an id in Data is included.

Potential Attacks

  1. Sybil resistance?
    1. If I create a lot of accounts for one DApp, will that increase it's ranking?
    2. If I vote for one DApp from lots of different accounts, in small amounts, rather than in 1 big amount from a single account, what effect does it have?

Creating many accounts for one DApp is not possible - each DApp is uniquely identified and by its id and ranked only by the amount of SNT staked on it. In the same way, there is no quadratic effect in this set up, so staking for a DApp from lots of different accounts in small amounts has no greater/lesser effect on its ranking than staking 1 large amount from a single account.

  1. Incentives to stake bad DApps and "force" the community to spend SNT to downvote?

Remember, you never get back more SNT than you stake, so this is also economically sub-optimal. In addition, there will be a free "complaint" feature as part of the "downvote" screen. There is an important difference between "contractual" and "social" (i.e. the Status UI) reality. Status reserves the right to remove from our UI any DApp that actively violates our principles, though anyone else is free to fork the software and implement different social/UI rules for the same contractual reality. This protects even further against any incentive to submit bad/damaging DApps.

However, at the beginning of the Store, this is an attack vector: ranking highly requires but a small stake, and this could conceivably result in a successful, cheap hype campaign. The "complain" feature is meant as social protection against this (though it depends on the responsiveness of the Status team, which is not optimal).

  1. Stake a damaging DApp, force some downvotes, and then withdraw my stake?

You can still never earn back quite as much as you initially staked, enforced by the condition in the withdraw function: require(_amount <= available).

  1. What is left in the store when a DApp withdraws the SNT it staked?

Simply balance - available, i.e. some small amount of SNT not available to be withdrawn.

  1. The majority of the cost to downvote comes from the last ~5%, so moving a DApp down 80%, say, is not that expensive relative to the effect you have.

Yeah, and I'm not sure that playing with the curve will mitigate this. However, another (implemented) solution would be just to lower the second bound in the require to - say 5/100 - i.e. you can only affect a ranking by between 1 and 5% with any given vote. More research needs to be done on exactly what the optimal bound there really is (though I'm not sure how to even define "optimal" for this).

  1. I'm worried about the behaviour of the graph for higher v_cast - things get very expensive.

This is a result of how the data and sliders are structured. If you mock a high v_cast, then the graph, trying to show the effect of that on DApps with lower balances naturally spikes for balance < v_cast, which I have tried to exclude as best as possible.

Rationale

This is a simple economic mechanism that

  1. does not place high mental overheads on users and could conceivably be understood by a wider and non-technical audience and
  2. does not require a lot of screen real estate (important on mobile). All that is required is a balance for each DApp and up/downvote carrots to it's right or left, a pattern already well understood on sites like Reddit etc.

Moreover, having SNT is not required to see (and benefit from) a well-curated list of DApps; only if you want to effect the rankings on that list do you require tokens, which also makes the UX considerably easier for non-technical users.

From the perspective of DApp Developers - they must still spend some capital to rank well, just as they currently do with SEO and AdWords etc., but they stand to earn most of that back if the community votes on their product/service, and they can withdraw their stake at any time. The algorithm is entirely transparent and they know where they stand and why at all times.

Copyright

Copyright and related rights for this specification waived via CC0.

recollections's People

Contributors

andytudhope avatar bakasura980 avatar jacqueswww avatar richard-ramos avatar vyomshm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

recollections's Issues

Extend barebones to test to cover as many cases as we can

Working off this commit: 68c32ce

Add any and all test cases you can think of. We need to test everything in this contract as thoroughly as possible: whether the rate, available, votes_minted and effective_balance are what we expect at all times, whether SNT goes to the correct place (either the contract for upvotes or the developer for downvotes), whether the ceiling functions as intended, whether all the asserts work as intended and so on.

@jacqueswww has recommended https://hypothesis.works

The main reasons for testing in python and not javascript, to put it bluntly, are:

  1. Floating point BS in JS
  2. Readability

Build a Simple Playground For Optimising The Curve

The latest instalment of DApp curation using a simple bonded curve can be found here. I need to update the contract itself to reflect the latest changes and research, but we can parallelize this, and create a bounty simply for a better playground in which to experiment with curves and constants.

The latest spreadsheet that sets out exactly how the mechanism works can be found here. Look on the 3 sheet, entitled Playground Wireframe for a sense of what to build here. Please play with it yourself first by inserting different values for:

  1. The exponent (and therefore the shape of the curve). Satisfy yourself that 1.6 is well chosen, that there is an inflection point i.t.o. the cost to move by 1 SNT at 1.5 (so we can't go below) and that any other value between 1.6 and 2 doesn't give us as high an amountAvailable.
  2. The % of negative votes (or positive votes). Play with this until you get a sense of what % of votes have to have been cast for the cost to the user to move the DApp 1 SNT down in the store to become "significant" (remembering that "significant" here not only refers to how much it actually costs, but also the effect of loosing 1 SNT as compared to the amount a DApp has staked, i.e. the more they have staked, the less significant loosing 1 SNT is).

Requirements

Now, this bounty is for a demo environment of your choice in which we can:

  1. Play with different values for the exponent and see their effect on the cost paid by the user and the amountAvailable (hence what the DApp can receive back) in real time. Extra points if we can play with entirely different curves.
  2. Have a slider for the % of negative votes cast vs votes minted (and the % of total votes cast vs votes minted) which we can use to show what the real cost of voting is for different amounts staked, and different numbers of votes cast.
  3. A simple calculator for "if I spend X SNT right now (with A SNT staked and B votes already cast it will move the DApp Y SNT in the store". It's easier just to look at the functional wireframe in the spreadsheet.

This idea comes from a tweet from @okwme: https://twitter.com/billyrennekamp/status/1064189839543799816 I'm not sure it asks for exactly what is in that tweet, but hopefully he can comment on some good requirements/deliverables here too.

Maybe the most meta thing you've ever seen. Much wow.

Main bounty in SNT is to disprove the thesis in this repo. Yes, it is the same as the first interval in the curve I have been working with. So meta...

Out of band bounties to help optimise the parameters curve_factor and snt_percent.

A (somewhat) formal proof is also produced below. The graph in the spreadsheet does hint at this, but the insight that curve_factor can be calculated dynamically in the contract based only on the relevant balances, to always be a max x-value in terms of where cost to mint vs tokens mint intersects, is a big one.

That intersection is the point at which it becomes increasingly cheaper to have a bigger and bigger influence on the ranking, and you want to make sure it is as large as possible in order to make sure that your information store lives long and prospers.

Vyper bytecode size issues

I am glad to report that the upcoming vyper release (0.1.0b11) will prevent the ballooning problem this repo had with approveandcallback. So I am opening an issue to bump the vyper version so long ;)

Implement the spec provided in the README in Vyper

Put me out of my Solidity misery by implementing the spec provided in Vyper.

a.k.a.

Lead us not into SafeMath, and deliver us from inheritance,
For thine is the overflow checking, the signed integers and strong typing,
Now and forever,
Amen

Research Which Exponent Library is Safest and Cheapest

The next step in writing this contract is to swap out all the current mathematical operations for safer ones that actually work in Solidity.

The core piece of work here is to figure out the best and cheapest way to calculate v_minted = d.available ** (1/d.rate) given that there is no floating point arithmetic in Solidity. A fractional exponent is the equivalent of a square root, so we need a gas-efficient library that will help us achieve this. Look into

https://github.com/dydxprotocol/protocol/blob/master/contracts/lib/Exponent.sol

and

https://github.com/extraterrestrial-tech/fixidity

to see which one is cheaper, as well as looking for other alternatives. Bancor has an interesting approach too: https://github.com/bogatyy/bancor/blob/master/solidity/BancorFormula.sol#L270 but I suspect that, because our exponent is dynamic, using a static table is not going to be the solution here.

Other Resources

Babylonian method: https://ethereum.stackexchange.com/questions/2910/can-i-square-root-in-solidity

Taylor Series: https://en.wikipedia.org/wiki/Taylor_series

Newton-Raphson: https://ethereum.stackexchange.com/questions/38468/calculate-the-nth-root-of-an-arbitrary-uint-using-solidity?rq=1

Easter Egg: https://en.wikipedia.org/wiki/Fast_inverse_square_root

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.