eip-1417.md
1 --- 2 eip: 1417 3 title: Poll Standard 4 author: Chaitanya Potti (@chaitanyapotti), Partha Bhattacharya (@pb25193) 5 type: Standards Track 6 category: ERC 7 status: Draft 8 created: 2018-09-16 9 requires: 165, 1261 10 discussions-to: https://github.com/ethereum/EIPs/issues/1417 11 --- 12 13 ## Note to Readers 14 15 1. We have created a couple of implementations of polls for varied use cases. 16 Please refer to them [here](https://github.com/chaitanyapotti/Voting) 17 18 ## Simple Summary 19 20 A standard interface for Polls to be used with EIP-1261 (MVT). 21 22 ## Abstract 23 24 The following standard allows for the implementation of a standard API for polls to be used with MVTs (refer [EIP-1261](https://eips.ethereum.org/EIPS/eip-1261)). The standard provides basic functionality to vote, unvote, tally votes, get voter turnout, and a lot more. The poll standard attempts to modularize blockchain voting by breaking down a poll into 4 crucial building blocks: voterbase qualification, vote weight calculation, vote consequences, and vote tallying. By creating a common interface for polls that have different kinds of building blocks, the poll standard makes it possible to make interactive front end applications which can seamlessly get data from a poll contract in order to bring transparency into consensus and decision making on the blockchain. 25 26 We considered the usage of polls with MVTs because MVTs serve as a permissioning mechanism. The manual permissioning of polls allows for vote weightage functions to take up several shapes and forms. Hence the voterbase function applies several logical checks on the vote sender to confirm that they are member(see EIP 1261) of a certain entity or combination of entities. For the specification of the nature of voting, we define the vote weight function. The vote weight function decides how much of vote share each voter will receive and this can be based on several criteria, some of which are listed below in this article. There are certain kinds of polls that enforce certain consequences on the voter, for example a poll may require a voter to lock in a certain amount of tokens, or require the voter to pay a small fee. These on-chain consequences can be coded into the consequence module of the poll standard. Finally, the last module is where the votes are added. A ballot for each candidate is updated whenever relevant, depending on the vote value, and the corresponding NoV count(number of voters). This module is common for most polls, and is the most straightforward. Polls may be time bound, ie. having a finish time, after which no votes are recorded, or be unbound, such that there is no finish time. The following are some examples of specific polls which leverage the flexibility of the poll standard, and it is possible to come up with several others: 27 28 - Plurality Voting: The simplest form of voting is when you want all eligible voters to have one vote per person. This is the simplest to code, as the vote weight is 1, and there is no vote consequence. The only relevant module here is the voterbase, which can be categorized by one or more MVT contracts. 29 - Token proportional voting: This kind of a poll is actually possible without the use of a voterbase function, because the vote weight function having token proportionality automatically rules out addresses which don't hold the appropriate ERC - 20/ ERC - 777 token. However the voterbase function may be leveraged to further permission the system and give voting rights only to a fixed subset of token holders. 30 - Capped Token Proportional Voting: This is a modified version of the previous example, where each voter is given proportional vote share only until a certain limit of token ownership. After exceeding that limit, holding more coins does not add more vote share. This format leverages the voterbase module effectively, disallowing people from spreading their coins across multiple addresses by allowing the admin to control which addresses can vote. 31 - Delegated Voting: Certain polls may allow voters to delegate their votes to other voters. This is known as delegated voting or liquid democracy. For such a poll, a complicated vote weight function is needed, and a data structure concerning the voterbase is also required. A consequence of voting here would be that a user cannot delegate, and a consequence of delegating is that a user cannot vote. Sample implementation of polls contains an example of this vote scheme. 32 - Karma Based Voting: A certain form of poll may be based on weightage from digital respect. This digital respect would be like a simple upvote from one member of voterbase to another. A mapping of mappings along with an appropriate vote weight function can serve this purpose. Sample implementation has an example. 33 - Quadratic voting: A system where each vote is associated with a fee, and the fee is proportional to the square of the vote weight that the voter wants. This can be designed by applying a vote weight based on the transaction message, and then charging a fee in the vote consequence module. 34 35 The poll standard is intended to be a smart contract standard that makes poll deployment flexible, transparent and accessible. 36 37 ## Motivation 38 39 A standard interface allows any user or applications to work with any Poll contract on Ethereum. We provide for simple ERC-1417 smart contracts. Additional applications are discussed below. 40 41 This standard is inspired by the lack of governance tools in the blockchain space. Whenever there is a consensus collection exercise, someone goes ahead and deploys some kind of poll, and there is no standard software for accessing the data on the poll. For an end user who is not a developer, this is a real problem. The poll, which might be fully transparent, appears to be completely opaque to a common user who does not understand blockchain. In order for developers to build applications for interacting with and accessing poll data, and for poll deployers to have ready application level support, there must be a standardization of poll interfaces. 42 43 This realization happened while conducting market research on DAICOs. The first ever DAICO, Abyss, had far from optimal user experience, and abysmal transparency. Since then, we have been working on a poll standard. During the process, we came across EIP 1202, the voting standard, and found that the discussion there had already diverged from our thoughts to an extent that it made sense to publish a separate proposal altogether. Some of the benefits brought by the poll standard - EIP 1417 aims to offer some additional benefits. 44 45 1. Modularization: EIP 1417 modularizes the code present in the poll standard into 4 major building blocks based on functionality. These are: voterbase logic, vote weight calculation, vote consequence processing, and tallying module. This makes it easy for developers to change parts of a poll without disrupting other parts, and also helps people understand better, code written in the same format by other people. 46 47 2. Permissioning: Permissioning is an important aspect of polls, and is missing in most poll proposals so far, on the blockchain. For some reason, most blockchain based polls seem to consider token holding as the only way to permission a poll. However this hampers flexibility, and hence our poll standard is leveraging EIP 1261 in order to clear the permissioning hurdle. Not only does it allow for more creative poll structures in terms of vote weightage, but even improves the flexibility in permissioning by allowing developers to combine several entities and read attributes from entities. 48 49 3. Flexibility: The vote weight module of the poll standard can be used effectively to design various kinds of poll contracts which function differently and are suited to different environments. Some examples are quadratic voting, karma voting, delegated voting, token based voting, and one person one vote systems. These schemes are possible due to the separation of voterbase creation and vote weight calculation. 50 51 4. NoV Counts: Several weighted polls have struggled to provide proper transparency because they only show the final result without enough granularity. This is because they do not store the number of voters that have voted for each proposal, and only store the total accrued vote for each option. EIP 1417 solves this by additionally recording number of voters(NoV) in each proposal. This NoV count is redundant in the case of one person one vote, but elsewhere, it is helpful in figuring out concentration of power. This ensures that malicious parties can be traced to a larger extent. 52 53 5. Event Logging: The poll standard logs an event during a successful vote, unsuccessful vote, and a successful unvote. This is being done so that in the event of a malicious admin removing real members or adding fake members, communities can build tools in order to perform advanced audits and simulate results in the absence of the malicious attack. Such advanced features are completely absent in most polls, and hence, it is hard to investigate such polls. 54 55 6. Pollscan.io: The Electus foundation is working on a web based application for accessing and interacting with poll data on the blockchain, it will be deployed on the domain name www.pollscan.io in the coming months. 56 57 All that being said, we are very excited to share our proposal with the community and open up to suggestions in this space. 58 59 ### Benefits 60 61 1. Building applications (pollscan.io) on top of a standardized voting interface enables transparency and encourage more DAO/DAICO's to act responsibly in terms of governance 62 2. Create Action contracts which take actions programmatically based on the result of a poll 63 3. Allow the compatibility with token standard such as [ERC-20](https://eips.ethereum.org/EIPS/eip-20) or (https://eips.ethereum.org/EIPS/eip-777)) and membership standard such as [EIP-1261](https://eips.ethereum.org/EIPS/eip-1261) 64 4. Flexibility allows for various voting schemes including but not limited to modern schemes such as PLCR Voting 65 66 ### Use-cases: 67 68 Polls are useful in any context of collective decision making, which include but aren't limited to: 69 70 1. Governing public resources, like ponds, playgrounds, streets etc 71 2. Maintaining fiscal policy in a transparent consensus driven manner 72 3. Governing crowdfunded projects - refer DAICO, Vitalik Buterin 73 4. Implementation of Futarchy 74 5. Decision making in political parties, and municipal corporations 75 6. Governing expenditure of a cryptocurrency community 76 77 ## Specification 78 79 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119. 80 81 **Every ERC-1417 compliant contract must implement the `ERC1417` and `ERC165` interfaces** (subject to "caveats" below): 82 83 ```solidity 84 /// @title ERC-1417 Poll Standard 85 /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1417.md 86 /// Note: the ERC-165 identifier for this interface is 0x4fad898b. 87 interface IPoll { 88 /// @dev This emits when a person tries to vote without permissions. Useful for auditing purposes. 89 /// E.g.: To prevent an admin to revoke permissions; calculate the result had they not been removed. 90 /// @param _from User who tried to vote 91 /// @param _to the index of the proposal he voted to 92 /// @param voteWeight the weight of his vote 93 event TriedToVote(address indexed _from, uint8 indexed _to, uint voteWeight); 94 95 /// @dev This emits when a person votes successfully 96 /// @param _from User who successfully voted 97 /// @param _to the index of the proposal he voted to 98 /// @param voteWeight the weight of his vote 99 event CastVote(address indexed _from, uint8 indexed _to, uint voteWeight); 100 101 /// @dev This emits when a person revokes his vote 102 /// @param _from User who successfully unvoted 103 /// @param _to the index of the proposal he unvoted 104 /// @param voteWeight the weight of his vote 105 event RevokedVote(address indexed _from, uint8 indexed _to, uint voteWeight); 106 107 /// @notice Handles the vote logic 108 /// @dev updates the appropriate data structures regarding the vote. 109 /// stores the proposalId against the user to allow for unvote 110 /// @param _proposalId the index of the proposal in the proposals array 111 function vote(uint8 _proposalId) external; 112 113 /// @notice Handles the unvote logic 114 /// @dev updates the appropriate data structures regarding the unvote 115 function revokeVote() external; 116 117 /// @notice gets the proposal names 118 /// @dev limit the proposal count to 32 (for practical reasons), loop and generate the proposal list 119 /// @return the list of names of proposals 120 function getProposals() external view returns (bytes32[]); 121 122 /// @notice returns a boolean specifying whether the user can vote 123 /// @dev implement logic to enable checks to determine whether the user can vote 124 /// if using eip-1261, use protocol addresses and interface (IERC1261) to enable checking with attributes 125 /// @param _to the person who can vote/not 126 /// @return a boolean as to whether the user can vote 127 function canVote(address _to) external view returns (bool); 128 129 /// @notice gets the vote weight of the proposalId 130 /// @dev returns the current cumulative vote weight of a proposal 131 /// @param _proposalId the index of the proposal in the proposals array 132 /// @return the cumulative vote weight of the specified proposal 133 function getVoteTally(uint _proposalId) external view returns (uint); 134 135 /// @notice gets the no. of voters who voted for the proposal 136 /// @dev use a struct to keep a track of voteWeights and voterCount 137 /// @param _proposalId the index of the proposal in the proposals array 138 /// @return the voter count of the people who voted for the specified proposal 139 function getVoterCount(uint _proposalId) external view returns (uint); 140 141 /// @notice calculates the vote weight associated with the person `_to` 142 /// @dev use appropriate logic to determine the vote weight of the individual 143 /// For sample implementations, refer to end of the eip 144 /// @param _to the person whose vote weight is being calculated 145 /// @return the vote weight of the individual 146 function calculateVoteWeight(address _to) external view returns (uint); 147 148 /// @notice gets the leading proposal at the current time 149 /// @dev calculate the leading proposal at the current time 150 /// For practical reasons, limit proposal count to 32. 151 /// @return the index of the proposal which is leading 152 function winningProposal() external view returns (uint8); 153 154 /// @notice gets the name of the poll e.g.: "Admin Election for Autumn 2018" 155 /// @dev Set the name in the constructor of the poll 156 /// @return the name of the poll 157 function getName() external view returns (bytes32); 158 159 /// @notice gets the type of the Poll e.g.: Token (XYZ) weighted poll 160 /// @dev Set the poll type in the constructor of the poll 161 /// @return the type of the poll 162 function getPollType() external view returns (bytes32); 163 164 /// @notice gets the logic to be used in a poll's `canVote` function 165 /// e.g.: "XYZ Token | US & China(attributes in erc-1261) | Developers(attributes in erc-1261)" 166 /// @dev Set the Voterbase logic in the constructor of the poll 167 /// @return the voterbase logic 168 function getVoterBaseLogic() external view returns (bytes32); 169 170 /// @notice gets the start time for the poll 171 /// @dev Set the start time in the constructor of the poll as Unix Standard Time 172 /// @return start time as Unix Standard Time 173 function getStartTime() external view returns (uint); 174 175 /// @notice gets the end time for the poll 176 /// @dev Set the end time in the constructor of the poll as Unix Time or specify duration in constructor 177 /// @return end time as Unix Standard Time 178 function getEndTime() external view returns (uint); 179 180 /// @notice returns the list of entity addresses (eip-1261) used for perimissioning purposes. 181 /// @dev addresses list can be used along with IERC1261 interface to define the logic inside `canVote()` function 182 /// @return the list of addresses of entities 183 function getProtocolAddresses() external view returns (address[]); 184 185 /// @notice gets the vote weight against all proposals 186 /// @dev limit the proposal count to 32 (for practical reasons), loop and generate the vote tally list 187 /// @return the list of vote weights against all proposals 188 function getVoteTallies() external view returns (uint[]); 189 190 /// @notice gets the no. of people who voted against all proposals 191 /// @dev limit the proposal count to 32 (for practical reasons), loop and generate the vote count list 192 /// @return the list of voter count against all proposals 193 function getVoterCounts() external view returns (uint[]); 194 195 /// @notice For single proposal polls, returns the total voterbase count. 196 /// For multi proposal polls, returns the total vote weight against all proposals 197 /// this is used to calculate the percentages for each proposal 198 /// @dev limit the proposal count to 32 (for practical reasons), loop and generate the voter base denominator 199 /// @return an integer which specifies the above mentioned amount 200 function getVoterBaseDenominator() external view returns (uint); 201 } 202 ``` 203 204 ### Caveats 205 206 The 0.4.24 Solidity interface grammar is not expressive enough to document the ERC-1417 standard. A contract which complies with ERC-1417 MUST also abide by the following: 207 208 - Solidity issue #3412: The above interfaces include explicit mutability guarantees for each function. Mutability guarantees are, in order weak to strong: `payable`, implicit nonpayable, `view`, and `pure`. Your implementation MUST meet the mutability guarantee in this interface and you MAY meet a stronger guarantee. For example, a `payable` function in this interface may be implemented as nonpayble (no state mutability specified) in your contract. We expect a later Solidity release will allow your stricter contract to inherit from this interface, but a workaround for version 0.4.24 is that you can edit this interface to add stricter mutability before inheriting from your contract. 209 - Solidity issue #2330: If a function is shown in this specification as `external` then a contract will be compliant if it uses `public` visibility. As a workaround for version 0.4.24, you can edit this interface to switch to `public` before inheriting from your contract. 210 211 _If a newer version of Solidity allows the caveats to be expressed in code, then this EIP MAY be updated and the caveats removed, such will be equivalent to the original specification._ 212 213 ## Rationale 214 215 As the poll standard is built with the intention of creating a system that allows for more transparency and accessibility of governance data, the design choices in the poll standard are driven by this motivator. In this section we go over some of the major design choices, and why these choices were made: 216 217 1. Event logging: The logic behind maintaining event logs in the cases of: 218 219 - Cast Vote 220 - Unvote 221 - Failed Vote 222 is to ensure that in the event of a manipulated voterbase, simple off chain checks can be performed to audit the integrity of the poll result. 223 224 2. No poll finish trigger: There was a consideration of adding functions in the poll which execute after completion of the poll to carry out some pre-decided logic. However this was deemed to be unnecessary - because such an action can be deployed in a separate contract which simply reads the result of a given poll, and against the spirit of modularity, because no actions can be created after the poll has been deployed. Also, such functions would not be able to combine the results of polls, and definitely would not fit into polls that do not have an end time. 225 226 3. Allow for unbound polls: The poll standard, unlike other voting standard proposals, does not force polls to have an end time. This becomes relevant in some cases where the purpose of a poll is to have a live register of ongoing consensus. Some other use cases come into picture when you want to deploy a set of action contracts which read from the poll, and want to be able to execute the action contract whenever a poll reaches a certain threshold, rather than waiting for the end of the poll. 227 228 4. Modularization: There have been opinions in the Ethereum community that there cannot exist a voting standard, because voting contracts can be of various types, and have several shapes and forms. However we disagree, and make the case that modularization is the solution. While different polls may need different logic, they all need consistent end points. All polls need to give out results along with headcounts, all polls should have event logs, all polls should be examinable with frontend tools, and so on. The poll standard is not a statement saying “all polls should be token based” or any such specific system. However the poll standard is a statement saying that all polls should have a common access and modification protocol - this will enable more apps to include governance without having to go through the trouble of making customers start using command line. 229 230 Having explained our rationale, we are looking forward to hearing from the community some thoughts on how this can be made more useful or powerful. 231 232 **Gas and Complexity** (regarding the enumeration for proposal count) 233 234 This specification contemplates implementations that contain a sample of 32 proposals (max up to blockgaslimit). If your application is able to grow and needs more than 32 proposals, then avoid using for/while loops in your code. These indicate your contract may be unable to scale and gas costs will rise over time without bound 235 236 **Privacy** 237 238 Personal information: The standard does not put any personal information on to the blockchain, so there is no compromise of privacy in that respect. 239 240 **Community Consensus** 241 242 We have been very inclusive in this process and invite anyone with questions or contributions into our discussion. However, this standard is written only to support the identified use cases which are listed herein. 243 244 ## Test Cases 245 246 Voting Standard includes test cases written using Truffle. 247 248 ## Implementations 249 250 Voting Standard -- a reference implementation 251 252 - MIT licensed, so you can freely use it for your projects 253 - Includes test cases 254 - Also available as a npm package - npm i electusvoting 255 256 ## References 257 258 **Standards** 259 260 - [EIP-20: ERC-20 Token Standard (a.k.a. ERC-20)](https://eips.ethereum.org/EIPS/eip-20) 261 - [EIP-165: Standard Interface Detection](https://eips.ethereum.org/EIPS/eip-165) 262 - [EIP-721: Non-Fungible Token Standard(a.k.a. ERC-721)](https://eips.ethereum.org/EIPS/eip-721) 263 - [ERC-1261 MV Token Standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1261.md) 264 - [RFC 2119 Key words for use in RFCs to Indicate Requirement Levels](https://www.ietf.org/rfc/rfc2119.txt) 265 266 **Issues** 267 268 1. The Original ERC-1417 Issue. https://github.com/ethereum/eips/issues/1417 269 1. Solidity Issue \#2330 -- Interface Functions are Axternal. https://github.com/ethereum/solidity/issues/2330 270 1. Solidity Issue \#3412 -- Implement Interface: Allow Stricter Mutability. https://github.com/ethereum/solidity/issues/3412 271 1. Solidity Issue \#3419 -- Interfaces Can't Inherit. https://github.com/ethereum/solidity/issues/3419 272 273 **Discussions** 274 275 1. ERC-1417 (announcement of first live discussion). https://github.com/ethereum/eips/issues/1417 276 277 **Voting Implementations and Other Projects** 278 279 - [Voting Implementations](https://github.com/chaitanyapotti/Voting) 280 281 ## Copyright 282 283 Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).